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

Расширение OCB

Расширение OCB

В ряде случаев у вас может возникнуть необходимость расширения OCB. Процедура эта является относительно безболезненной. Обычно OCB расширяют дополнительными флагами, характеризующими каждый конкретный open(). Один такой флаг можно было бы использовать с обработчиком io_unblock() для кэширования значения флага ядра _NTO_MI_UNBLOCK_REQ (подробнее см. параграф «Применение флага _NTO_MI_UNBLOCK_REQ» в главе «Обмен сообщениями»).

Для расширения блока OCB вам нужно будет обеспечить две дополнительных функции: одну для выделения OCB, и одну — для его освобождения. Затем вы должны будете привязать эти две функции к записи точки монтирования. (Да-да, совершенно верно — вам понадобится запись точки монтирования, даже если только для этого.) И наконец, вы должны будете определить ваш собственный тип OCB, чтобы все прототипы в программе были корректны.

Давайте рассмотрим сначала описание типа OCB, а затем уже поглядим, как переопределяются функции:

#define IOFUNC_OCB_T struct my_ocb
#include <sys/iofunc.h>

Это сообщает включаемому файлу <sys/iofunc.h>, что именованная константа IOFUNC_OCB_T теперь указывает на вашу новую усовершенствованную структуру OCB.


Очень важно иметь в виду, что ваш «расширенный» OCB должен содержать «стандартный» OCB в качестве своего первого элемента! Это так, потому что вспомогательная библиотека POSIX везде передает указатель на то, что она считает стандартным OCB — о вашем расширенном OCB ей ничего не известно, так что первый элемент данных, расположенный по этому указателю, должен соответствовать стандартному OCB.

Вот наш расширенный OCB:

typedef struct my_ocb {
 iofunc_ocb_t normal_ocb;
 int          my_extra_flags;
 ...
} my_ocb_t;

А вот код, иллюстрирующий, как переопределяются функции выделения и освобождения OCB в записи точки монтирования:

// Декларации
iofunc_mount_t mount;
iofunc_funcs_t mount_funcs;
// Задать в записи точки монтирования
// наши функции выделения/освобождения
// _IOFUNC_NFUNCS взята из .h-файла
mount_funcs.nfuncs = _IOFUNC_NFUNCS;
// Новая функция выделения OCB
mount_funcs.ocb_calloc = my_ocb_calloc;
// Новая функция освобождения OCB
mount_funcs.ocb_free = my_ocb_free;
// Настроить запись точки монтирования
memset(&mount, 0, sizeof(mount));

После этого остается только привязать запись точки монтирования к атрибутной записи:

...
attr.mount = &mount;

Функции my_ocb_calloc() и my_ocb_free() отвечают за выделение обнуленного расширенного OCB и освобождения OCB, соответственно. Вот их прототипы:

IOFUNC_OCB_T* my_ocb_calloc(resmgr_context_t *ctp,
 IOFUNC_ATTR_T *attr);
void my_ocb_free(IOFUNC_OCB_T *ocb);

Это означает, что функции my_ocb_calloc() передаются одновременно и внутренний контекст администратора ресурсов, и атрибутная запись. Функция отвечает за возврат обнуленного OCB. Функция my_ocb_free() получает OCB и отвечает за освобождение выделенной под него памяти.

Для этих двух функций имеются два интересных применения (которые ничем не связаны с выполнением расширения блока OCB):

• контроль распределения/освобождения блока OCB;

• обеспечение более эффективного распределения/ освобождения

Контроль за OCB

В этом случае вы можете просто «подключиться» к функциям распределения/освобождения и контролировать использование OCB (например, вам может быть необходимо ограничить суммарное количество OCB). Это может оказаться полезным, если вы не перехватываете функцию io_open(), но создание (и, возможно, удаление) OCB все-таки хотите контролировать.

Более эффективное распределение

Другое применение для переопределения встроенных библиотечных функций распределения/освобождения OCB может заключаться в том, что вы можете захотеть хранить OCB в свободном списке вместо использования библиотечных calloc() и free(). Если вы распределяете и освобождаете OCB с большой частотой, это может оказаться более эффективно.

Оглавление книги


Генерация: 0.299. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз