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

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

Жанры

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

Кёртен Роб

Шрифт:

write(fd, buf, 16);

Это сработает так, как и ожидается, если сервер вызовет MsgReceive с размером буфера, скажем, 1024 байта. Так как наш клиент послал небольшое сообщение (28 байт), никаких проблем не будет.

А что если клиент отправит сообщение, превышающее по размеру 1024 байт — скажем, 1 мегабайт? Например, так:

write(fd, buf, 1000000);

Как сервер мог бы обработать это сообщение поизящнее? Мы могли, к примеру, сказать, что клиенту не позволяется записывать более чем n байт. Тогда функции write в клиентской Си-библиотеке пришлось бы разбивать

каждый «длинный» запрос на несколько запросов по n байт каждый. Неуклюже.

Другая проблема в этом примере заключается в вопросе «А каково должно быть n

Как вы видите, этот подход имеет следующие основные недостатки:

• Все функции, которые применяются для обмена сообщениями ограниченного размера, должны быть модифицированы в Си- библиотеке так, чтобы функция передавала запросы в виде серии пакетов. Это само по себе немалый объем работы. Также это может иметь ряд неожиданных побочных эффектов при работе в мнопоточной среде — что если первая часть сообщения от одного потока передана, и тут его вытесняет другой поток клиента и посылает свое собственное сообщение. Что будет с прерванным потоком тогда?

• Все серверы должны быть готовы к обработке сообщения максимально возможного размера. Это означает, что все серверы должны будут иметь значительные области данных, или Си-библиотека будет должна разделять большие запросы на несколько меньших, ухудшая тем самым быстродействие.

К счастью, эта проблема довольно просто обходится, причем даже с дополнительным выигрышем.

Здесь будут особенно полезны функции MsgRead и MsgWrite. Важно при этом помнить, что клиент блокирован — это означает, что он не собирается изменять данные, пока сервер их анализирует.

В многопоточном клиенте теоретически возможно, что в область данных заблокированного по серверу клиентского потока залезет другой поток. Такая ситуация рассматривается как некорректная (ошибка проектирования), поскольку серверный поток предполагает, что он имеет монопольный доступ к области данных клиента, пока тот заблокирован.

Функция MsgRead описана так:

#include <sys/neutrino.h>

int MsgRead(int rcvid, void *msg, int nbytes, int offset);

Функция MsgRead позволяет Вашему серверу считать nbytes байт данных из адресного пространства заблокированного клиента, начиная со смещения offset от начала клиентского буфера, в буфер, указанный параметром msg. Сервер не блокируется, а клиент не разблокируется. Функция MsgRead возвращает число байтов, которые были фактически считаны, или возвращает -1, если произошла ошибка.

Итак, давайте подумаем, как бы мы использовали эти возможности в нашем примере с вызовом write. Библиотечная функция write создает сообщение с заголовком и посылает его серверу файловой системы

fs-qnx4
. Сервер принимает небольшую часть сообщения с помощью MsgReceive, анализирует его и принимает решение, где разместить остальную часть сообщения — например, где-то в уже выделенном буфере дискового
кэша.

Давайте рассмотрим пример.

Пример отправки сообщения серверу fs-qnx4 с непрерывным представлением данных.

Итак, клиент решил переслать файловой системе 4Кб данных. (Отметьте для себя, что Си-библиотека добавила к сообщению перед данными небольшой заголовок — чтобы потом можно было узнать, к какому типу принадлежал этот запрос. Мы еще вернемся к этому вопросу, когда будем говорить о составных сообщениях, а также — еще более детально — когда будем анализировать работу администраторов ресурсов.) Файловая система считывает только те данные (заголовок), которые будут ей необходимы для того, чтобы выяснить тип принятого сообщения:

// Часть заголовков, вымышлены для примера

struct _io_write {

 uint16_t type;

 uint16_t combine_len;

 int32_t nbytes;

 uint32_t xtype;

};

typedef union {

 uint16_t type;

 struct _io_read io_read;

 struct _io_write io_write;

 ...

} header_t;

header_t header; // Объявить заголовок

rcvid = MsgReceive(chid, &header, sizeof(header), NULL);

switch (header.type) {

 ...

case _IO_WRITE:

 number_of_bytes = header.io_write.nbytes;

 ...

Теперь сервер

fs-qnx4
знает, что в адресном пространстве клиента находится 4Кб данных (сообщение известило его об этом через элемент структуры nbytes), и что эти данные надо передать в буфер кэша. Теперь сервер
fs-qnx4
может сделать так:

MsgRead(rcvid, cache_buffer[index].data,

 cache_buffer[index].size, sizeof(header.io_write));

Обратите внимание, что операции приема сообщения задано смещение

sizeof(header.io_write)
— это сделано для того, чтобы пропустить заголовок, добавленный клиентской библиотекой. Мы предполагаем здесь, что
cache_buffer[index].size
(размер буфера кэша) равен 4096 (или более) байт.

Для записи данных в адресное пространство клиента есть аналогичная функция:

#include <sys/neutrino.h>

int MsgWrite(int rcvid, const void *msg, int nbytes,

 int offset);

Применение функции MsgWrite позволяет серверу записать данные в адресное пространство клиента, начиная со смещения offset байт от начала указанного клиентом приемного буфера. Эта функция наиболее полезна в случаях, где сервер ограничен в ресурсах, а клиент желает получить от него значительное количество информации.

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

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

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

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Защитник. Второй пояс

Игнатов Михаил Павлович
10. Путь
Фантастика:
фэнтези
5.25
рейтинг книги
Защитник. Второй пояс

Счастье быть нужным

Арниева Юлия
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Счастье быть нужным

Огненный князь 3

Машуков Тимур
3. Багряный восход
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Огненный князь 3

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

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

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

Не отпускаю

Шагаева Наталья
Любовные романы:
современные любовные романы
эро литература
8.44
рейтинг книги
Не отпускаю

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

Кодекс Охотника. Книга XVIII

Винокуров Юрий
18. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVIII

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Курсант: Назад в СССР 7

Дамиров Рафаэль
7. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 7

Белые погоны

Лисина Александра
3. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны