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

на главную

Жанры

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

Кёртен Роб

Шрифт:

Здесь мы определили новый тип — объединение (union) из сообщений ввода и вывода — и назвали этот тип

my_message_xyz_t
. Закономерность в имени идентификатора заключается в том, что это сообщение относится к службе «
xyz
» какова бы она ни была. Сообщение ввода имеет тип
my_input_xyz_t
, а сообщение вывода —
my_output_xyz_t
. Отметьте, что и «ввод», и «вывод» определяются с позиции администратора ресурса: «ввод» — это данные, поступающие в администратор ресурса, а «вывод» — это данные, поступающие из него (обратно клиенту).

Нам

надо придумать какой-то вызов API для клиента — мы, конечно, можем принудить клиента «вручную» заполнять структуры
my_input_xyz_t
и
my_output_xyz_t
, но я не рекомендовал бы так делать по той причине, что API призван «отвязать» реализацию передаваемого сообщения от функциональности. Давайте предположим, что API клиента у нас такой:

int adjust_xyz(int *data_rate, int *оdata_rate,

 int *more_stuff);

Теперь мы имеем хорошо документированную функцию adjust_xyz, которая выполняет нечто полезное для клиента. Заметьте, что для передачи данных мы использовали указатели на целые числа — это просто пример реализации. Вот текст функции adjust_xyz:

int adjust_xyz(int *dr, int *odr, int *ms) {

 my_message_xyz_t msg;

 int sts;

 msg.i.data_rate = *dr;

 msg.i.more_stuff = *ms;

 sts =

io_msg(global_fd, COMMAND_XYZ, &msg, sizeof(msg.i),

sizeof(msg.o));

 if (sts == EOK) {

*odr = msg.o.old_data_rate;

*ms = msg.o.more_stuff;

 }

 return (sts);

}

Это пример применения функции io_msg (ее мы скоро опишем — это не стандартный библиотечный вызов!). Функция io_msg колдует над сборкой сообщения _IO_MSG. Чтобы уйти от проблемы функции devctl с наличием только одного параметра размера, мы дали функции io_msg два таких параметра: один — для ввода (

sizeof(msg.i)
), другой — для вывода (
sizeof(msg.о)
). Заметьте, что мы обновляем значения *odr и *ms только в том случае, когда функция io_msg возвращает EOK. Это обычный прием, и здесь он полезен потому, что передаваемые аргументы не изменятся, если команда не завершится успешно. (Это предохраняет клиентскую программу от необходимости держать копию передаваемых данных на случай несрабатывания функции.)

Последнее, что я сделал в функции adjust_xyz, — это зависимость от переменной global_fd, содержащей дескриптор файла администратора ресурса. Есть, опять же, множество способов обработки этого:

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

• Передавать от клиента дескриптор файла каждому вызову функции библиотеки API (полезно, если клиент хочет разговаривать с администратором ресурса еще и другими способами, например, стандартными POSIX-вызовами на основе файловых дескрипторов типа read, или если клиент должен уметь общаться с несколькими администраторами ресурсов).

Вот текст функции io_msg:

int io_msg(int fd, int cmd, void *msg, int isize,

 int osize) {

 io_msg_t io_message;

 iov_t rx_iov[2];

 iov_t tx_iov[2];

 int sts;

 // set up the transmit IOV

 SETIOV(tx_iov + 0, &io_msg.o, sizeof(io_msg.o));

 SETIOV(tx_iov + 1, msg, osize);

 // set up the receive IOV

 SETIOV(rx_iov + 0, &io_msg.i, sizeof(io_msg.i));

 SETIOV(r.x_iov + 1, msg, isize);

 // set up the _IO_MSG itself

 memset(&io_message, 0, sizeof(io_message));

 io_message.type = _IO_MSG;

 io_message.mgrid = cmd;

 return (MsgSendv(fd, tx_iov, 2, rx_iov, 2));

}

Отметьте несколько вещей.

В функции io_msg для «инкапсуляции» специального сообщения (передаваемого в параметре «msg») в структуру io_message использован двухкомпонентный вектор ввода-вывода IOV.

Структура io_message была предварительно обнулена, и в ней был задан тип сообщения (_IO_MSG), а также инициализировано поле cmd (это будет использовано администратором ресурса для определения типа посылаемого сообщения).

В качестве кода завершения функции io_msg использовался непосредственно код завершения MsgSendv.

Единственная «забавная» вещь, которую мы тут сделали, касается поля mgrid. QSSL резервирует для данного поля диапазон значений со специальным поддиапазоном для «неофициальных» драйверов. Этот поддиапазон ограничен значениями от _IOMGR_PRIVATE_BASE до IOMGR_PRIVATE_MAX соответственно. Если вы разрабатываете глубоко встраиваемую систему и хотите быть уверены, что ваш администратор ресурса не получит никаких неподходящих сообщений, то смело можете использовать значения из этого специального диапазона. С другой стороны, если вы разрабатываете в большей степени «настольную» или «обычную» систему, вы можете захотеть точно проконтролировать, будут ли вашему администратору ресурса приходит несоответствующие сообщения или нет. В этом случае вам нужно будет обратиться в QSSL за значением mgrid, зарезервированным специально для вас — никто, кроме вас, не должен использовать это номер. Посмотрите файл

<sys/iomgr.h>
, там представлены используемые в настоящее время диапазоны. В нашем вышепредставленном мы могли предположить, что COMMAND_XYZ базирована на _IOMGR_PRIVATE_BASE:

#define COMMAND_XYZ (_IOMGR_PRIVATE_BASE + 0x0007)

или QSSL назначила нам специальный поддиапазон:

#define COMMAND_XYZ ( IOMGR_ACME_CORP + 0x0007)

«Клиент/сервер» с использованием администратора ввода/вывода

А что если клиент, которого вы переносите, использует администратор ввода/вывода? Как адаптировать его для QNX/ Neutrino? Ответ прост: мы уже это сделали. Установив интерфейс на основе файловых дескрипторов, мы уже используем администратор ресурса. В QNX/Neutrino вам почти никогда не придется использовать интерфейс «сырых» сообщений. Почему?

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

Царь поневоле. Том 1

Распопов Дмитрий Викторович
4. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Царь поневоле. Том 1

Измена. Не прощу

Леманн Анастасия
1. Измены
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Измена. Не прощу

Мастер Разума IV

Кронос Александр
4. Мастер Разума
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер Разума IV

Король Масок. Том 1

Романовский Борис Владимирович
1. Апофеоз Короля
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Король Масок. Том 1

Мерзавец

Шагаева Наталья
3. Братья Майоровы
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
5.00
рейтинг книги
Мерзавец

Я — Легион

Злобин Михаил
3. О чем молчат могилы
Фантастика:
боевая фантастика
7.88
рейтинг книги
Я — Легион

Не грози Дубровскому! Том II

Панарин Антон
2. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том II

Девятый

Каменистый Артем
1. Девятый
Фантастика:
боевая фантастика
попаданцы
9.15
рейтинг книги
Девятый

Матабар. II

Клеванский Кирилл Сергеевич
2. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар. II

Ты нас предал

Безрукова Елена
1. Измены. Кантемировы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Ты нас предал

Девочка по имени Зачем

Юнина Наталья
Любовные романы:
современные любовные романы
5.73
рейтинг книги
Девочка по имени Зачем

Не грози Дубровскому! Том V

Панарин Антон
5. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том V

Проданная Истинная. Месть по-драконьи

Белова Екатерина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Проданная Истинная. Месть по-драконьи

Генерал Империи

Ланцов Михаил Алексеевич
4. Безумный Макс
Фантастика:
альтернативная история
5.62
рейтинг книги
Генерал Империи