Почему я могу cat / dev?

41

Я могу cat /dev, я могу ls /dev, я не могу less /dev. Почему catмне разрешен catэтот каталог, а других нет?

Картина такого поведения в зш.

haboutnnah
источник
@KamilMaciorowski, вот вывод и neofetchдля вашей информации :) i.imgur.com/3azpnDt.png
haboutnnah

Ответы:

43

Исторически (до V7 UNIX или около 1979 года) readсистемный вызов работал как с файлами, так и с каталогами. readon каталог вернул бы простую структуру данных, которую пользовательская программа проанализировала бы для получения записей каталога. Действительно, 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 и не затрагивалась в течение очень долгого времени. Часть меня подозревает, что это сохраняется по какой-то причине обратной совместимости, но это может быть так же легко, как тот факт, что никто не заботится о том, чтобы удалить функцию, так как это на самом деле ничего не вредит.

nneonneo
источник
Вероятно, последний, видя, как он был удален из большинства каталогов.
user253751
36

Меньше - средство просмотра текстовых файлов, cat - инструмент для копирования произвольных данных. Таким образом, less выполняет свою собственную проверку, чтобы убедиться, что вы не открываете что-то, что будет содержать большие объемы данных или ведет себя очень странно. С другой стороны, у cat такой проверки вообще нет - если ядро ​​позволяет вам что-то открыть (даже если это канал, устройство или что-то еще хуже), cat прочитает это.

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

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

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

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

Отказ от ответственности: я на самом деле не проводил никаких исследований на BSD или MacOS. Я просто обожаю это.

grawity
источник
Это, кажется, имеет смысл. Существуют ли другие разделы хранилища, которые отличаются от стандартной файловой системы ОС? Я предположил /etcбы, поэтому я использовал это в качестве ориентира.
haboutnnah
2
Наоборот, обычно / etc - это обычная папка, содержащая обычные файлы. Там могут быть и другие виртуальные файловые системы , хотя - бежать mountили /sbin/mountпосмотреть , что в настоящее время устанавливается , где.
Gravity
Вы правы! Смотрите это: i.imgur.com/pcVpo1o.png
haboutnnah
Это действительно здорово @grawity, i.imgur.com/8QuR0FK.png
haboutnnah
6
@haboutnnah Ваш скриншот подтверждает, что /devэто виртуальная файловая система, использующая devfsдрайвер, тогда как /etcявляется частью /файловой системы, использующей apfsдрайвер. Так что причина catбудет читать один и не другая разница между apfsи devfsдрайверами.
kasperd