Вот содержимое записи точки монтирования (взято из <sys/iofunc.h>
):
typedef struct _iofunc_mount {
uint32_t flags;
uint32_t conf;
dev_t dev;
int32_t blocksize;
iofunc_funcs_t *funcs;
} iofunc_mount_t;
Поле flags содержит только один флаг — IOFUNC_MOUNT_32BIT. Этот флаг указывает на то, что параметр offset в OCB и параметры nbytes и inode в атрибутной записи являются 32-разрядными. Заметьте, что вы можете определять ваши собственные флаги в поле flags, используя биты, определенные константой IOFUNC_MOUNT_FLAGS_PRIVATE.
Поле conf содержит следующие флаги:
IOFUNC_PC_CHOWN_RESTRICTED
Указывает, что файловая система является «chown-ограниченной», то есть никто, кроме суперпользователя (root), не может применять к файлам операцию chown().
IOFUNC_PC_NO_TRUNC
Указывает на то, что файловая система не выполняет усечение имен.
IOFUNC_PC_SYNC_IO
Указывает на то, что файловая система поддерживает синхронные операции ввода-вывода.
IOFUNC_PC_LINK_DIR
Указывает на то, что допускается создание/уничтожение связей (linking/unilnking) для каталогов.
Поле dev содержит номер устройства и описывается ниже в параграфе «О номерах устройств, индексных дескрипторах и нашем друге rdev».
Поле blocksize описывает типовой для данного устройства размер блока в байтах. Например, для дисковых устройств типовым значением будет 512.
И наконец, поле funcs указывает на следующую структуру (взято из <sys/iofunc.h>):
typedef struct _iofunc_funcs {
unsigned nfuncs;
IOFUNC_OCB_T *(*ocb_calloc)(
resmgr_context_t *ctp, IOFUNC_ATTR_T *attr);
void (*ocb_free)(IOFUNC_OCB_T *ocb);
} iofunc_funcs_t;
Как и в таблицах функций установления соединения и ввода/вывода, поле nfuncs должен содержать текущий размер таблицы. Используйте для этого константу _IOFUNC_NFUNCS.
Указатели на функции ocb_calloc и ocb_free могут быть заполнены адресами функций, которые следует вызывать всякий раз при создании и уничтожении OCB. Зачем вам могут понадобиться эти функции — мы обсудим это чуть позже, когда будем говорить о расширении OCB.
Запись точки монтирования содержит поле с именем dev. Атрибутная запись содержит два поля: inode и rdev. Давайте рассмотрим их взаимосвязь на примере традиционной дисковой файловой системы. Файловая система монтируется на блок- ориентированном устройстве (которое представляет собой весь диск целиком). Это блок-ориентированное устройство может называться, скажем, /dev/hd0
(первый жесткий диск в системе). На этом диске может быть несколько разделов, один из которых вполне может называться /dev/hd0t77
(первый раздел файловой системы QNX на этом конкретном устройстве). И, наконец, на этом разделе может находиться произвольное число файлов, один из которых может иметь имя /hd/spud.txt
.
Поле dev («device number» — «номер устройства») содержит число, уникальное для узла, на котором зарегистрирован данный администратор ресурсов. Поле rdev — значение dev для корневого устройства (root device). И, наконец, поле inode — порядковый номер файла.
Попробуем соотнести это с нашим примером дисковой системы. В приведенной ниже таблице приведен ряд чисел; взглянем на таблицу, а потом посмотрим, откуда появились эти номера и как они соотносятся.
Устройство | dev | inode | rdev |
---|---|---|---|
/dev/hd0 | 6 | 2 | 1 |
/dev/hd0t77 | 1 | 12 | 77 |
/hd/spud.txt | 77 | 47343 | - |
Для «сырого» блок-ориентированного устройства /dev/hd0
значения dev и inode назначил администратор процессов (значения 6 и 2 в таблице, см. выше). Администратор ресурсов при старте получил для устройства уникальное значение rdev (число 1).
Для раздела /dev/hd0t77
значение dev взялось из значения rdev «сырого» блок-ориентированного устройства (та самая 1). Значение inode было выбрано администратором ресурсов как уникальное в пределах rdev. Так появилась цифра 12. Наконец, значение rdev было также выбрано администратором ресурсов — здесь разработчик администратора выбрал значение 77, потому что оно соответствует типу раздела.
И наконец, для файла /hd/spud.txt
, значение dev (77) было взято из значения rdev для раздела. Значение inode было выбрано администратором ресурса (в случае файла номер выбирается так, чтобы соответствовать некоторому внутреннему представлению файла — конкретное число не имеет значения, лишь бы оно было ненулевым и уникальным в пределах rdev). Отсюда число 47343. Для файла поле rdev не имеет значения.
Функции-обработчики
Не все вызовы обработчиков соответствуют клиентским сообщениям. Некоторые из них синтезируются ядром, а некоторые — библиотекой.
Я организовал этот раздел следующим образом:
• общие замечания;
• замечания о функциях установления соединения;
• алфавитный список сообщений установления соединения и ввода/вывода.
Общие замечания
Каждой функции-обработчику передается внутренний контекстный блок (параметр ctp), который следует рассматривать как «только для чтения», за исключением поля iov. Как это уже упоминалось в параграфе «Внутренний контекстный блок resmgr_context_t
», этот контекстный блок содержит несколько интересных вещей. Также, каждой функции передается указатель на сообщение (аргумент msg). Вы будете активно использовать этот указатель, поскольку он содержит параметры, которыми его для вас заполнил клиентский библиотечный вызов. Функция, которую вы пишете, должна возвращать некоторое значение (все функции описаны как возвращающие int
).