Чому я можу котів / розробити?


41

Я можу cat /dev, можу ls /dev, не можу less /dev. Чому catя дозволяю мені catцей каталог, але немає інших каталогів?

Зображення такої поведінки в zsh.


@KamilMaciorowski, ось результат і neofetchдля вашої інформації :) i.imgur.com/3azpnDt.png
haboutnnah

Відповіді:


43

Історично (до V7 UNIX або близько 1979 року) readсистемний виклик працював як у файлах, так і в каталогах. readна каталог повертає просту структуру даних, яку програма користувача розбирала б, щоб отримати записи каталогу. Дійсно, lsінструмент V7 зробив саме це - readу каталозі проаналізуйте отриману структуру даних та виведіть у форматі списку.

Оскільки файлові системи стали більш складними, ця "проста" структура даних ускладнилася, до того моменту, коли readdirбула додана функція бібліотеки, яка допомагає програмам аналізувати вихід read(directory). У різних системах і файлових системах можуть бути різні дискові формати, що ускладнюється.

Коли Sun представила мережеву файлову систему (NFS), вони хотіли повністю абстрагувати структуру каталогів на диску. Замість того, щоб зробити своє read(directory)повернення каталогу незалежним від платформи, вони додали новий системний виклик getdirents- і заборонили кататися readна мережевих каталогах. Цей системний виклик був швидко адаптований для роботи над усіма каталогами різних ароматів UNIX, що робить його типовим способом отримання вмісту каталогів. (Історія абстрагується з https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )

Оскільки readdirзараз спосіб читання каталогів за замовчуванням read(directory)зазвичай не реалізується (повертається -EISDIR) на більшості сучасних ОС (наприклад, QNX є помітним винятком, який реалізується readdirяк read(directory)). Однак з дизайном "віртуальної файлової системи" в більшості сучасних ядер фактично залежить від індивідуальної файлової системи, чи працює чи ні каталог, чи ні.

І дійсно, на macOS devfsфайлова система, що лежить в основі точки /devмонтажу, дійсно підтримує зчитування ( https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629 ) :

static int
devfs_read(struct vnop_read_args *ap)
{
        devnode_t * dn_p = VTODN(ap->a_vp);

    switch (ap->a_vp->v_type) {
      case VDIR: {
          dn_p->dn_access = 1;

          return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);

Це явно викликає, READDIRякщо ви намагаєтесь прочитати /dev(читання файлів під /devобробляється окремою функцією - devfsspec_read). Отже, якщо програма викликає readсистемний виклик /dev, вона матиме успіх і отримує список каталогів!

Це фактично функція, яка є захопленням з найперших днів UNIX і яка не торкалася вже дуже давно. Частина мене підозрює, що це зберігається з якоїсь причини зворотної сумісності, але це може бути так само просто, що ніхто не піклується про те, щоб видалити цю функцію, оскільки це насправді нічого не шкодить.


Напевно, останнє, бачачи, як його видалено з більшості каталогів.
користувач253751

36

Менше - це переглядач текстових файлів, кішка - це інструмент для копіювання довільних даних. Так менше проводить власну перевірку, щоб переконатися, що ти не відкриваєш щось, що матиме велику кількість даних, або ведеш себе дуже дивно. З іншого боку, у кішки взагалі немає такої перевірки - якщо ядро ​​дозволить вам щось відкрити (навіть якщо це труба чи пристрій чи щось гірше), кішка прочитає це.

То чому ОС дозволяє кішці відкривати каталоги? Традиційно в системах стилю BSD всі каталоги можна читати як файли, і саме так програми перелічували б каталог в першу чергу: просто інтерпретуючи різні структури, що зберігаються на диску.

Пізніше ці дискові структури почали відходити від дирента, використовуваного ядром: де раніше каталог був лінійним списком, пізніше файлові системи почали використовувати хештелі, B-дерева тощо. Тож читання каталогів безпосередньо вже не було простим - ядро ​​вирощувало для цього спеціальні функції. (Я не впевнений, чи це було основною причиною, чи вони були в основному додані з інших причин, таких як кешування.)

Деякі системи BSD продовжують дозволяти вам відкривати всі каталоги для читання; Я не знаю, чи дають вони необроблені дані з диска, чи повертають вони замість них емуляційний список, або чи дозволяють драйверу файлової системи приймати рішення.

Тому, можливо, macOS є однією з тих операційних систем, де ядро ​​дозволяє це , доки файлова система надає дані. І різниця полягає в тому, що /devу devfsфайловій системі, яка була написана для того, щоб це дозволити в перші дні, в той час /як у файловій системі APFS, яка пропускала цю функцію як непотрібну в сучасний час.

Відмова: Я фактично не проводив жодних досліджень на BSD або macOS. Я просто крилату.


Це, здається, має сенс. Чи є інші розділи пам’яті, які відрізняються від стандартної файлової системи ОС? Я припускав /etc, що так, тому я використав це як мій орієнтир.
haboutnnah

2
Навпаки, загалом / etc - це лише звичайна папка, що містить звичайні файли. Там можуть бути і інші віртуальні файлові системи , хоча - бігти mountабо /sbin/mountподивитися , що в даний час встановлюється , де.
grawity

Ти правий! Дивіться це: i.imgur.com/pcVpo1o.png
haboutnnah

Це дійсно акуратно @grawity, i.imgur.com/8QuR0FK.png
haboutnnah

6
@haboutnnah Ваш знімок екрана підтверджує, що /devце віртуальна файлова система з використанням devfsдрайвера, тоді як вона /etcє частиною /файлової системи з використанням apfsдрайвера. Тому причина catбуде читати одне, а не інше - це різниця між драйверами apfsта devfs.
kasperd
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.