Bagaimana Linux membedakan antara file nyata dan tidak ada (misalnya: perangkat)?

28

Ini adalah pertanyaan tingkat rendah, dan saya mengerti bahwa itu mungkin bukan tempat terbaik untuk bertanya. Tapi, sepertinya lebih tepat daripada situs SE lainnya, jadi begini.

Saya tahu bahwa pada sistem file Linux, beberapa file benar - benar ada , misalnya: /usr/bin/bashadalah salah satu yang ada. Namun, (sejauh yang saya mengerti), beberapa juga tidak benar-benar ada seperti itu dan lebih maya file, misalnya: /dev/sda, /proc/cpuinfo, dll Pertanyaan saya adalah (mereka adalah dua, tapi terlalu erat kaitannya dengan menjadi pertanyaan terpisah):

  • Bagaimana cara kerja kernel Linux apakah file-file ini asli (dan karena itu membacanya dari disk) atau tidak ketika perintah baca (atau semacamnya) dikeluarkan?
  • Jika file tidak nyata: sebagai contoh, membaca dari /dev/randomakan mengembalikan data acak, dan membaca dari /dev/nullakan kembali EOF. Bagaimana cara kerjanya data apa yang harus dibaca dari file virtual ini (dan karenanya apa yang harus dilakukan ketika / jika data ditulis ke file virtual juga) - apakah ada semacam peta dengan pointer untuk memisahkan perintah baca / tulis yang sesuai untuk setiap file, atau bahkan untuk direktori virtual itu sendiri? Jadi, entri untuk /dev/nullhanya dapat mengembalikan EOF.
Joe
sumber
1
Ketika file dibuat, kernel mencatat jenisnya. File-file disk biasa kemudian diperlakukan secara berbeda dari symlink, perangkat blok, perangkat karakter, direktori, soket, FIFO, dll. Ini adalah tugas kernel untuk mengetahui.
Jonathan Leffler
lihat pria itu mencari mknod
Jasen
Ini seperti bertanya "bagaimana saklar lampu tahu apakah lampu dihidupkan?" Sakelar lampu bertugas memutuskan apakah lampu dihidupkan.
Lightness Races with Monica

Jawaban:

25

Jadi pada dasarnya ada dua jenis hal di sini:

  1. Sistem file normal, yang menyimpan file dalam direktori dengan data dan metadata, dengan cara yang biasa (termasuk tautan lunak, tautan keras, dan sebagainya). Ini sering, tetapi tidak selalu, didukung oleh perangkat blok untuk penyimpanan persisten (tmpf hanya hidup dalam RAM, tetapi sebaliknya identik dengan sistem file normal). Kata-kata semantik ini akrab; baca, tulis, ganti nama, dan sebagainya, semua bekerja seperti yang Anda harapkan.
  2. Sistem file virtual, dari berbagai jenis. /procdan /sysmerupakan contoh di sini, seperti halnya filesystem khusus FUSE seperti sshfsatau ifuse. Ada jauh lebih beragam dalam hal ini, karena sebenarnya mereka hanya merujuk pada sistem file dengan semantik yang dalam beberapa hal 'custom'. Jadi, ketika Anda membaca dari file di bawah /proc, Anda sebenarnya tidak mengakses sepotong data tertentu yang telah disimpan oleh orang lain yang menulisnya sebelumnya, seperti di bawah sistem file normal. Anda pada dasarnya melakukan panggilan kernel, meminta beberapa informasi yang dihasilkan saat itu juga. Dan kode ini dapat melakukan apa saja yang disukainya, karena itu hanya beberapa fungsi yang mengimplementasikan readsemantik. Dengan demikian, Anda memiliki perilaku aneh file di bawah /proc, seperti misalnya berpura-pura menjadi symlink ketika mereka tidak

Kuncinya adalah yang /devsebenarnya, biasanya, adalah yang pertama. Itu normal dalam distribusi modern untuk memiliki /devsesuatu seperti tmpfs, tetapi dalam sistem yang lebih tua, itu normal untuk memilikinya menjadi direktori polos pada disk, tanpa atribut khusus. Kuncinya adalah bahwa file-file di bawahnya /devadalah node perangkat, sejenis file khusus yang mirip dengan FIFO atau soket Unix; simpul perangkat memiliki nomor utama dan kecil, dan membaca atau menulisnya sedang melakukan panggilan ke driver kernel, seperti membaca atau menulis FIFO memanggil kernel untuk buffer output Anda dalam pipa. Driver ini dapat melakukan apa saja yang diinginkan, tetapi biasanya menyentuh perangkat keras entah bagaimana, misalnya untuk mengakses hard disk atau memutar suara di speaker.

Untuk menjawab pertanyaan awal:

  1. Ada dua pertanyaan yang relevan dengan apakah 'file itu ada' atau tidak; ini adalah apakah file node perangkat benar-benar ada, dan apakah kode kernel yang mendukungnya bermakna. Yang pertama diselesaikan seperti apa pun pada sistem file normal. Sistem modern menggunakan udevatau sesuatu seperti itu untuk menonton acara perangkat keras dan secara otomatis membuat dan menghancurkan node perangkat di bawahnya /dev. Tetapi sistem yang lebih lama, atau custom light builds, dapat memiliki semua node perangkat mereka secara harfiah pada disk, dibuat sebelumnya. Sementara itu, ketika Anda membaca file-file ini, Anda melakukan panggilan ke kode kernel yang ditentukan oleh nomor perangkat utama dan minor; jika ini tidak masuk akal (misalnya, Anda mencoba membaca perangkat blok yang tidak ada), Anda hanya akan mendapatkan beberapa jenis kesalahan I / O.

  2. Cara kerjanya apa kode kernel untuk memanggil file perangkat yang bervariasi. Untuk sistem file virtual seperti /proc, mereka mengimplementasikan sendiri readdan writefungsinya; kernel hanya memanggil kode itu tergantung pada titik mount yang mana, dan implementasi sistem file menangani sisanya. Untuk file perangkat, ini dikirim berdasarkan nomor perangkat utama dan kecil.

Tom Hunt
sumber
Jadi jika, katakanlah, sistem lama memiliki kekuatannya yang ditarik, file-file di /devdalamnya masih ada, tapi saya kira mereka akan dihapus ketika sistem dinyalakan?
Joe
2
Jika sistem lama (satu tanpa pembuatan perangkat dinamis) dimatikan, baik secara normal atau tidak normal, simpul perangkat akan tetap ada di disk seperti halnya file apa pun. Kemudian ketika bootup berikutnya terjadi, mereka juga akan tetap di disk, dan Anda bisa menggunakannya seperti biasa. Ini hanya dalam sistem modern bahwa sesuatu yang istimewa terjadi ketika membuat dan menghancurkan node perangkat.
Tom Hunt
Jadi sistem yang lebih modern tidak menggunakan tmpfsakan secara dinamis membuat dan menghapusnya sesuai kebutuhan, misalnya: bootup dan shutdown?
Joe
3
devtmpfs, sistem /devfile di Linux modern, mirip dengan tmpfs, tetapi memiliki beberapa perbedaan untuk didukung udev. (Kernel melakukan beberapa pembuatan simpul otomatis sendiri sebelum menyerahkannya udev, untuk membuat boot tidak terlalu rumit.) Dalam semua kasus ini, node perangkat hanya hidup dalam RAM dan dibuat dan dihancurkan secara dinamis sebagaimana perangkat keras membutuhkannya. Mungkin Anda juga bisa menggunakan udevpada-disk biasa /dev, tapi saya belum pernah melihat ini dilakukan dan sepertinya tidak ada alasan bagus untuk itu.
Tom Hunt
17

Berikut adalah daftar file /dev/sda1pada server Arch Linux saya yang hampir terbaru:

% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov  9 13:26 /dev/sda1

Jadi entri direktori /dev/untuk sdamemiliki nomor inode, 1294. Ini adalah file nyata pada disk.

Lihatlah di mana ukuran file biasanya muncul. "8, 1" muncul sebagai gantinya. Ini adalah nomor perangkat utama dan kecil. Perhatikan juga 'b' dalam izin file.

File /usr/include/ext2fs/ext2_fs.hini berisi struct (fragmen) C ini:

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
    __u16   i_mode;     /* File mode */

Struct yang menunjukkan kepada kita struktur on-disk dari inode file. Banyak hal menarik dalam struct itu; lihatlah itu.

The i_modeunsur struct ext2_inodememiliki 16 bit, dan menggunakan hanya 9 untuk user / group / lainnya, membaca / menulis / mengeksekusi hak akses, dan 3 lain untuk setuid, setgid, dan lengket. Itu punya 4 bit untuk membedakan antara jenis-jenis seperti "file biasa", "tautan", "direktori", "pipa bernama", "soket keluarga Unix", dan "blok perangkat".

Kernel Linux dapat mengikuti algoritma pencarian direktori yang biasa, kemudian membuat keputusan berdasarkan izin dan tanda pada i_modeelemen. Untuk 'b', blokir file perangkat, ia dapat menemukan nomor perangkat utama dan minor, dan secara tradisional, menggunakan nomor perangkat utama untuk mencari penunjuk ke beberapa fungsi kernel (driver perangkat) yang berhubungan dengan disk. Nomor perangkat kecil biasanya digunakan sebagai katakanlah, nomor perangkat bus SCSI, atau nomor perangkat EIDE atau semacamnya.

Beberapa keputusan lain tentang cara menangani file seperti /proc/cpuinfodibuat berdasarkan tipe sistem file. Jika Anda melakukan:

% mount | grep proc 
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)

Anda dapat melihat bahwa /procmemiliki jenis sistem file "proc". Membaca dari suatu file /procmenyebabkan kernel melakukan sesuatu yang berbeda berdasarkan pada jenis sistem file, seperti halnya membuka file pada sistem file ReiserFS atau DOS akan menyebabkan kernel menggunakan fungsi yang berbeda untuk mencari file, dan mencari data dari file.

Bruce Ediger
sumber
Apakah Anda yakin, bahwa hanya "file nyata pada disk" yang memiliki nomor inode yang ditampilkan? Saya mendapatkan 4026531975 -r--r--r-- 1 root root 0 Nov 14 18:41 /proc/mdstatyang jelas bukan "file nyata".
guntbert
7

Pada akhirnya mereka semua adalah file untuk Unix, itulah keindahan dari abstraksi.

Cara file ditangani oleh kernel, sekarang itu adalah cerita yang berbeda.

/ proc dan saat ini / dev dan / run (alias / var / run) adalah filesystem virtual dalam RAM. / proc adalah antarmuka / windows untuk variabel dan struktur kernel.

Saya sarankan membaca Kernel Linux http://tldp.org/LDP/tlk/tlk.html dan Linux Device Drivers, Edisi Ketiga https://lwn.net/Kernel/LDD3/ .

Saya juga menikmati Desain dan Implementasi Sistem Operasi FreeBSD http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1

Lihatlah halaman yang relevan yang berkaitan dengan pertanyaan Anda.

http://www.tldp.org/LDP/tlk/dd/drivers.html

Rui F Ribeiro
sumber
terima kasih, saya sedikit mengubah pertanyaan pertama setelah Anda berkomentar.
Joe
Tolong baca komentar terakhir.
Rui F Ribeiro
5

Selain jawaban @ RuiFRibeiro dan @ BruceEdiger, perbedaan yang Anda buat bukanlah perbedaan yang dibuat oleh kernel. Sebenarnya, Anda memiliki berbagai jenis file: file biasa, direktori, tautan simbolik, perangkat, soket (dan saya selalu lupa beberapa sehingga saya tidak akan mencoba membuat daftar lengkap). Anda dapat memiliki informasi tentang jenis file dengan ls: itu adalah karakter pertama di telepon. Sebagai contoh:

$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov.  08:29 /dev/sda

Tanda 'b' di bagian paling awal menandakan bahwa file ini adalah perangkat blok. Tanda hubung, berarti file biasa, 'l' tautan simbolik dan sebagainya. Informasi ini disimpan dalam metadata file, dan dapat diakses melalui system call statmisalnya, sehingga kernel dapat membaca file yang berbeda dan tautan simbolik misalnya.

Kemudian, Anda membuat perbedaan lain antara "file nyata" seperti /bin/bashdan "file virtual" seperti /proc/cpuinfotetapi lsmelaporkan keduanya sebagai file biasa sehingga perbedaannya dari jenis lain:

ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root  829792 24 août  10:58 /bin/bash
-r--r--r-- 1 root wheel      0 20 nov.  16:50 /proc/cpuinfo

Apa yang terjadi adalah mereka berasal dari sistem file yang berbeda. /procadalah titik pemasangan sistem file pseudo procfssedangkan /bin/bashpada sistem file disk biasa. Ketika Linux membuka file (itu berbeda tergantung pada filesystem), itu mengisi struktur data fileyang memiliki, antara lain atribut struktur beberapa fungsi pointer yang menjelaskan cara menggunakan file ini. Oleh karena itu, ia dapat mengimplementasikan perilaku berbeda untuk berbagai jenis file.

Misalnya, ini adalah operasi yang diiklankan oleh /proc/meminfo:

static int meminfo_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, meminfo_proc_show, NULL);
}

static const struct file_operations meminfo_proc_fops = {
    .open       = meminfo_proc_open,
    .read       = seq_read,
    .llseek     = seq_lseek,
    .release    = single_release,
};

Jika Anda melihat definisi meminfo_proc_open, Anda dapat melihat bahwa fungsi ini mengisi buffer dalam memori dengan informasi yang dikembalikan oleh fungsi meminfo_proc_show, yang tugasnya adalah mengumpulkan data tentang penggunaan memori. Informasi ini kemudian dapat dibaca secara normal. Setiap kali Anda membuka file, fungsinya meminfo_proc_opendipanggil dan informasi tentang memori di-refresh.

lororget
sumber
3

Semua file dalam sistem file "nyata" dalam arti bahwa mereka memungkinkan file I / O. Ketika Anda membuka file, kernel membuat deskriptor file, yang merupakan objek (dalam arti pemrograman berorientasi objek) yang bertindak seperti file. Jika Anda membaca file, deskriptor file menjalankan metode baca, yang pada gilirannya akan meminta sistem file (sysfs, ext4, nfs, dll.) Untuk data dari file. Sistem file menyajikan antarmuka yang seragam ke userspace, dan tahu apa yang harus dilakukan untuk menangani membaca dan menulis. Sistem file pada gilirannya meminta lapisan lain untuk menangani permintaan mereka. Untuk file biasa di katakan sistem file ext4, ini akan melibatkan mencari dalam struktur data sistem file (yang mungkin melibatkan membaca disk), dan akhirnya membaca dari disk (atau cache) untuk menyalin data ke buffer baca. Untuk file di say sysfs, umumnya hanya sprintf () sesuatu ke buffer. Untuk node dev blok, ia akan meminta driver disk untuk membaca beberapa blok dan menyalinnya ke buffer (nomor utama dan kecil memberi tahu sistem file yang driver untuk membuat permintaan ke).

jpkotta
sumber