Я можу cat /dev
, можу ls /dev
, не можу less /dev
. Чому cat
я дозволяю мені cat
цей каталог, але немає інших каталогів?
Я можу cat /dev
, можу ls /dev
, не можу less /dev
. Чому cat
я дозволяю мені cat
цей каталог, але немає інших каталогів?
Відповіді:
Історично (до 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 і яка не торкалася вже дуже давно. Частина мене підозрює, що це зберігається з якоїсь причини зворотної сумісності, але це може бути так само просто, що ніхто не піклується про те, щоб видалити цю функцію, оскільки це насправді нічого не шкодить.
Менше - це переглядач текстових файлів, кішка - це інструмент для копіювання довільних даних. Так менше проводить власну перевірку, щоб переконатися, що ти не відкриваєш щось, що матиме велику кількість даних, або ведеш себе дуже дивно. З іншого боку, у кішки взагалі немає такої перевірки - якщо ядро дозволить вам щось відкрити (навіть якщо це труба чи пристрій чи щось гірше), кішка прочитає це.
То чому ОС дозволяє кішці відкривати каталоги? Традиційно в системах стилю BSD всі каталоги можна читати як файли, і саме так програми перелічували б каталог в першу чергу: просто інтерпретуючи різні структури, що зберігаються на диску.
Пізніше ці дискові структури почали відходити від дирента, використовуваного ядром: де раніше каталог був лінійним списком, пізніше файлові системи почали використовувати хештелі, B-дерева тощо. Тож читання каталогів безпосередньо вже не було простим - ядро вирощувало для цього спеціальні функції. (Я не впевнений, чи це було основною причиною, чи вони були в основному додані з інших причин, таких як кешування.)
Деякі системи BSD продовжують дозволяти вам відкривати всі каталоги для читання; Я не знаю, чи дають вони необроблені дані з диска, чи повертають вони замість них емуляційний список, або чи дозволяють драйверу файлової системи приймати рішення.
Тому, можливо, macOS є однією з тих операційних систем, де ядро дозволяє це , доки файлова система надає дані. І різниця полягає в тому, що /dev
у devfs
файловій системі, яка була написана для того, щоб це дозволити в перші дні, в той час /
як у файловій системі APFS, яка пропускала цю функцію як непотрібну в сучасний час.
Відмова: Я фактично не проводив жодних досліджень на BSD або macOS. Я просто крилату.
/etc
, що так, тому я використав це як мій орієнтир.
mount
або /sbin/mount
подивитися , що в даний час встановлюється , де.
/dev
це віртуальна файлова система з використанням devfs
драйвера, тоді як вона /etc
є частиною /
файлової системи з використанням apfs
драйвера. Тому причина cat
буде читати одне, а не інше - це різниця між драйверами apfs
та devfs
.
neofetch
для вашої інформації :) i.imgur.com/3azpnDt.png