Що таке каталоги, якщо все в Linux - це файл?


17

Дуже часто початківці чують фразу "Все є файлом в Linux / Unix". Однак які каталоги тоді? Чим вони відрізняються від файлів?

Відповіді:


22

Примітка: спочатку це було написано на підтримку моєї відповіді на те, чому поточний каталог у lsкоманді визначений як пов'язаний з собою? але я відчув, що це тема, яка заслуговує на те, щоб стати самостійно, а отже, це питання .

Розуміння файлової системи Unix / Linux та файлів: все є inode

По суті, каталог - це лише спеціальний файл, який містить список записів та їх ідентифікатор.

Перш ніж розпочати дискусію, важливо зробити відмінність між декількома термінами та зрозуміти, що насправді представляють каталоги та файли. Можливо, ви чули вираз "Все - це файл" для Unix / Linux. Що ж, користувачі часто розуміють як файл, це: /etc/passwd- Об'єкт із контуром та назвою. Насправді ім’я (будь то каталог чи файл, чи будь-що інше) - це лише рядок тексту - властивість фактичного об’єкта. Цей об'єкт називається inode або I-число і зберігається на диску в таблиці inode. Відкриті програми також мають таблиці inode, але це зараз не хвилює нас.

Поняття Unix про каталог, як Кен Томпсон в інтерв'ю 1989 року :

... А потім деякі з цих файлів були каталогами, які просто містили ім'я та I-номер.

Цікаве спостереження можна зробити з розмови Денніса Річі в 1972 році, що

"... каталог насправді не більше ніж файл, але його вміст контролюється системою, а вміст - це імена інших файлів. (Каталог іноді називається каталогом в інших системах.)"

... але ніде в розмові немає згадок про індекси. Однак у посібнику 1971 р. Йдеться про format of directories:

Про те, що файл є каталогом, позначається бітом у слові прапора його входу i-node.

Записи в каталозі мають довжину 10 байт. Перше слово - i-вузол файла, представлений записом, якщо він не є нулем; якщо нуль, запис порожній.

Так воно було там з самого початку.

Спарювання каталогів та inode також пояснено у розділі Як зберігаються структури каталогів у файловій системі UNIX? . сам каталог - це структура даних, точніше: перелік об'єктів (файлів та номерів inode), що вказує на списки про ці об'єкти (дозволи, тип, власник, розмір тощо). Отже, кожен каталог містить власний номер inode, а потім імена файлів та їхні номери inode. Найвідомішим є inode №2, який є /каталогом . (Зауважте, хоча це /devі /runє віртуальні файлові системи, тому, оскільки вони є кореневими папками для їх файлової системи, вони також мають inode 2; наприклад, inode є унікальним у власній файловій системі, але з доданими декількома файловими системами у вас є не унікальні вставки). діаграма, запозичена з пов'язаного питання, ймовірно, пояснює це більш коротко:

Каталог-iNode-блок

Всю інформацію, що зберігається в inode, можна отримати через stat()системні дзвінки відповідно до Linux man 7 inode:

Кожен файл має вкладку, що містить метадані про файл. Додаток може отримати ці метадані, використовуючи stat (2) (або пов'язані з ним виклики), що повертає структуру stat, або statx (2), яка повертає структуру statx.

Чи можна отримати доступ до файлу лише знаючи його номер inode ( ref1 , ref2 )? У деяких реалізаціях Unix це можливо, але це обходить перевірки дозволу та доступу, тому в Linux це не реалізовано, і вам доведеться перейти до дерева файлової системи ( find <DIR> -inum 1234наприклад, наприклад), щоб отримати ім'я файлу та його відповідний inode.

На рівні вихідного коду він визначений у джерелі ядра Linux, а також прийнятий багатьма файловими системами, що працюють в операційних системах Unix / Linux, включаючи файлові системи ext3 та ext4 (за замовчуванням Ubuntu). Цікава річ: оскільки дані є лише блоками інформації, Linux насправді має функцію inode_init_always, яка може визначити, чи є inode трубою ( inode->i_pipe). Так, розетки та труби технічно також є файлами - анонімними файлами, які можуть не мати на диску файлу. У сокетів FIFO та Unix-Domain є назви файлів у файловій системі.

Дані самі по собі можуть бути унікальними, але номери inode не є унікальними. Якщо у нас є жорстке посилання на foo з назвою foobar, це також вказуватиме на inode 123. Цей самий inode містить інформацію про те, які фактичні блоки дискового простору займають цей інод. І це технічно, як ви можете .бути пов'язані з назвою файлу каталогу. Ну, майже: ви не можете створювати жорсткі посилання на каталоги в Linux самостійно , але файлові системи можуть дозволяти жорсткі посилання на каталоги дуже дисципліновано, що обмежує наявність лише .та ..жорстких посилань.

Дерево каталогів

Файлові системи реалізують дерево каталогів як одну з структур даних дерева. Зокрема,

  • ext3 і ext4 використовують HTree
  • xfs використовує B + дерево
  • zfs використовує хеш-дерево

Ключовим моментом тут є те, що самі каталоги є вузлами в дереві, а підкаталоги - дочірніми вузлами, причому кожна дитина має посилання назад до батьківського вузла. Таким чином, для посилання на каталог кількість inode становить мінімум 2 для голого каталогу (посилання на ім'я каталогу /home/example/та посилання на self /home/example/.), і кожен додатковий підкаталог є додатковою посиланням / вузлом:

# 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

Діаграма, знайдена на сторінці курсу курсу Ієна Д. Аллена, показує спрощену дуже чітку схему:

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>

Єдине, що невірно в діаграмі ПРАВО - це те, що файли технічно не вважаються самим деревом каталогів: додавання файлу не впливає на кількість посилань:

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

Доступ до каталогів так, ніби вони файли

Щоб цитувати Лінуса Торвальда :

Вся справа в тому, що "все є файлом" полягає не в тому, що у вас є якесь випадкове ім'я файлу (дійсно, розетки та труби показують, що "файл" і "ім'я файлу" не мають нічого спільного), а в тому, що ви можете використовувати загальну інструменти для роботи над різними речами.

Враховуючи, що каталог - це лише особливий випадок файлу, природно, повинні бути API, які дозволяють нам відкривати / читати / записувати / закривати їх аналогічно звичайним файлам.

Ось де dirent.hстворена бібліотека C, яка визначає direntструктуру, яку ви можете знайти в 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 */
   };

Таким чином, у вашому коді C ви повинні визначитись struct dirent *entry_p, і коли ми відкриємо каталог із ним opendir()і почнемо його читати readdir(), ми будемо зберігати кожен елемент у цій entry_pструктурі. Звичайно, кожен елемент буде містити поля, визначені в шаблоні, direntпоказаному вище.

Практичний приклад того, як це працює, ви можете знайти у моїй відповіді на тему « Перерахування файлів та їх номерів inode у поточному робочому каталозі .

Зауважте, що в посібнику POSIX на fdopen зазначено, що "[t] he записи в каталозі для крапки та крапки є необов'язковими", а в посібниках readdir в ручному режимі struct dirent потрібно мати лише поля d_nameта d_inoполя.

Зауважте про "запис" у каталоги: запис у каталог змінює його "список" записів. Отже, створення або видалення файлу безпосередньо пов'язане з дозволами на запис у каталог , а додавання / видалення файлів - це операція запису у вказаному каталозі.


2
Я відмовляюся приймати сокети - це файли;) Чи буде "все доступно як файл" точнішим?
Rinzwind

@Rinzwind Ну, фраза "все доступно як файл" є точною. У звичайних файлах є open()і read()сокети, connect()і read()теж. Що точніше, це те, що "файл" - це дійсно організовані "дані", що зберігаються на диску або пам'яті, а деякі файли є анонімними - вони не мають імені файлу. Зазвичай користувачі думають про файли з точки зору цього значка на робочому столі, але це не єдине, що існує. Дивіться також unix.stackexchange.com/a/116616/85039
Сергій Колодяжний

Ну питання було більше про те, чи каталог був файлом. І воно є. Розетки можуть бути майже окремим питанням разом з FIFO Named Pipes.
WinEunuuchs2Unix

Ну, я отримав відповідь про труби поки: askubuntu.com/a/1074550/295286 Можливо, FIFO будуть наступні
Сергій Колодяжний,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.