Примечание
Управляющая структура пула потоков описана так:
typedef struct _thread_pool thread_pool_t;
struct _thread_pool {
thread_pool_attr_t pool_attr;
unsigned created;
unsigned waiting;
unsigned flags;
unsigned reserved[3];
};
3. Последний шаг в процедуре запуска пула потоков:
int thread_pool_start(void* pool);
где pool— это указатель, возвращаемый thread_pool_create(). [40] Вы спросите, почему указатель, возвращаемый thread_pool_create() , имеет тип thread_pool_t* , а получающий его параметр thread_pool_start() определен как void* ? Это или неаккуратность разработчиков QNX, или глубокая сермяжная правда, которую мы пока не понимаем.
При успешном завершении (которого почти никогда не происходит, за исключением значения флага 0; об этом см. выше) функция возвращает EOK, в противном случае (что происходит гораздо чаще) — значение -1.
4. Другие, относящиеся к библиотеке динамического пула потоков функции, которые целесообразно посмотреть в документации QNX (но которые в силу различных обстоятельств используются гораздо реже):
int thread_pool_destroy(thread_pool_t* pool);
int thread_pool_control(thread_pool_t* pool, thread_pool_attr_t* attr,
_Uint16t lower, _Uint16t upper, unsigned flags);
int thread_pool_limits(thread_pool_t* pool,
int lowater, int hiwater, int maximum, int increment, unsigned flags);
QNX вводит технику программирования, которая единообразно проходит сквозь всю систему. [41] Эта техника возникла не «сразу» и не случайно: ее идеология практически сложилась за почти 20 лет развития системы QNX, но не была представлена в виде формальных механизмов. В QNX 6.X оставалось только придать ей формальный вид и обеспечить ее поддержание написанием специальных библиотек.
Идея техники менеджеров ресурсов столь же проста, сколь и остроумна:
• Вся система построена на тщательно проработанной в теории (и редко используемой при построении реальных ОС) концепции - коммутации сообщений. Ядро (точнее «микроядро») операционной системы при таком подходе выступает в качестве компактного коммутатора сообщений между взаимодействующими программными компонентами. При этом взаимодействующие компоненты выступают в качестве клиента, запрашивающего услугу (ресурс), и сервера, обеспечивающего эту услугу (обслуживающего ресурс).
• Большинство системных вызовов API (в том числе все «привычные» POSIX-вызовы: open(), read(), write(), seek(), close()…) реально посылаются обслуживающему данный ресурс сервису (например, в файловую систему типа FAT32 — fs-dos) в виде сообщений уровня микроядра. Код сообщения при этом определяет тип операции (например, open()), а последующее тело сообщения — конкретные параметры запроса, зависящие от типа операции (параметры запроса пакуются в тело сообщения).
• Раз эта схема столь универсальна, единообразна и не зависит от конкретной природы ресурса, на котором обеспечивается обслуживание, то разработчики QNX предоставляют некоторый шаблон сервера, в котором на месте обработчиков стандартных POSIX-запросов находятся пустые программные заглушки. Этот шаблон и служит базовым элементом построения разнообразных серверов услуг, называемых при выполнении в такой технике «менеджерами ресурса».
• При запуске программа менеджера ресурса регистрирует свое имя (точнее имя управляемого ею ресурса) в пространстве имен файловой системы QNX (обычно в каталоге /dev, но это может быть любое место файловой системы). Теперь можно обращаться с запросами к данному менеджеру так же, как и к любому реальному файлу в файловой системе.
• Программисту, пишущему свой драйвер услуги, ресурса, устройства или псевдоустройства, остается только переопределить программное наполнение тех программных заглушек, которые ответственны за интересующие его вызовы (например, open(), read(), close()), никак не затрагивая вызовы, не обеспечиваемые этим ресурсом (например, write(), seek()и др.).
В наши цели не входит детальное обсуждение техники написания менеджеров ресурсов (этому посвящено специальное исчерпывающее руководство в составе технической документации QNX объемом более 80 страниц [42] В Интернете доступен прекрасный перевод этого документа, выполненный Владимиром Зайцевым и отредактированный к публикации Сергеем Малышевым: http://qnxclub.net/files/articles/resmgr/resmgr.pdf.gz .
). Поэтому, как и ранее с динамическим пулом потоков, начнем с примера. Приведем простейший код менеджера ресурса, который использовался нами для тестирования наследования приоритетов в QNX ( файл prior.cc ):
Читать дальше
Конец ознакомительного отрывка
Купить книгу