Чтение онлайн

ЖАНРЫ

Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform

Кёртен Роб

Шрифт:

Указатели на функции ocb_calloc и ocb_free могут быть заполнены адресами функций, которые следует вызывать всякий раз при создании и уничтожении OCB. Зачем вам могут понадобиться эти функции — мы обсудим это чуть позже, когда будем говорить о расширении OCB.

О номерах устройств, индексных дескрипторах и нашем друге rdev

Запись точки монтирования содержит поле с именем 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
).

Значения выбираются из следующего списка:

_RESMGR_NOREPLY

Указывает библиотеке администратора ресурсов, что она не должна выполнять MsgReplyv — в предположении, что вы либо уже сделали это самостоятельно в вашей функции-обработчике, либо собираетесь сделать это несколько позже.

_RESMGR_NPARTS(n)

Указывает библиотеке администратора ресурсов при выполнении MsgReplyv возвратить n– элементный вектор ввода/вывода (он располагается в

ctp->iov
). Ваша функция ответственна за заполнение поля iov структуры ctp и возврат _RESMGR_NPARTS с корректным числом элементов.

Память под поле iov структуры ctp выделяется динамически, и ее должно быть достаточно, чтобы вместить столько число элементов массива, сколько вы записываете в iov! Детали о настройке поля nparts_max см. выше в разделе «Управляющая структура
resmgr_attr_t
».

_RESMGR_DEFAULT

Это говорит библиотеке администратора ресурсов выполнить низкоуровневую функцию по умолчанию (это другое семейство функций; не путайте их с iofunc_*_default!). Это возвращаемое значение вам вряд ли когда-нибудь пригодится. В общем случае оно заставляет библиотеку администратора ресурсов возвратить клиенту значение errno, равное ENOSYS, что означает «функция не поддерживается».

_RESMGR_ERRNO(errno)

(Устаревшее.) Данное возвращаемое значение использовалось для «инкапсуляции» значения errno в возвращаемое сообщением значение. Например, если бы клиент выдал запрос open (по записи — прим. ред.) устройству, доступному только для чтения, корректно было бы возвратить код ошибки EROFS. Поскольку данный способ сделать это считается устаревшим, вы можете возвратить код ошибки непосредственно (например, при помощи

return (EROFS);
вместо громоздкого
_RESMGR_ERRNO(EROFS);
).

_RESMGR_PTR(ctp, addr, len)

Это макрос для удобства. Он берет указатель на контекст ctp и заполняет его первый элемент IOV адресом addr и длиной len, а затем возвращает библиотеке эквивалент

_RESMGR_NPARTS(1)
. Это может быть полезно для функций, возвращающих одноэлементные IOV.

Блокировки, разблокировки и обработка составных сообщений

Мы видели клиентский взгляд на составные сообщения, когда рассматривали функцию readblock (в параграфе «Составные сообщения»). Клиент мог атомарно создать сообщение, которое содержало бы несколько «подсообщений» администратору ресурсов — в нашем примере это были сообщения, соответствующие функциям lseek и read. С точки зрения клиента две (или более) функций были как минимум атомарно переданы (и, вследствие самой сути обмена сообщениями, будут атомарно приняты администратором ресурсов). О чем мы еще не говорили, так это о том, как мы сможем гарантированно обеспечить атомарность обработки этих сообщений.

Поделиться с друзьями: