Sangat sering pemula mendengar ungkapan "Semuanya adalah file di Linux / Unix". Namun, apa direktori itu? Bagaimana mereka berbeda dari file?
Sangat sering pemula mendengar ungkapan "Semuanya adalah file di Linux / Unix". Namun, apa direktori itu? Bagaimana mereka berbeda dari file?
Jawaban:
Catatan: awalnya ini ditulis untuk mendukung jawaban saya untuk Mengapa direktori saat ini dalam ls
perintah diidentifikasi sebagai terhubung dengan dirinya sendiri? tetapi saya merasa bahwa ini adalah topik yang pantas untuk berdiri sendiri, dan karenanya, tanya jawab .
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 directories
negara:
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 /dev
dan /run
sistem 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:
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 1234
misalnya) 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.
Filesystem menerapkan pohon direktori sebagai salah satu struktur data pohon. Khususnya,
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
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.h
C library muncul, yang mendefinisikan dirent
struktur, 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_p
struktur itu. Tentu saja, setiap item akan berisi bidang yang ditentukan dalam template untuk dirent
ditampilkan 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_name
dan d_ino
bidang.
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.
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