Выбрать главу

Как вы, наверное, догадываетесь, в OCB содержатся важные вещи по каждому открытию ресурса и по каждому дескриптору файла. Вот его содержание (взято из <sys/iofunc.h>):

typedef struct _iofunc_ocb {

 IOFUNC_ATTR_T *attr;

 int32_t       ioflag;

 CM НИЖЕ!!!    offset;

 uint16_t      sflag;

 uint16_t      flags;

} iofunc_ocb_t;

Проигнорируем пока комментарий относительно поля offset; мы вернемся к этому вопросу сразу же после данного обсуждения.

Поля структуры iofunc_ocb_t:

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, скажем так, как минимум любопытно. Посмотрите в <sys/iofunc.h>, как оно реализовано. В зависимости от того, какие у вас заданы флаги препроцессора, вы можете получить одну из шести (!) возможных раскладок поля offset. Но не беспокойтесь особо по поводу реализации — реально есть смысл рассматривать только два случая, в зависимости от того, хотите вы поддерживать 64-разрядные смещения или нет:

• если да, то поле offset 64-разрядное;

• если нет (у вас 32-разрядные целые), то поле offset — это младшие 32 бита; старшие 32 бита хранятся в поле offset_hi.

Для наших целей, если речь не идет о явном противопоставлении 32- и 64-разрядных значений, мы будем предполагать, что все смещения являются 64-разрядными (типа off_t), и платформа знает, что делать с 64-разрядными числами.

Атрибутная запись iofunc_attr_t

В то время как OCB был определен как структура данных по каждому дескриптору файла, атрибутная запись является структурой данных по каждому устройству. Вы видели, что стандартный OCB типа iofunc_ocb_t имеет элемент, называемый attr, который представляет собой указатель на атрибутную запись. Это сделано для того, чтобы у OCB был доступ к информации об устройстве. Давайте посмотрим на атрибутную запись (взято из <sys/iofunc.h>):

typedef struct _iofunc_attr {

 IOFUNC_MOUNT_T           *mount;

 uint32_t                 flags;

 int32_t                  lock_tid;

 uint16_t                 lock_count;

 uint16_t                 count;

 uint16_t                 rcount;

 uint16_t                 wcount;

 uint16_t                 rlocks;

 uint16_t                 wlocks;

 struct _iofunc_mmap_list *mmap_list;

 struct _iofunc_lock_list *lock_list;

 void                     *list;

 uint32_t                 list_size;

 СМ_НИЖЕ!!!               nbytes;

 СМ_НИЖЕ!!!               inode;

 uid_t                    uid;

 gid_t                    gid;

 time_t                   mtime;

 time_t                   atime;

 time_t                   ctime;

 mode_t                   mode;

 nlink_t                  nlink;

 dev_t                    rdev;

} iofunc_attr_t;

У полей nbytes и inode такой же набор директив условной компиляции, что и у поля offset в OCB (см. параграф «Это странное поле offset»).