Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
Шрифт:
Это сработает так, как и ожидается, если сервер вызовет MsgReceive с размером буфера, скажем, 1024 байта. Так как наш клиент послал небольшое сообщение (28 байт), никаких проблем не будет.
А что если клиент отправит сообщение, превышающее по размеру 1024 байт — скажем, 1 мегабайт? Например, так:
Как сервер мог бы обработать это сообщение поизящнее? Мы могли, к примеру, сказать, что клиенту не позволяется записывать более чем n байт. Тогда функции write в клиентской Си-библиотеке пришлось бы разбивать
Другая проблема в этом примере заключается в вопросе «А каково должно быть n?»
Как вы видите, этот подход имеет следующие основные недостатки:
• Все функции, которые применяются для обмена сообщениями ограниченного размера, должны быть модифицированы в Си- библиотеке так, чтобы функция передавала запросы в виде серии пакетов. Это само по себе немалый объем работы. Также это может иметь ряд неожиданных побочных эффектов при работе в мнопоточной среде — что если первая часть сообщения от одного потока передана, и тут его вытесняет другой поток клиента и посылает свое собственное сообщение. Что будет с прерванным потоком тогда?
• Все серверы должны быть готовы к обработке сообщения максимально возможного размера. Это означает, что все серверы должны будут иметь значительные области данных, или Си-библиотека будет должна разделять большие запросы на несколько меньших, ухудшая тем самым быстродействие.
К счастью, эта проблема довольно просто обходится, причем даже с дополнительным выигрышем.
Здесь будут особенно полезны функции MsgRead и MsgWrite. Важно при этом помнить, что клиент блокирован — это означает, что он не собирается изменять данные, пока сервер их анализирует.
Функция MsgRead описана так:
Функция MsgRead позволяет Вашему серверу считать nbytes байт данных из адресного пространства заблокированного клиента, начиная со смещения offset от начала клиентского буфера, в буфер, указанный параметром msg. Сервер не блокируется, а клиент не разблокируется. Функция MsgRead возвращает число байтов, которые были фактически считаны, или возвращает -1, если произошла ошибка.
Итак, давайте подумаем, как бы мы использовали эти возможности в нашем примере с вызовом write. Библиотечная функция write создает сообщение с заголовком и посылает его серверу файловой системы
Давайте рассмотрим пример.
Пример отправки сообщения серверу fs-qnx4 с непрерывным представлением данных.
Итак, клиент решил переслать файловой системе 4Кб данных. (Отметьте для себя, что Си-библиотека добавила к сообщению перед данными небольшой заголовок — чтобы потом можно было узнать, к какому типу принадлежал этот запрос. Мы еще вернемся к этому вопросу, когда будем говорить о составных сообщениях, а также — еще более детально — когда будем анализировать работу администраторов ресурсов.) Файловая система считывает только те данные (заголовок), которые будут ей необходимы для того, чтобы выяснить тип принятого сообщения:
Теперь сервер
Обратите внимание, что операции приема сообщения задано смещение
Для записи данных в адресное пространство клиента есть аналогичная функция:
Применение функции MsgWrite позволяет серверу записать данные в адресное пространство клиента, начиная со смещения offset байт от начала указанного клиентом приемного буфера. Эта функция наиболее полезна в случаях, где сервер ограничен в ресурсах, а клиент желает получить от него значительное количество информации.