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

на главную

Жанры

QNX/UNIX: Анатомия параллелизма
Шрифт:

// здесь создается путевое имя для менеджера

id = resmgr_attach(dpp, &resmgr_attr, "/dev/prior",

_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &attr);

if (id == -1)

perror("attach name"), exit(EXIT_FAILURE);

ctp = dispatch_context_alloc(dpp);

// старт менеджера как бесконечный цикл ожидания

// поступающих сообщений для диспетчеризации:

while (true) {

if ((ctp = dispatch_block(ctp)) == NULL)

perror("block error"), exit(EXIT_FAILURE);

dispatch_handler(ctp);

}

}

Здесь

использован простейший однопоточный шаблон написания менеджера. Менеджер отрабатывает только одну команду
read
(т.e. отрабатывает нестандартно; в целевом коде все остальные команды, например
open
, он отрабатывает по умолчанию). По команде
read
менеджер: а) возвращает в виде текстовой строки, завершающейся переводом строки, текущий приоритет (помните, что в QNX приоритеты «плавают»?), на котором он обрабатывает запрос, и б) делает это через один запрос, в оставшиеся разы создавая на всякий случай (почему «на всякий», сейчас станет понятно) ситуацию EOF (конца файла). Выполним несколько команд:

# prior &

# ls -l /dev/pr*

nrw-rw-rw- 1 root root 0 Dec 18 17:13 /dev/prior

Все соответствует нашим ожиданиям: менеджер ресурса запущен, он зарегистрировал в пространстве имен свое имя

/dev/prior
, по которому мы можем к нему обращаться. Теперь выполним обращения к нашему... «устройству». Для этого мы сознательно не станем пользоваться каким-либо специальным клиентом, запрашивающим наш созданный сервис, а воспользуемся самыми заурядными командами UNIX, которые ничего не подозревают о существовании нового сервиса:

# cat /dev/prior

10

# nice -n-5 cat /dev/prior

15

# nice -n-19 cat /dev/prior

29

Вот здесь и проявляется исключительная мощь техники написания менеджера ресурса: созданная минимальными средствами серверная служба «камуфлирует» специфичный QNX-механизм передачи сообщений микроядра под стандартные POSIX-запросы к файловой системе (

open
,
read
и т.д.), и стандартные команды UNIX «не видят» отличий новой серверной службы от стандартных файлов (устройств) UNIX. Вот для достижения такой полной совместимости с «привычками» команд UNIX и созданы «на всякий случай» те особенности формата, возвращаемого запросами
read
, о которых упоминалось выше.

Теперь разработка, например драйвера некоторого специфичного устройства, перемещается из области шаманства «системного программиста» в область деятельности проблемного программиста, да и выполняется привычными высокоуровневыми инструментальными средствами, например С++.

Примечание

Пользуясь случаем, именно здесь уместно на примере созданного менеджера ресурсов продемонстрировать гибкость микроядерной архитектуры и техники менеджера ресурса, а заодно убедиться, что наследование приоритетов (критически важное свойство для систем реального времени) сохраняется при запросе к удаленному менеджеру ресурса, запущенному на другом узле сети (имя узла —

rtp
):

# on -frtp prior &

# ls -l /net/rtp/dev/pr*

nrw-rw--rw- 1 root root 0 Dec 18 17.09 /net/rtp/dev/prior

# nice -n-5 cat /net/rtp/dev/prior

15

# nice -n-19 cat /net/rtp/dev/prior

29

Многопоточный

менеджер

Следующим шагом развития техники менеджера ресурсов является многопоточный менеджер. Фактически это объединение техники менеджера ресурсов с динамическим пулом потоков, рассмотренным выше.

Реальный работающий многопоточный менеджер с сопутствующим ему обстоятельным обсуждением приводился нами в книге [4] в главе «Драйверы». Мы не станем полностью приводить здесь этот достаточно объемный текст, поскольку он отличается от ранее показанного однопоточного менеджера только несколькими строками после вот этого оператора регистрации префикса имени менеджера:

// здесь создается путевое имя для менеджера

id = resmgr_attach(dpp, &resmgr_attr, "/dev/prior",

_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &attr);

if (id == -1)

perror("attach name"), exit(EXIT_FAILURE);

Вот те несколько строк, которые, собственно, и превращают однопоточный менеджер в многопоточный:

...

thread_pool_attr_t pool_attr;

memset(&pool_attr, 0, sizeof pool_attr);

pool_attr.handle = dpp;

// это всегда остается так ...:

pool_attr.context_alloc = dispatch_context_alloc;

pool_attr.block_func = dispatch_block;

pool_attr.handler_func = dispatch_handler;

pool_attr.context_free = dispatch_context_free;

// численные параметры пула:

pool_attr.lo_water = 2;

pool_attr.hi_water = 6;

pool_attr.increment = 1;

pool_attr.maximum = 50;

thread_pool_t *tpp;

// флаг создания пула, который может принимать значения:

// POOL_FLAG_EXIT_SELF, POOL_FLAG_USE_SELF или,

// наконец, 0 и который определяет, что будет

// происходить дальше с вызывающим потоком...

if ((tpp = thread_pool_create(&pool_attr, POOL_FLAG_EXIT_SELF)) == NULL)

perror("create pool"), exit(EXIT_FAILURE);

thread_pool_start(tpp);

...

}

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

Вот такими элементарными манипуляциями мы превращаем менеджер ресурса (практически любой менеджер!) в многопоточный. С другой стороны, простота трансформации одной формы в другую подсказывает простое и эффективное решение: вначале всегда пишите одно- поточный менеджер, поскольку в отладке и понимании он намного проще, и только потом при необходимости трансформируйте его в многопоточный.

Поделиться:
Популярные книги

Моя на одну ночь

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
5.50
рейтинг книги
Моя на одну ночь

Черный Маг Императора 8

Герда Александр
8. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 8

Измена. Отбор для предателя

Лаврова Алиса
1. Отбор для предателя
Фантастика:
фэнтези
5.00
рейтинг книги
Измена. Отбор для предателя

Кодекс Крови. Книга II

Борзых М.
2. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга II

Шаг в бездну

Муравьёв Константин Николаевич
3. Перешагнуть пропасть
Фантастика:
фэнтези
космическая фантастика
7.89
рейтинг книги
Шаг в бездну

Часовая битва

Щерба Наталья Васильевна
6. Часодеи
Детские:
детская фантастика
9.38
рейтинг книги
Часовая битва

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II

Хроники странного королевства. Вторжение. (Дилогия)

Панкеева Оксана Петровна
110. В одном томе
Фантастика:
фэнтези
9.38
рейтинг книги
Хроники странного королевства. Вторжение. (Дилогия)

Часовой ключ

Щерба Наталья Васильевна
1. Часодеи
Фантастика:
фэнтези
9.36
рейтинг книги
Часовой ключ

Инвестиго, из медика в маги

Рэд Илья
1. Инвестиго
Фантастика:
фэнтези
городское фэнтези
попаданцы
5.00
рейтинг книги
Инвестиго, из медика в маги

Кротовский, может, хватит?

Парсиев Дмитрий
3. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
аниме
7.50
рейтинг книги
Кротовский, может, хватит?

Драконий подарок

Суббота Светлана
1. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
7.30
рейтинг книги
Драконий подарок

Очешуеть! Я - жена дракона?!

Амеличева Елена
Фантастика:
юмористическая фантастика
5.43
рейтинг книги
Очешуеть! Я - жена дракона?!

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9