Набор элементов файлов является средоточием активности для дескрипторов файлов. Они содержат информацию, необходимую для доступа к нижележащим объектам и для поддержания общих сведений.
Элемент файла является объектно-ориентированной структурой данных. Каждый элемент содержит тип и массив указателей функций, которые преобразуют общие операции с дескрипторами файлов в специфические действия, связанные с их типом. Операции, которые должны быть реализованы для каждого типа, следующие:
· чтение из дескриптора;
· запись в дескриптор;
· опрос (poll) дескриптора;
· выполнение для дескриптора операций ioctl;
· сбор статистической (stat) информации для дескриптора;
· проверка наличия для дескриптора каких-нибудь ожидающих событий kqueue;
· закрытие и возможное удаление объекта, связанного с дескриптором.
Обратите внимание, что в объектной таблице не определена процедура open. FreeBSD рассматривает дескрипторы на объектно-ориентированный манер лишь после их создания. Такой подход был избран, поскольку у различных типов дескрипторов различные свойства. Обобщение интерфейса для обработки всех типов дескрипторов во время открытия усложнило бы простой в других отношениях интерфейс. Дескрипторы vnode создаются системным вызовом open; дескрипторы сокетов создаются системным вызовом socket; дескрипторы fifo создаются системным вызовом pipe.
У каждого элемента файла есть указатель на структуру данных, которая содержит информацию, специфическую для экземпляра нижележащего объекта. Эта структура данных непрозрачна для процедур, которые манипулируют элементом файла. Ссылка на структуру данных передается при каждом вызове функции, которая реализует файловую операцию. Все состояние, связанное с экземпляром объекта, должно храниться в структуре данных этого экземпляра; нижележащим объектам не разрешается самим управлять элементом файла.
Системные вызовы read и write не принимают в качестве аргумента смещение в файле. Вместо этого каждое чтение или запись обновляют текущее файловое смещение в соответствии с числом переданных байтов. Смещение определяет положение в файле для следующего чтения или записи. Смещение может быть установлено непосредственно системным вызовом Iseek. Поскольку один и тот же файл могут открыть более чем один процесс и для каждого процесса нужно свое собственное смещение для файла, смещение не может храниться в структуре данных объекта. Поэтому каждый системный вызов open выделяет новый элемент файла, а открытый элемент файла содержит смещение.
Некоторая семантика, связанная со всеми дескрипторами файлов, проводится в жизнь на уровне дескриптора до извлечения нижележащего системного вызова. Эта семантика сохраняется в наборе флагов, связанных с дескриптором файла. Например, флаги фиксируют, открыт ли дескриптор для чтения, записи или и для чтения, и для записи. Если дескриптор помечен как открытый только для чтения, попытка записи в него будет перехвачена кодом дескриптора. Таким образом, функциям, определенным для осуществления чтения и записи, не нужно проверять действительность запроса; мы можем реализовать их, зная, что они никогда не получат недействительный запрос.
Кроме видимых приложению флагов поле флагов содержит также информацию о том, удерживает ли дескриптор разделяемую или исключительную блокировку нижележащего файла. Примитивы блокировки могли бы быть расширены для работы с сокетами так же, как с файлами. Однако дескрипторы для сокета редко ссылаются на один и тот же элемент файла. Единственным способом для двух процессов разделять один и тот же дескриптор сокета является разделение дескриптора родителя с потомком посредством разветвления процессов или путем передачи дескриптора одним процессом другому в сообщении.
У каждого элемента файла есть счетчик ссылок. У одного процесса может быть несколько ссылок на элемент в результате использования системных вызовов dup или fcntl. Структуры файла наследуются также порожденными процессами после fork, поэтому несколько различных процессов могут ссылаться на один и тот же элемент файла. В результате чтение или запись любым процессом в спаренные дескрипторы изменит файловое смещение. Эта семантика дает двум процессам возможность читать один и тот же файл или чередовать вывод в тот же самый файл. Другой процесс, независимо открывший файл, будет ссылаться на этот файл через другую структуру файла с другим файловым смещением. Эта возможность была исходной причиной существования структуры файла; структура файла предоставляет место для файлового смещения между дескриптором и нижележащим объектом.
Каждый раз при создании новой ссылки счетчик ссылок увеличивается. Когда дескриптор закрывается (в любом из случаев, когда (1) закрывается явно посредством close, (2) неявно после exec, поскольку дескриптор был помечен для закрытия при исполнении, или (3) при завершении процесса), счетчик ссылок уменьшается. Когда счетчик ссылок достигает нуля, элемент файла освобождается.
Флаг закрытия при исполнении (close-on-exec) хранится в таблице дескрипторов, а не в элементе файла. Этот флаг не разделяется между всеми ссылками на элемент файла, поскольку он является атрибутом самого дескриптора файла. Флаг закрытия при исполнении является лишь частью информации, которая хранится в таблице дескрипторов, а не разделяется в элементе файла.
- 09/11/2010 18:56 - Реализация select
- 08/11/2010 02:22 - Мультиплексирование ввода/вывода для дескрипторов
- 04/11/2010 08:33 - Блокировка дескриптора файла
- 03/11/2010 00:01 - Асинхронный ввод/вывод
- 02/11/2010 10:14 - Управление дескрипторами
- 29/10/2010 16:19 - Управление дескрипторами и службы дескрипторов
- 27/10/2010 14:46 - Метки дисков
- 27/10/2010 14:21 - Сортировка запросов дискового ввода/вывода
- 27/10/2010 11:07 - Точки входа для драйверов дисковых устройств
- 25/10/2010 03:12 - Дисковые устройства