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

на главную - закладки

Жанры

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

Кёртен Роб

Шрифт:

Обмен специализированными сообщениями происходит в функции CLID_IPC. Она берет значение глобальной переменной CLID_IPCData и пробует переслать его серверу, используя функцию QNX4 Send.

Специализированные сообщения могут быть обработаны о из двух способов. Можно:

1. транслировать их в стандартные вызовы функций POSIX основанные на файловых дескрипторах;

2. инкапсулировать их в сообщение типа devctl, либо в специализированное сообщение, используя тип _IO_MSG.

В обоих случаях вы перестраиваете клиента на обмен сообщениями стандартными

для администраторов ресурсов средствами. Как? У вас нет файлового дескриптора? Есть только идентификатор соединения? Или наоборот? Ну, это как раз не проблема. В QNX/Neutrino дескриптор файла в действительности является идентификатором соединения!

Трансляция сообщений в стандартные вызовы POSIX на основе файловых дескрипторов

В случае CLID-сервера это не вариант. Не существует стандартного POSIX-вызова на основе файлового дескриптора, который мог бы «добавить к администратору ресурса CLID пару NPA/NXX». Однако, существует стандартный механизм devctl, так что если ваши отношения клиент/сервер требуют такой формы, смотрите ниже.

Прежде чем броситься реализовывать этот подход (трансляцию в стандартные сообщения на основе файловых дескрипторов), давайте остановимся и подумаем, где это может оказаться полезным. В аудиодрайвере QNX4 вы могли бы использовать нестандартные сообщения для передачи аудиоданных администратору и от него. При ближайшем рассмотрении здесь, для задачи блочной передачи данных, вероятно, наиболее бы подошли функции read и write. Установку частоты оцифровки, с другой стороны, можно было бы гораздо удачнее реализовать с применением функции devctl.

Хорошо, но ведь не каждое взаимодействие клиент/сервер сводится к блочной передаче данных (тот же сервер CLID — тому пример).

Трансляция сообщений в вызовы devctl или _IO_MSG

Итак, возник вопрос — как выполнять операции управления? Самый простой способ состоит в применении POSIX-вызова devctl. Наш пример из библиотеки CLID примет вид:

/*

 * CLID_AddSingleNPANXX(npa, nxx)

*/

int CLID_AddSingleNPANXX(int npa, int nxx) {

 struct clid_addnpanxx_t msg;

 checkAttach; // Оставить или нет — дело вкуса

 msg.npa = npa;

 msg.nxx = nxx;

 return

(devctl(clid_pid, DCMD_CLID_ADD_NPANXX,

&msg, sizeof(msg), NULL));

}

Как видите, операция относительно безболезненная. (Для тех, кто не любит devctl за то, что приходится отправлять в обе стороны блоки данных одного и того же размера, см. ниже обсуждение сообщений _IO_MSG.). Опять же, если вы пишете программу, которая должна работать в обеих операционных системах, вам следует выделить функцию обмена сообщениями в отдельный библиотечный модуль и предоставить несколько вариантов реализации, в зависимости от применяемой операционной системы.

Реально мы убили двух зайцев:

1. отказались от глобальной переменной и стали собирать сообщения на основе стековой переменной — это делает нашу программу безопасной в многопоточной среде (thread- safe);

2. передали

структуру данных нужного размера вместо структуры данных максимального размера, как мы это делали в предыдущем примере с QNX4.

Заметьте, что нам пришлось определить константу DCMD_CLID_ADD_NPANXX — в принципе, мы могли бы для этих же целей применить константу CLID_MsgAddSingleNPANXX (сделав соответствующее изменение в заголовочном файле), но я просто хотел подчеркнуть тот факт, что эти две константы не являются одинаковыми.

Второй убитый заяц заключался в том, что мы передали «структуру данных нужного размера». На самом деле, мы тут немножко приврали. Обратите внимание на то, что функция devctl имеет только один параметр размера (четвертый, который мы установили в

sizeof(msg)
). Как на самом деле происходит пересылка данных? Второй параметр функции devctl содержит команду для устройства (поэтому и «DCMD»). Двумя старшими битами команды кодируется направление, которое может быть одним из четырех:

1. «00» — передачи данных нет;

2. «01» — передача от драйвера клиенту;

3. «10» — передача от клиента драйверу;

4. «11» — двунаправленная передача.

Если вы не передаете данные (то есть достаточно просто команды) или передаете их в одном направлении, то применение функции devctl — прекрасный выбор. Интересен тот вариант, когда вы передаете данные в обоих направлениях. Интересен он тем, что, поскольку у функции devctl только один параметр размера, обе пересылки данных (как драйверу, так и от драйвера) передадут весь буфер данных целиком! Это хорошо в том частном случае, когда размеры буферов «ввода» и «вывода» одинаковы, но представьте себе, что буфер принимаемых драйвером данных имеет размер в несколько байт, а буфер передаваемых данных гораздо больше. Поскольку у нас есть только один параметр размера, мы вынуждены будем каждый раз передавать драйверу полный буфер данных, хотя требовалось передать всего несколько байт!

Эта проблема может быть решена применением «своих собственных» сообщений на основе общего механизма управляющих последовательностей, поддерживаемого в сообщениях типа _IO_MSG.

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

Первое, что вы должны сделать при использовании сообщений типа _IO_MSG — это определить ваши «специальные» сообщения. В этом примере мы определим два таких типа и последуем стандартной модели сообщений администратора ресурсов: один тип будет сообщением ввода, другой — вывода.

typedef struct {

 int data_rate;

 int more_stuff;

} my_input_xyz_t;

typedef struct {

 int old_data_rate;

 int new_data_rate;

 int more_stuff;

} my_output_xyz_t;

typedef union {

 my_input_xyz_t i;

 my_output_xyz_t o;

} my_message_xyz_t;

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

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

На границе империй. Том 10. Часть 2

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
5.00
рейтинг книги
На границе империй. Том 10. Часть 2

Маяк надежды

Кас Маркус
5. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Маяк надежды

Законы Рода. Том 3

Flow Ascold
3. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 3

Бастард Императора. Том 8

Орлов Андрей Юрьевич
8. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 8

Первый среди равных. Книга III

Бор Жорж
3. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
6.00
рейтинг книги
Первый среди равных. Книга III

Восход. Солнцев. Книга I

Скабер Артемий
1. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга I

На границе империй. Том 7. Часть 5

INDIGO
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 7. Часть 5

Real-Rpg. Еретик

Жгулёв Пётр Николаевич
2. Real-Rpg
Фантастика:
фэнтези
8.19
рейтинг книги
Real-Rpg. Еретик

Отмороженный 3.0

Гарцевич Евгений Александрович
3. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный 3.0

Газлайтер. Том 3

Володин Григорий
3. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 3

СД. Том 13

Клеванский Кирилл Сергеевич
13. Сердце дракона
Фантастика:
фэнтези
6.55
рейтинг книги
СД. Том 13

Хорошая девочка

Кистяева Марина
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Хорошая девочка

Вторая жизнь майора. Цикл

Сухинин Владимир Александрович
Вторая жизнь майора
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Вторая жизнь майора. Цикл