Шрифт:
А как насчет самого администратора ресурсов? Как он обрабатывает операцию readblock за один прием? Мы вскоре рассмотрим это, когда будем обсуждать операции, выполняемые для каждого компонента составных сообщений.
Структуры данных уровня POSIX
К подпрограммам POSIX-уровня относятся три структуры данных. Отметьте, что пока речь идет о базовом уровне, вы можете использовать любые структуры данных, которые пожелаете; соответствия определенной структуре и содержанию требует именно уровень POSIX. Однако, преимущества, которые предоставляет POSIX-уровень, с лихвой окупают вносимые ограничения. Как мы увидим далее, вы также сможете дополнять эти структуры вашим собственным содержанием.
На рисунке приведены эти три структуры данных для случая, когда несколько клиентов используют администратора ресурсов, объявивший два устройства:
Структуры данных — общая схема.
Структурами данных являются:
Содержит информацию по каждому дескриптору файла.
Содержит информацию по каждому устройству.
Содержит информацию по каждой точке монтирования.
Когда мы обсуждали таблицы функций установления соединения и ввода/вывода, мы уже видели блоки открытого контекста и атрибутные записи — в таблицах функций ввода/вывода OCB был последним передаваемым параметром. Атрибутная запись передавалась как параметр handle (третий по счету) в функциях установления соединения. Запись точки монтирования обычно представляет собой глобальную структуру и привязывается к атрибутной записи «вручную» (в инициализационном коде, написанном вами для вашего администратора ресурса).
Структура блока открытого контекста (OCB) содержит информацию по каждому дескриптору файла. Это означает, что когда клиент выполняет вызов open и получает в ответ дескриптор файла (в противоположность коду ошибки), администратор ресурсов создает OCB и связывает его с данным клиентом. Этот OCB будет существовать до тех пор, пока клиент держит данный дескриптор файла открытым. В действительности, OCB и дескриптор файла — всегда согласованная пара. По каждому сообщению ввода/вывода от клиента библиотека администратора ресурсов автоматически ищет нужный OCB и вместе с сообщением передает его нужной функции из таблицы функций ввода/вывода. Это ответ на вопрос, зачем всем функциям ввода/вывода параметр ocb. В конце концов клиент закроет дескриптор файла (применив close), что заставит администратор ресурса отвязать OCB от дескриптора файла и от клиента. Заметьте, что клиентская функция dup просто увеличивает счетчик связей. В этом случае OCB отделяется от дескриптора файла и от клиента только тогда, когда значение счетчика связей достигнет нуля (то есть когда число вызовов close будет соответствовать числу open и dup).
Как вы, наверное, догадываетесь, в OCB содержатся важные вещи по каждому открытию ресурса и по каждому дескриптору файла. Вот его содержание (взято из
Проигнорируем пока комментарий относительно поля offset; мы вернемся к этому вопросу сразу же после данного обсуждения.
Поля структуры
attr | Указатель на атрибутную запись, связанную с данным блоком OCB. В функциях ввода/вывода вы будете встречать устоявшуюся идиому « ocb->attr »; она используется для получения доступа к элементам атрибутной записи. |
ioflag | Режим открытия, то есть как был открыт ресурс (например, «только для чтения»). Заметьте, что поле ioflag содержит режим открытия (который был передан клиентской функции open) плюс единица. Например, режим открытия O_RDONLY (значение 0) появится в поле ioflag, как значение, равное единице (1) (константа _READ из <stdio.h> ). Это позволяет трактовать два младших бита поля ioflag как флаги разрешения чтения и записи (ioflag & _READ указывает на право доступа по чтению; ioflag & _WRITE — по записи). |
offset | Текущее смещение lseek в данном ресурсе. |
sflag | Флаг разделяемого использования (см. <share.h> ), используемый с клиентской функцией вызова sopen. Возможны значения SH_COMPAT, SH_DENYRW, SH_DENYWR, SH_DENYRD, и SH_DENYN |
flags | Системные флаги. В настоящее время поддерживаются два флага: IOFUNC_OCB_PRIVILEGED, указывающий на то, что этот OCB был создан в результате сообщения установления соединения от привилегированного процесса, и IOFUNC_OCB_MMAP, указывающий, используется ли этот OCB функцией mmap на стороне клиента. На настоящий момент никаких других флагов не определено. Вы можете использовать биты, заданные в IOFUNC_OCB_FLAGS_PRIVATE, по своему собственному усмотрению. |
Если вы хотите наряду со «стандартным» OCB сохранить какие-либо дополнительные данные, то будьте покойны — OCB можно «расширять». Мы обсудим это в разделе «Дополнительно».
Поле offset, скажем так, как минимум любопытно. Посмотрите в
• если да, то поле offset 64-разрядное;
• если нет (у вас 32-разрядные целые), то поле offset — это младшие 32 бита; старшие 32 бита хранятся в поле offset_hi.
Для наших целей, если речь не идет о явном противопоставлении 32- и 64-разрядных значений, мы будем предполагать, что все смещения являются 64-разрядными (типа