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

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

Жанры

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

Кёртен Роб

Шрифт:

 if (resmgr_msgread(ctp, buffer, nbytes,

start_data_offset) == -1) {

free(buffer);

return (errno);

 }

 // 4) Сделать что-нибудь с данными

 process_data(off, buffer, nbytes);

 // 5) Освободить память буфера

 free(buffer);

 // 6) Установить, сколько байт
должна возвращать

 // клиентская функция «write»

 _IO_SET_WRITE_NBYTES(ctp, nbytes);

 // 7) Если данные записаны, обновить структуры

 // данных POSIX и смещение OCB

 if (nbytes) {

ocb->attr->flags |=

IOFUNC_ATTR_MTIME | IОFUNC_ATTR_DIRTY_TIME;

if (xtype == _IO_XTYPE_NONE) {

ocb->offset += nbytes;

}

 }

 // 8) Пусть библиотека сама ответит, что все в порядке

 return (EOK);

}

Как вы видите, некоторые начальные действия идентичны таковым из примера функции io_read — функция iofunc_write_verify аналогична функции iofunc_read_verify, и проверка переопределения xtype выполняется точно также.

Этап 1

Здесь мы выполняем обработку переопределения xtype, в значительной степени аналогичную примеру с io_read — за исключением того, что смещение не сохраняется в поле структуры входящего сообщения. Причина этого состоит в том, что обычной практикой для определения начального адреса поступающих от клиента данных является использование размера структуры входящего сообщения. Мы предпринимаем дополнительные усилия, чтобы удостовериться, что смещение начала данных (doffset) в коде обработки xtype является корректным.

Этап 2

Здесь мы выделяем буфер, достаточный для размещения в нем данных. Число байт, которые клиент собирается записать, представлено нам в поле nbytes объединения msg, оно заполняется автоматически Си-библиотекой клиента в коде функции write. Отметим, что у нас недостаточно памяти для обработки запроса malloc, мы возвращаем клиенту ENOMEM, чтобы он знал, почему его запрос потерпел неудачу.

Этап 3

Здесь мы применяем вспомогательную функцию resmgr_msgread для считывания всего объема данных от клиента непосредственно в только что выделенный для этого буфер. В большинстве случаев здесь вполне сошла бы функция MsgRead, но в случаях, когда сообщение является частью составного сообщения, функция resmgr_msgread выполни для нас еще и соответствующие «магические» действия (о том, почему это надо, см. раздел «Составные сообщения»). Параметры функции resmgr_msgread довольно очевидны: мы передаем ей указатель на внутренний контекстный блок (ctp), буфер, в который мы хотим поместить данные (buffer), и число байт, которые мы хотим считать (поле nbytes

объединения msg). Последний параметр — это смещение, которое мы вычислили ранее, на этапе 1. Смещение реально позволяет пропустить заголовок, помещенный туда функцией write клиентской Си-библиотеки, и сразу перейти к данным. Здесь возникает два интересных момента:

• мы могли бы взять произвольное смещение, чтобы считывать любые фрагменты данных в любом порядке, как нам заблагорассудится;

• мы могли бы использовать функцию resmgr_msgreadv (обратите внимание на символ «V» в названии) для считывания данных от клиента в вектор ввода/вывода, возможно, описывающий несколько разных буферов, подобно тому, как мы делали с буферами кэша при обсуждении файловых систем в главе «Обмен сообщениями».

Этап 4

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

Этап 5

Критически важный этап! Упустить его из виду очень просто, но это неизбежно приведет к «утечкам памяти». Обратите также внимание, как мы позаботились об освобождении памяти в случае неудачи на этапе 3.

Этап 6

Здесь мы используем макрос _IO_SET_WRITE_NBYTES для сохранения числа записанных байт, которое затем будет передано назад клиенту в качестве значения, возвращаемого функцией write. Важно отметить, что вы должны возвратить фактическое число байт! От этого зависит судьба клиента.

Этап 7

Пришло время навести лоск для функций stat, lseek и последующих write, аналогично тому, как мы это делали в нашей io_read (и опять мы изменяем смещение в ocb только в том случае, если это не сообщение типа _IO_XTYPE_OFFSET). Однако, поскольку мы выполняем запись в устройство, мы используем при этом константу IOFUNC_ATTR_MTIME вместо константы IOFUNC_ATTR_ATIME. Флаг MTIME означает «время модификации» (modification time) — функция write определенно его изменяет.

Этап 8

Последний этап прост: мы возвращаем константу EOK, которая сообщает библиотеке администратора ресурсов, что она должна ответить клиенту. Здесь наша работа закончена. Библиотека администратора ресурсов использует в ответе данные о числе записанных байт, которые мы сохранили с помощью макроса IO_SET_WRITE_NBYTES, и разблокирует клиента. Клиентская функция write возвратит число байт, записанное нашим устройством.

Простой пример функции io_devctl

Клиентский вызов devctl формально определен так:

#include <sys/types.h>

#include <unistd.h>

#include <devctl.h>

int devctl(int fd, int dcmd, void *dev_data_ptr,

 size_t nbytes, int *dev_info_ptr);

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

Sos! Мой босс кровосос!

Юнина Наталья
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Sos! Мой босс кровосос!

Черный Маг Императора 7 (CИ)

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

Я – Орк

Лисицин Евгений
1. Я — Орк
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я – Орк

Купеческая дочь замуж не желает

Шах Ольга
Фантастика:
фэнтези
6.89
рейтинг книги
Купеческая дочь замуж не желает

Возвышение Меркурия. Книга 4

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

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

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

Наследник и новый Новосиб

Тарс Элиан
7. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник и новый Новосиб

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

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

Промышленникъ

Кулаков Алексей Иванович
3. Александр Агренев
Приключения:
исторические приключения
9.13
рейтинг книги
Промышленникъ

Адъютант

Демиров Леонид
2. Мания крафта
Фантастика:
фэнтези
6.43
рейтинг книги
Адъютант

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

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

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

Я еще не князь. Книга XIV

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

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый