Операционная система UNIX
Шрифт:
В то же время открытие файла, например с помощью системного вызова open(2), предусматривает ряд операций, реализованных реальной файловой системой, в которой находится специальный файл устройства (в нашем примере ufs). Одной из таких операций является трансляция имени, которая не может быть реализована файловой системой specfs, по существу являющейся виртуальной.
Решение данной проблемы рассмотрим на конкретном примере. Допустим, процесс вызывает функцию open(2) для специального файла устройства /dev/kmem для работы с виртуальной памятью ядра. Функция трансляции имени файловой системы ufs —
Рис. 5.4. Связь процесса с файлом /dev/kmem после его открытия
Однако изложенная схема является неполной и имеет ряд существенных недостатков. Дело в том, что драйвер конкретного устройства может адресоваться несколькими специальными файлами устройств, возможно, расположенными в различных физических файловых системах. В этом случае ядро бессильно определить фактическое число связей прикладных процессов с данным устройством, что может потребоваться, например, при вызове функции
Для решения этой проблемы файловая система specfs предусматривает наличие дополнительного snode, позволяющего контролировать доступ к конкретному устройству. Этот объект, получивший название общего snode (common snode), является единственным интерфейсом доступа к драйверу устройства. Для каждого устройства (драйвера устройства) существует единственный common snode, который создается при первом доступе к устройству. Каждый специальный файл устройства, в свою очередь, имеет собственный snode в файловой системе specfs и соответствующий ему vnode, а также inode физической файловой системы, где расположен специальный файл устройства, и соответствующий ему vnode.
Для связи всех этих индексных дескрипторов между собой snode имеет два поля:
Использование тех или иных vnode и связанных с ними inode или snode зависит от конкретных операций, выполняемых процессом с устройством. Большинство из этих операций не зависят от имени специального файла устройства и, соответственно, от реальной файловой системы, в которой он расположен. Эти операции выполняются через vnode, соответствующий common snode. Однако существует ряд операций, выполнение которых зависит от конкретного специального файла устройства, через который процесс взаимодействует с драйвером. Примером может служить проверка прав доступа при открытии специального файла устройства, которые расположены в vnode/inode реальной файловой системы. В этом случае используется vnode соответствующего специального файла устройства.
Схема описанной архитектуры приведена на рис. 5.5.
Рис. 5.5. Доступ к устройству через различные специальные файлы
Клоны
Как уже обсуждалось, старший номер устройства адресует драйвер, в то время как младший номер интерпретируется самим драйвером и может использоваться для различных целей. Например, используя различные младшие номера, процесс может получить доступ к разным разделам жесткого диска, обслуживаемого одним драйвером.
Во многих случаях использование различных младших номеров позволяет нескольким процессам осуществлять одновременную независимую работу с устройством (или псевдоустройством). Каждый младший номер при этом соответствует логическому драйверу, поддерживающему собственные структуры данных при работе с конкретным процессом. Типичным примером могут служить псевдотерминалы. В таких случаях процессу требуется получить доступ к устройству,
Возможным сценарием доступа к такому устройству может являться перебор различных младших номеров (соответствующих специальных файлов), пока операция
Когда процесс открывает специальный файл устройства, происходит инициализация соответствующего snode и вызов функции
53
Clone (англ.) — размножаться.
Рис. 5.6. Создание клонов с помощью зарезервированного младшего номера
Другой подход заключается в использовании специального драйвера, обеспечивающего создание клонов, — драйвера клонов (clone driver). При этом все драйверы, чье "размножение" обеспечивается таким образом, имеют один и тот же старший номер, адресующий драйвер клонов. Младший номер адресует собственно драйвер, т.е. представляет собой старший номер реального устройства, для которого создается клон. Примеры использования такой схемы можно обнаружить для драйверов системы STREAMS, с помощью которых часто реализуются сетевые протоколы и терминальный доступ, включая псевдотерминалы. Это можно заметить, рассмотрев подробный список файлов, отвечающих за эти устройства:
В данном случае старший номер всех драйверов равен 11 — это драйвер клонов. Если проанализировать информацию файла, скажем, tcp, то станет понятно, что старший номер драйвера этого протокола равен 42, для файла tcp он представлен младшим номером устройства. Когда процесс открывает этот файл, производится вызов функции