Apa itu direktori, jika semua yang ada di Linux adalah file?

17

Sangat sering pemula mendengar ungkapan "Semuanya adalah file di Linux / Unix". Namun, apa direktori itu? Bagaimana mereka berbeda dari file?

Sergiy Kolodyazhnyy
sumber

Jawaban:

22

Catatan: awalnya ini ditulis untuk mendukung jawaban saya untuk Mengapa direktori saat ini dalam lsperintah diidentifikasi sebagai terhubung dengan dirinya sendiri? tetapi saya merasa bahwa ini adalah topik yang pantas untuk berdiri sendiri, dan karenanya, tanya jawab .

Memahami sistem file dan file Unix / Linux: Semuanya adalah sebuah inode

Pada dasarnya, direktori hanyalah file khusus, yang berisi daftar entri dan ID mereka.

Sebelum kita memulai diskusi, penting untuk membuat perbedaan antara beberapa istilah dan memahami apa yang sebenarnya direpresentasikan oleh direktori dan file. Anda mungkin pernah mendengar ungkapan "Semuanya adalah file" untuk Unix / Linux. Nah, yang sering dipahami pengguna sebagai file adalah ini: /etc/passwd- Objek dengan path dan nama. Pada kenyataannya, sebuah nama (baik itu direktori atau file, atau apa pun yang lain) hanyalah serangkaian teks - properti dari objek aktual. Objek itu disebut inode atau I-number, dan disimpan di disk dalam tabel inode. Program terbuka juga memiliki tabel inode, tapi itu bukan urusan kami untuk saat ini.

Gagasan Unix tentang sebuah direktori adalah seperti yang ditulis oleh Ken Thompson dalam sebuah wawancara tahun 1989 :

... Dan kemudian beberapa dari file-file itu, adalah direktori yang hanya berisi nama dan nomor-I.

Pengamatan yang menarik dapat dilakukan dari ceramah Dennis Ritchie pada tahun 1972 itu

"... direktori sebenarnya tidak lebih dari sebuah file, tetapi isinya dikendalikan oleh sistem, dan isinya adalah nama-nama file lain. (Direktori kadang-kadang disebut katalog di sistem lain.)"

... tapi tidak disebutkan inode di mana pun dalam pembicaraan. Namun, manual 1971 tentang format of directoriesnegara:

Fakta bahwa file adalah direktori ditunjukkan oleh sedikit pada kata bendera entri i-simpulnya.

Entri direktori sepanjang 10 byte. Kata pertama adalah simpul-i dari file yang diwakili oleh entri, jika bukan nol; jika nol, entri kosong.

Jadi sudah ada sejak awal.

Pasangan direktori dan inode juga dijelaskan dalam Bagaimana struktur direktori disimpan dalam sistem file UNIX? . direktori itu sendiri adalah struktur data, lebih khusus: daftar objek (file dan nomor inode) menunjuk ke daftar tentang objek-objek tersebut (izin, tipe, pemilik, ukuran, dll.). Jadi setiap direktori berisi nomor inode sendiri, dan kemudian nama file dan nomor inode mereka. Paling terkenal adalah inode # 2 yang merupakan /direktori . (Catatan, meskipun itu /devdan /runsistem file virtual, jadi karena mereka adalah folder root untuk sistem file mereka , mereka juga memiliki inode 2; yaitu inode unik pada sistem file sendiri, tetapi dengan beberapa sistem file terpasang, Anda memiliki inode non-unik). diagram yang dipinjam dari pertanyaan terkait mungkin menjelaskannya dengan lebih ringkas:

Direktori-iNode-Block

Semua informasi yang disimpan dalam inode dapat diakses melalui stat()panggilan sistem, sesuai Linux man 7 inode:

Setiap file memiliki inode yang berisi metadata tentang file tersebut. Aplikasi dapat mengambil metadata ini menggunakan stat (2) (atau panggilan terkait), yang mengembalikan struktur stat, atau statx (2), yang mengembalikan struktur statx.

Apakah mungkin mengakses file hanya mengetahui nomor inode-nya ( ref1 , ref2 )? Pada beberapa implementasi Unix dimungkinkan tetapi melewati izin dan akses pemeriksaan, jadi di Linux itu tidak diterapkan, dan Anda harus melintasi pohon sistem file (via find <DIR> -inum 1234misalnya) untuk mendapatkan nama file dan inode yang sesuai.

Pada level kode sumber, ini didefinisikan dalam sumber kernel Linux dan juga diadopsi oleh banyak filesystem yang bekerja pada sistem operasi Unix / Linux, termasuk filesystem ext3 dan ext4 (default Ubuntu). Hal yang menarik: dengan data yang hanya berupa blok informasi, Linux sebenarnya memiliki fungsi inode_init_always yang dapat menentukan apakah inode adalah pipa ( inode->i_pipe). Ya, soket dan pipa secara teknis juga berupa file - file anonim, yang mungkin tidak memiliki nama file pada disk. FIFOs dan Unix-Domain sockets memang memiliki nama file pada filesystem.

Data itu sendiri mungkin unik, tetapi nomor inode tidak unik. Jika kita memiliki tautan keras ke foo yang disebut foobar, itu juga akan mengarah ke inode 123. Inode ini sendiri berisi informasi tentang blok ruang disk aktual yang ditempati oleh inode itu. Dan itu secara teknis bagaimana Anda bisa .terhubung ke nama file direktori. Yah, hampir: Anda tidak dapat membuat hardlinks ke direktori di Linux sendiri , tapi filesystem dapat memungkinkan hard link ke direktori dengan cara yang sangat disiplin, yang membuat kendala hanya memiliki .dan ..sebagai link keras.

Pohon Direktori

Filesystem menerapkan pohon direktori sebagai salah satu struktur data pohon. Khususnya,

  • ext3 dan ext4 menggunakan HTree
  • xfs menggunakan B + Tree
  • zfs menggunakan pohon hash

Poin kunci di sini adalah bahwa direktori itu sendiri adalah simpul di pohon, dan subdirektori adalah simpul anak, dengan setiap anak memiliki tautan kembali ke simpul induk. Jadi, untuk tautan direktori, jumlah inode adalah minimum 2 untuk direktori telanjang (tautan ke nama direktori /home/example/dan tautan ke diri /home/example/.), dan setiap subdirektori tambahan adalah tautan / simpul tambahan:

# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24

Diagram yang ditemukan pada halaman kursus Ian D. Allen menunjukkan diagram yang sangat jelas dan sederhana:

WRONG - names on things      RIGHT - names above things
=======================      ==========================

    R O O T            --->         [etc,bin,home]   <-- ROOT directory
   /   |   \                         /    |      \
etc   bin   home       --->  [passwd]  [ls,rm]  [abcd0001]
 |   /   \    \                 |      /    \       |
 |  ls   rm  abcd0001  --->     |  <data>  <data>  [.bashrc]
 |               |              |                   |
passwd       .bashrc   --->  <data>                <data>

Satu-satunya hal dalam diagram KANAN yang salah adalah bahwa file tidak secara teknis dianggap berada di pohon direktori itu sendiri: Menambahkan file tidak memiliki efek pada penghitungan tautan:

$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4

Mengakses direktori seolah-olah itu file

Mengutip Linus Torvalds :

Intinya dengan "semuanya adalah file" bukan bahwa Anda memiliki beberapa nama file acak (memang, soket dan pipa menunjukkan bahwa "file" dan "nama file" tidak ada hubungannya dengan satu sama lain), tetapi kenyataan bahwa Anda dapat menggunakan umum alat untuk beroperasi pada berbagai hal.

Menimbang bahwa direktori hanyalah kasus khusus dari suatu file, tentu saja harus ada API yang memungkinkan kita untuk membuka / membaca / menulis / menutupnya dengan cara yang mirip dengan file biasa.

Di situlah dirent.hC library muncul, yang mendefinisikan direntstruktur, yang dapat Anda temukan di man 3 readdir :

   struct dirent {
       ino_t          d_ino;       /* Inode number */
       off_t          d_off;       /* Not an offset; see below */
       unsigned short d_reclen;    /* Length of this record */
       unsigned char  d_type;      /* Type of file; not supported
                                      by all filesystem types */
       char           d_name[256]; /* Null-terminated filename */
   };

Jadi, dalam kode C Anda, Anda harus mendefinisikan struct dirent *entry_p, dan ketika kami membuka direktori dengan opendir()dan mulai membacanya readdir(), kami akan menyimpan setiap item ke dalam entry_pstruktur itu. Tentu saja, setiap item akan berisi bidang yang ditentukan dalam template untuk direntditampilkan di atas.

Contoh praktis tentang cara kerjanya dapat ditemukan dalam jawaban saya tentang Cara daftar file dan nomor inode mereka di direktori kerja saat ini .

Perhatikan bahwa manual POSIX pada fdopen menyatakan bahwa "[t] ia entri direktori untuk titik dan titik-titik adalah opsional" dan status manual readdir struct dirent hanya diperlukan untuk memiliki d_namedan d_inobidang.

Catatan tentang "menulis" ke direktori: menulis ke direktori mengubah "daftar" entri. Oleh karena itu, membuat atau menghapus file secara langsung dikaitkan dengan izin menulis direktori , dan menambahkan / menghapus file adalah operasi penulisan pada direktori tersebut.

Sergiy Kolodyazhnyy
sumber
2
Saya menolak menerima soket adalah file;) Apakah "semuanya dapat diakses sebagai file" lebih akurat?
Rinzwind
@Rinzwind Nah, frasa "semuanya dapat diakses sebagai file" adalah akurat. File biasa memiliki open()dan read()soket memiliki connect()dan read()juga. Apa yang lebih akurat adalah bahwa "file" benar-benar terorganisir "data" yang disimpan pada disk atau memori, dan beberapa file anonim - mereka tidak memiliki nama file. Biasanya pengguna memikirkan file dalam hal ikon itu di desktop, tetapi itu bukan satu-satunya hal yang ada. Lihat juga unix.stackexchange.com/a/116616/85039
Sergiy Kolodyazhnyy
Yah pertanyaannya adalah lebih lanjut tentang apakah direktori adalah file. Dan itu. Soket hampir bisa menjadi pertanyaan terpisah bersama dengan Pipa Bernama FIFO.
WinEunuuchs2Unix
Yah, saya mendapat jawaban tentang pipa sejauh ini: askubuntu.com/a/1074550/295286 Mungkin FIFO akan menjadi yang berikutnya
Sergiy Kolodyazhnyy