Bagaimana file "/ dev" Linux dibuat?


112

Ada file khusus di Linux yang sebenarnya bukan file.

Contoh-contoh yang paling terkenal dan jelas ini ada di devfolder, "file" seperti:

  • /dev/null - Abaikan apa pun yang Anda tulis ke file
  • /dev/random - Output data acak, bukan isi file
  • /dev/tcp - Mengirim semua data yang Anda tulis ke file ini melalui jaringan

Pertama-tama, apa nama dari jenis-jenis "file" yang benar-benar semacam skrip atau biner yang menyamar?

Kedua, bagaimana mereka diciptakan? Apakah file-file ini dibangun ke dalam sistem pada level kernel, atau adakah cara untuk membuat "file ajaib" sendiri (bagaimana dengan a /dev/rickroll)?


1
Saya tidak tahu bagaimana cara menandai pertanyaan ini, terutama karena saya tidak tahu nama apa yang saya cari. Merasa bebas untuk mengedit tag yang relevan.
IQAndreas

15
BTW, ini adalah bagian mendasar dari desain sistem operasi unix dan seperti-unix: (hampir) semuanya adalah file, atau dapat dibuat agar terlihat seperti file.
cas

5
Lihat Juga: mknod (2) man 2 mknod
RobertL

4
Ini adalah "node perangkat". Namun yang Anda sebutkan - tidak seperti yang terkait dengan disk, keyboard, mouse, kartu audio, dan perangkat lain - disebut "perangkat semu", karena mereka bukan perangkat "nyata" dan hanya ada di kernel. Dimungkinkan untuk membuat yang baru, dengan menulis driver perangkat yang sesuai dan menambahkannya ke kernel (mis. Perangkat pseudo untuk memonitor beberapa aktivitas di komputer). Sebelum direktori / dev ada di disk - hari ini ini adalah sistem file virtual (dari tipe devfs) yang dibuat oleh kernel.
Baard Kopperud

10
Semua file, bahkan file "nyata", adalah artefak perangkat lunak. Perangkat lunak di balik setiap perangkat, berkas, socket, file khusus, atau sesuatu masih harus diciptakan menyediakan meja fungsi untuk menangani open(), read(), close(), dll Setelah itu, terserah software
waltinator

Jawaban:


101

/dev/zeroadalah contoh "file khusus" - khususnya, "simpul perangkat". Biasanya ini bisa diciptakan oleh proses instalasi distro, tetapi Anda dapat benar-benar membuatnya sendiri jika Anda ingin.

Jika Anda bertanya lstentang /dev/zero:

# ls -l /dev/zero
crw-rw-rw- 1 root root 1, 5  Nov 5 09:34 /dev/zero

"C" di awal memberitahu Anda bahwa ini adalah "perangkat karakter"; tipe lainnya adalah "block device" (dicetak lssebagai "b"). Secara kasar, perangkat akses acak seperti harddisk cenderung menjadi perangkat blok, sementara hal-hal berurutan seperti tape drive atau kartu suara Anda cenderung menjadi perangkat karakter.

Bagian "1, 5" adalah "nomor perangkat utama" dan "nomor perangkat minor".

Dengan informasi ini, kita dapat menggunakan mknodperintah untuk membuat simpul perangkat kita sendiri:

# mknod foobar c 1 5

Ini membuat file baru bernama foobar, di folder saat ini, yang melakukan hal yang persis sama /dev/zero. (Tentu saja Anda dapat mengatur izin yang berbeda di atasnya jika Anda mau.) Semua "file" ini benar-benar berisi adalah tiga item di atas - jenis perangkat, nomor utama, nomor kecil. Anda dapat menggunakan lsuntuk mencari kode untuk perangkat lain dan membuat ulang juga. Ketika Anda bosan, cukup gunakan rmuntuk menghapus node perangkat yang baru saja Anda buat.

Pada dasarnya nomor utama memberitahu kernel Linux yang driver perangkat untuk berbicara, dan nomor kecil memberitahu driver perangkat yang Anda bicarakan. (Misalnya, Anda mungkin memiliki satu pengontrol SATA, tetapi mungkin beberapa harddisk terhubung ke dalamnya.)

Jika Anda ingin menemukan perangkat baru yang melakukan sesuatu yang baru ... yah, Anda perlu mengedit kode sumber untuk kernel Linux dan mengkompilasi kernel kustom Anda sendiri. Jadi jangan lakukan itu! :-) Tetapi Anda dapat menambahkan file perangkat yang menduplikasi yang sudah Anda miliki dengan baik. Sistem otomatis seperti udev pada dasarnya hanya mengawasi acara perangkat dan memanggil mknod/ rmuntuk Anda secara otomatis. Tidak ada yang lebih ajaib dari itu.

Masih ada lainnya jenis file khusus:

  • Linux menganggap direktori sebagai jenis file khusus. (Biasanya Anda tidak bisa langsung membuka direktori, tetapi jika Anda bisa, Anda akan menemukan itu adalah file normal yang berisi data dalam format khusus, dan memberi tahu kernel tempat menemukan semua file dalam direktori itu.)

  • Symlink adalah file khusus. (Tapi tautan keras tidak.) Anda dapat membuat symlink menggunakan ln -sperintah. (Carilah halaman manual untuk itu.)

  • Ada juga hal yang disebut "pipa bernama" atau "FIFO" (antrian masuk pertama, keluar pertama). Anda dapat membuatnya dengan mkfifo. FIFO adalah file ajaib yang dapat dibuka oleh dua program sekaligus - satu membaca, satu tulisan. Ketika ini terjadi, ia bekerja seperti pipa shell normal. Tetapi Anda dapat memulai setiap program secara terpisah ...

File yang tidak "spesial" dengan cara apa pun disebut "file biasa". Anda kadang-kadang akan melihat menyebutkan ini di dokumentasi Unix. Itu artinya; file yang bukan node perangkat atau symlink atau apa pun. Hanya file biasa, setiap hari tanpa properti magis.


4
Ada juga satu lagi jenis file khusus, soket domain Unix yang terikat ke sistem file.
Brian Bi

8
Jika Anda ingin bermain dengan mknod, jalankan cat /proc/devicesuntuk melihat nomor utama untuk semua driver. Yang membawa kita ke jenis file khusus /procsistem file lainnya ( jawaban ini membicarakannya).
ugoren

8
Unix lain telah menemukan file khusus mereka sendiri, misalnya Solaris punya pintu .
Kevin

6
Minor nitpick: Anda tidak perlu mengkompilasi ulang kernel untuk menulis karakter baru / perangkat blok :) crashcourse.ca/introduction-linux-kernel-programming/... Kalau tidak, ini jawaban yang sangat bagus, +1!
Commander Coriander Salamander

1
@MathematicalOrchid: Langkah balasan Anda tidak ada (atau setidaknya hanya menyatakan secara implisit) adalah fakta bahwa file-file khusus itu sama sekali tidak menyamarkan skrip shell atau binari (seperti pertanyaan tersirat), melainkan sebuah antarmuka untuk mengakses fungsionalitas yang ada di kernel OS.
Pemimpi

34

Sebagian besar /deventri adalah blok perangkat inode atau karakter perangkat inode. Wikipedia memiliki banyak detail tentang itu, yang tidak akan saya ulangi.

Tetapi /dev/tcpyang disebutkan dalam pertanyaan Anda tidak dijelaskan oleh jawaban yang ada. /dev/tcpdan /dev/udpberbeda dari kebanyakan /deventri lainnya . Perangkat blok dan karakter diimplementasikan oleh kernel, tetapi /dev/tcpdan /dev/udpdiimplementasikan dalam mode pengguna.

Bash shell adalah salah satu program yang memiliki implementasi /dev/tcpdan /dev/udp(disalin dari ksh93). Ketika Anda mencoba untuk membuka jalur di bawah mereka yang memiliki operator pengalihan bash, itu tidak akan melakukan openpanggilan sistem biasa . Sebaliknya bash akan membuat soket TCP dan menghubungkannya ke port yang ditentukan.

Itu diimplementasikan dalam mode pengguna dan hanya dalam beberapa program seperti yang dapat dilihat pada contoh berikut yang menunjukkan perbedaan antara membiarkan bashdan catmencoba membuka/dev/tcp/::1/22

$ cat /dev/tcp/::1/22
cat: /dev/tcp/::1/22: No such file or directory
$ cat < /dev/tcp/::1/22
SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3

Perbedaannya ksh93adalah bahwa bashhanya akan melakukan koneksi TCP dengan operator pengalihan, tidak di tempat lain di mana ia dapat membuka file seperti sourceatau .builtin.


Juga, GNU gawkmemiliki kasus khusus yang sama /inet{,4,6}/{tcp,udp}/$port/$remote/$rport, sejak sekitar 2010 (saya tidak ingat persis dan tidak dapat menemukan catatan rilis).
dave_thompson_085

6
IMO, cara yang lebih baik untuk menyatakan maksudnya /dev/tcpadalah BUKAN file. Tidak pernah ada file bernama ini. Sintaks Bash untuk membuka soket menggunakan string /dev/tcp/addressseperti nama file, tetapi menyebutnya "file yang diimplementasikan di ruang pengguna" hanya terdengar aneh. Menarik yang kshmengaitkan nama file itu untuk semuanya, bukan hanya pengalihan. Itu lebih dekat ke "menerapkan file".
Peter Cordes

@PeterCordes saya percaya UWIN mengatur ini sebagai file yang sebenarnya. dan saya pikir 3dfs melakukan hal yang sama. ingat, bashhanya menyalin perilaku ini, tetapi itu berasal dari tempat lain.
mikeserv

19

Selain node perangkat yang dijelaskan dalam jawaban lain (dibuat dengan mknod (2) atau disediakan oleh beberapa devfs ), Linux memiliki file "ajaib" lainnya yang disediakan oleh sistem file virtual khusus , khususnya di /proc/(lihat proc (5) , baca tentang procfs) ) dan dalam /sys/(baca tentang sysfs ).

File pseudo ini (yang muncul -eg to stat (2) - sebagai file biasa, bukan sebagai perangkat) adalah tampilan virtual yang disediakan oleh kernel; khususnya, membaca dari /proc/(misalnya dengan cat /proc/$$/maps, atau dengan membuka (2) -ing /proc/self/statusdalam program Anda) umumnya tidak melibatkan I / O fisik dari disk atau jaringan, jadi cukup cepat.

Untuk membuat beberapa file pseudo tambahan pada /proc/umumnya Anda harus menulis modul kernel Anda sendiri dan memuatnya (lihat misalnya ini ).


3
AFAIK informasi tentang perpanjangan / proc sudah ketinggalan zaman. Meskipun secara teknis masih memungkinkan, / proc (atau lebih tepatnya procfs) hanya boleh menyimpan informasi tentang proses yang sedang berjalan. Semua file pseudo lainnya termasuk yang berisi informasi runtime atau opsi konfigurasi untuk kernel harus masuk ke / sys (sysfs). Masih ada beberapa file pseudo yang tidak terkait proses di / proc (mis. Meminfo, cpuinfo) untuk alasan kompatibilitas, tetapi file pseudo baru harus masuk ke sysfs.
Pemimpi

13

Mereka disebut node perangkat, dan dibuat secara manual dengan mknodatau secara otomatis oleh udev. Mereka biasanya berupa antarmuka seperti file ke perangkat karakter atau blokir dengan driver di kernel - mis. Disk adalah perangkat blok, ttys dan port serial dll. Adalah perangkat karakter.

Ada jenis file "khusus" lainnya juga, termasuk pipa dan fifos dan soket bernama.


9

Karena pengguna lain telah menjelaskan dengan sangat rinci, file-file khusus memerlukan kode untuk mendukungnya. Namun, tampaknya tidak ada yang menyebutkan bahwa Linux menyediakan beberapa cara untuk menulis kode itu di userspace:

A. FUSE (Filesystem di USErspace) memungkinkan Anda untuk menulis sesuatu seperti /proctanpa risiko menabrak kernel dan melakukannya dalam bahasa / runtime pilihan Anda, seperti Go , Node.js , Perl , PHP , Python , Ruby , Rust , dll .

Ini juga memiliki keuntungan bahwa sistem file FUSE dapat dipasang tanpa sudokarena mereka berjalan sebagai pengguna melakukan pemasangan.

Berikut adalah beberapa contoh hal-hal yang ditulis orang menggunakan FUSE:

  • mp3fs (Lihat file FLAC Anda sebagai file MP3 yang dapat dibuat saat Anda menyalin / mengklik-seret ke pemutar MP3 Anda)
  • PyTagsFS (Lihat media Anda di pohon folder virtual yang dibangun dari tag metadata)
  • fuse-zip (Pasang file Zip sebagai folder)
  • FuseISO (Pasang ISO tanpa izin root)
  • iFUSE (Mount iDevices)
  • FuseDAV (Mount share WebDAV)
  • fuse-exfat (Mount filesystem yang diformat)
  • ntfs-3g ( The driver Linux NTFS)

B. Jika Anda ingin membuat perangkat input virtual seperti keyboard, mouse, joystick, dll. (Mis. Untuk menulis driver userspace untuk perangkat USB yang Anda gunakan libusb), ada uinput .

Bindings untuk itu lebih sulit ditemukan, tetapi saya tahu mereka ada untuk Go (khusus Keyboard), Python , dan Ruby (2) .

Contoh penggunaan uinput dunia nyata meliputi:

  • G15Daemon (driver Linux untuk tombol LCD dan gaming pada keyboard gaming Logitech G15)
  • ds4drv (Driver untuk pengontrol Sony DualShock 4)
  • xboxdrv (driver pengontrol XBox 360 Alternatif dan Linux setara dengan x360ce game yang didesain sangat buruk seperti Runner2: Legend of Rhythm Alien masa depan dapat berpikir bahwa mereka sedang berbicara dengan pengontrol XBox nyata ketika tidak)
  • Driver Wiimote lama seperti cwiid yang diperlukan sebelum seseorang akhirnya menulis driver Wiimote kernel sehingga dukungan akan tersedia secara default.

C. Untuk perangkat karakter umum, ada CUSE (Perangkat karakter di USErspace). Ini jauh kurang populer.

Satu-satunya pengguna dari Cuse API bahwa aku secara pribadi sadar adalah program yang sama yang mendorong penciptaan: osspd , yang mengimplementasikan /dev/dsp, /dev/adspdan /dev/mixer(API audio yang OSS) di userspace sehingga mereka dapat dialihkan melalui PulseAudio atau DMIX.

Satu-satunya CUSE binding yang dapat saya temukan adalah cusepy , yang belum diperbarui sejak 2010.

D. Anda mungkin tidak memerlukan file khusus baru sama sekali.

Sebagai contoh, Anda dapat membuka komunikasi mentah dengan perangkat USB apa pun menggunakan libusb (Daftar binding pada halaman) dan kemudian berkomunikasi dengan program lain melalui beberapa mekanisme lain (soket TCP / UDP, membaca / menulis stdin / stdout atau file biasa pada disk , dll.).


1
cusepy mungkin tidak diperbarui dalam beberapa saat (pada kenyataannya, itu tidak pernah diperbarui; itu hanya memiliki satu komit!), tetapi setelah baru saja menulis perangkat karakter menggunakan cusepy beberapa minggu yang lalu, saya dapat mengkonfirmasi masih berfungsi dengan baik. Itu kehilangan beberapa fungsi yang berkaitan dengan implementasi poll, tetapi karena cusepy menggunakan ctypes dan binding diautogasi berdasarkan file header C, memperbaiki setiap fungsi yang hilang hanyalah masalah menambahkan nama fungsi yang diinginkan ke daftar fungsi yang diekspor di setup.py.
Aleksi Torhamo

1
Contoh lain yang menarik dari penggunaan FUSE adalah sshfs . Ini memungkinkan Anda untuk menelusuri sistem file jarak jauh seolah-olah itu lokal menggunakan koneksi SSH di bawahnya.
Tn. Deathless

@ Mr.Deathless Ya. Saya benar-benar menggunakannya dan bermaksud menyebutkannya tetapi saya lupa.
ssokolow

6

Buku Linux Device Drivers (sangat disarankan) menjelaskan ini secara terperinci, dan bahkan telah Anda membuat modul kernel yang melakukan ini sebagai contoh, tetapi singkatnya, setiap driver perangkat memiliki fungsi spesifik yang dipanggil ketika file dibuka, ditutup , baca, tulis, dll. File "khusus" hanya melakukan sesuatu yang istimewa di dalam fungsi-fungsi itu, alih-alih mengakses perangkat keras penyimpanan pada disk.

Misalnya, fungsi tulis untuk /dev/nullhanya tidak melakukan apa-apa, mengabaikan byte. Fungsi baca untuk /dev/randommengembalikan nomor acak.


1

mount -t devtmpfs

Sangat menarik untuk melihat bahwa dalam sistem modern, /devbiasanya tipe sistem file yang dapat dipasang di mana pun Anda inginkan. Ubuntu 16.04:

mkdir d
sudo mount -t devtmpfs none d
head -c 10 d/random
sudo umount d

Ini diaktifkan oleh CONFIG_DEVTMPFS=y, dan memungkinkan kernel itu sendiri untuk membuat dan menghancurkan file perangkat sesuai kebutuhan.

CONFIG_DEVTMPFS_MOUNT=y

Opsi ini membuat kernel auto-mount devtmpfs aktif /dev.

drivers/base/Kconfig dokumen:

config DEVTMPFS_MOUNT
    bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs"
    depends on DEVTMPFS
    help
      This will instruct the kernel to automatically mount the
      devtmpfs filesystem at /dev, directly after the kernel has
      mounted the root filesystem. The behavior can be overridden
      with the commandline parameter: devtmpfs.mount=0|1.
      This option does not affect initramfs based booting, here
      the devtmpfs filesystem always needs to be mounted manually
      after the rootfs is mounted.
      With this option enabled, it allows to bring up a system in
      rescue mode with init=/bin/sh, even when the /dev directory
      on the rootfs is completely empty.

file_operations

Terakhir, Anda harus membuat modul kernel perangkat karakter Anda sendiri untuk melihat apa yang sebenarnya terjadi.

Berikut adalah contoh runnable minimal: Memahami file perangkat karakter (atau karakter khusus)

Langkah paling penting, adalah menyiapkan file_operationsstruct, misalnya:

static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = read,
    .open = open,
};

static int myinit(void)
{
    major = register_chrdev(0, NAME, &fops);
    return 0;
}

yang berisi pointer fungsi yang dipanggil untuk setiap panggilan sistem terkait file.

Kemudian menjadi jelas bahwa Anda mengabaikan panggilan sistem terkait file tersebut untuk melakukan apa pun yang Anda inginkan, jadi beginilah cara kernel mengimplementasikan perangkat /dev/zero.

Buat /deventri di secara otomatis tanpamknod

Misteri terakhir adalah bagaimana kernel secara otomatis membuat /deventri.

Mekanisme ini dapat diamati dengan membuat modul kernel yang melakukan itu sendiri seperti yang ditunjukkan di: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- code-of-a-linux-kernel-module / 45531867 # 45531867 dan turun ke device_createpanggilan.


Di OpenBSD ada skrip MAKEDEV yang menyederhanakan ini sedikit, lihat man.openbsd.org/MAKEDEV.8 Tidak yakin mengapa Linux tidak memilikinya kecuali itu jauh lebih rumit. Mungkin bagian bisa disesuaikan. Anda bisa mengatakan MKNOD tty misalnya dan menangani detailnya.
Alan Corey
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.