Skip to content

Latest commit

 

History

History
47 lines (29 loc) · 7.67 KB

file_descriptors.md

File metadata and controls

47 lines (29 loc) · 7.67 KB

Файловые дескрипторы

Источник: File Descriptors

Файловые дескрипторы

Одно из первых, что узнаёт программист UNIX, — каждая запущенная программа стартует с тремя уже открытыми файлами:

Описательное имя Короткое имя Номер Описание
Standard In stdin 0 Ввод с клавиатуры
Standard Out stdout 1 Вывод в консоль
Standard Error stderr 2 Вывод ошибок в консоль

Стандартные файлы, открываемые с любой программой UNIX

Это порождает вопрос: а что вообще представляет собой открытый файл? Значение, возвращаемое вызовом open, называется файловым дескриптором и по сути является индексом в массиве открытых файлов, который хранит ядро.

Файловые дескрипторы связывают абстракцию, предоставляемую драйверами устройств, с файловым интерфейсом, предоставляемым пользователю

Файловые дескрипторы — это индекс в таблице файловых дескрипторов, хранимой ядром. Ядро создаёт файловый дескриптор в ответ на вызов open и связывает его с некоей абстракцией лежащего под ней файлоподобного объекта — будь то реальное аппаратное устройство, файловая система или что-то ещё. В результате вызовы read или write процесса, ссылающиеся на этот дескриптор, маршрутизируются ядром в нужное место, чтобы в итоге сделать что-то полезное.

Короче говоря, файловый дескриптор — это шлюз в абстракции ядра, описывающие лежащее под ним оборудование.

Уровни абстракции

Начиная с самого низкого уровня, операционная система требует от программиста создания драйвера устройства, чтобы иметь возможность взаимодействовать с аппаратным устройством. Драйвер пишется под API, предоставляемый ядром, и предоставляет набор функций, вызываемых ядром в ответ на различные запросы. В упрощённом примере выше драйверы предоставляют функции read и write, вызываемые в ответ на аналогичные операции над файловым дескриптором. Драйвер устройства знает, как преобразовать эти родовые запросы в специфичные команды конкретного устройства.

Чтобы предоставить абстракцию в user-space, ядро даёт файловый интерфейс через так называемый слой устройств. Физические устройства хоста представлены файлами в специальной файловой системе вроде /dev. В UNIX-подобных системах узлы устройств имеют так называемые старший (major) и младший (minor) номера, позволяющие ядру связывать конкретные узлы с их драйверами. Их можно увидеть через ls:

$ ls -l /dev/null /dev/zero /dev/tty
crw-rw-rw- 1 root 1, 3 Aug 26 13:12 /dev/null
crw-rw-rw- 1 root 5, 0 Sep  2 15:06 /dev/tty
crw-rw-rw- 1 root 1, 5 Aug 26 13:12 /dev/zero

Это подводит нас к файловому дескриптору — «ручке», через которую user-space общается с устройством. В широком смысле при open файла ядро использует информацию пути, чтобы связать файловый дескриптор с чем-то, что предоставляет подходящие API read, write и так далее. Когда открывается устройство (/dev/sr0 выше), старший и младший номера узла устройства дают ядру информацию, нужную для поиска правильного драйвера и завершения привязки. После этого ядро знает, как маршрутизировать дальнейшие вызовы вроде read к функциям драйвера.

Обычный (неустройственный) файл работает похоже, хотя промежуточных слоёв больше. Абстракцией здесь служит точка монтирования: монтирование файловой системы выполняет двойную задачу — настраивает отображение, чтобы файловая система знала устройство, предоставляющее хранилище, а ядро знало, что файлы, открываемые под этой точкой монтирования, должны направляться в драйвер файловой системы. Как и драйверы устройств, файловые системы пишутся под конкретный генерический API файловых систем, предоставляемый ядром.

В реальной жизни картину усложняют и другие слои. Например, ядро прилагает большие усилия, чтобы кешировать как можно больше данных с дисков в иначе свободной памяти — это даёт множество преимуществ по скорости. Оно также старается организовать доступ к устройствам максимально эффективно: например, упорядочивать дисковые обращения так, чтобы физически близкие данные извлекались вместе, даже если запросы приходили не последовательно. Более того, многие устройства принадлежат более генерическим классам вроде USB или SCSI, предоставляющим собственные слои абстракции. Так что файловые системы пишут не напрямую на устройства, а через множество этих слоёв. Понять ядро — значит понять, как все эти API соотносятся и сосуществуют.


файловые дескрипторы ядро