Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform - [43]
Функция MsgReply() может показаться очень простой (и так оно и есть), но рассмотреть ее применение было бы полезно.
Однако, вы вовсе не обязаны обязательно ответить клиенту перед приемом новых сообщений от других клиентов с помощью функции MsgReceive()! Это положение можно с успехом использовать в множестве различных сценариев.
В типовом драйвере устройства клиент может выдать запросом, который не будет обслужен в течение продолжительного времени. Например, клиент может запросить драйвер аналого-цифрового преобразователя (АЦП): «Сходи-ка принеси мне данные за следующие 45 секунд.» Драйвер АЦП не может себе позволить вывесить табличку «Закрыто» на целых 45 секунд, потому что другим клиентам тоже может срочно что-нибудь понадобиться — например, данные по другому каналу, информация о состоянии, и т.п.
В соответствии со своей архитектурой, драйвер АЦП просто поставит в очередь полученный от функции MsgReceive() идентификатор отправителя, осуществит запуск 45-секундного процесса накопления данных и снова вернется к обработке клиентских запросов. По истечении этого 45-секундного интервала, когда данные накоплены, драйвер АЦП сможет найти идентификатор отправителя, связанный с данным запросом, и ответить нужному клиенту.
Вам также может понадобиться задержаться с ответом клиенту в случае модели «сервер/субсервер» (то есть некоторые клиенты — на самом деле субсерверы). Вы можете просто запомнить идентификаторы ищущих работу субсерверов и сохранить их до поры до времени. Когда работа для субсерверов появится, тогда и только тогда вы ответите субсерверу, указав, что именно он должен сделать.
Когда дело наконец доходит до ответа клиенту, вы совершенно не обязаны передавать ему какие-либо данные. Это может использоваться в двух случаях.
Вы можете отправить клиенту ответ без данных, если единственная цель ответа — разблокировать клиента. Скажем, клиент желает быть блокированным до некоторого события, а до какого именно — ему знать не обязательно. В этом случае функции MsgReply() не потребуется никаких данных, достаточно будет только идентификатора отправителя:
>MsgReply(rcvid, EOK, NULL, 0);
Такой вызов разблокирует клиента (но не передаст ему никаких данных) и возвратит код EOK («успешное завершение»).
Как вариант, вы можете при желании возвратить клиенту код ошибки. Вы не сможете сделать это с помощью функции MsgReply(), вместо нее для этого используется функция MsgError():
>MsgError(rcvid, EROFS);
В приведенном выше примере сервер обнаруживает, что клиент пытается записать данные в файловую систему, предназначенную только для чтения, и вместо данных возвращает клиенту код ошибки (errno) EROFS.
Еще одним поводом ответить клиенту без данных (и соответствующие вызовы мы вскоре рассмотрим) может быть то, что данные уже переданы ранее (с помощью функции MsgWrite()), и больше никаких данных нет.
Почему применяются два типа вызовов? Они немного различны. В то время как обе функции MsgError() и MsgReply() разблокируют клиента, функция MsgError() при этом не передаст никаких данных, заставит функцию MsgSend() клиента возвратить -1 и установит переменную errno на стороне клиента в значение, переданное функции MsgError() в качестве второго аргумента.
С другой стороны, функция MsgReply() может передавать данные (как видно из ее третьего и четвертого параметров) и заставляет функцию MsgSend() клиента возвратить значение, переданное MsgReply() в качестве второго аргумента. Переменная errno клиента остается нетронутой.
В общем случае, если вам нужно только сообщить о результатах действия («прошло/не прошло»), лучше применять функцию MsgError(). Если бы вы возвращали данные, здесь была бы необходима функция MsgReply(). Обычно, когда вы возвращаете данные, вторым параметром функции MsgReply() будет положительное целое число, указывающее на число возвращаемых байт.
Ранее мы отметили, что для соединения с сервером функции ConnectAttach() необходимо указать дескриптор узла (Node Descriptor — ND), идентификатор процесса (process ID — PID), а также идентификатор канала (Channel ID — CHID). До настоящего момента мы не обсуждали, как именно клиент находит эту информацию.
Если один процесс создает другой процесс, тогда это просто — вызов создания процесса возвращает идентификатор вновь созданного процесса. Создающий процесс может либо передать собственные PID и CHID вновь созданному процессу в командной строке, либо вновь созданный процесс может вызвать функцию getppid() для получения идентификатора родительского процесса, и использовать некоторый «известный» идентификатор канала.
А что если у нас два совершенно чужих процесса? Это возможно, например, в том случае, если сервер создан некоей третьей стороной, а вашему приложению нужно уметь общаться с этим сервером. Реально мы должны найти ответ на вопрос: «Как сервер объявляет о своем местонахождении?»
Одно из немногих изданий на русском языке, которое посвящено старейшей глобальной компьютерной сети "Fidonet". Сатирический справочник о жизни и смерти самого древнего сетевого сообщества, которое до сих пор существует среди нас.
В пособии излагаются основные тенденции развития организационного обеспечения безопасности информационных систем, а также подходы к анализу информационной инфраструктуры организационных систем и решению задач обеспечения безопасности компьютерных систем.Для студентов по направлению подготовки 230400 – Информационные системы и технологии (квалификация «бакалавр»).
В книге американских авторов — разработчиков операционной системы UNIX — блестяще решена проблема автоматизации деятельности программиста, системной поддержки его творчества, выходящей за рамки языков программирования. Профессионалам открыт богатый "встроенный" арсенал системы UNIX. Многочисленными примерами иллюстрировано использование языка управления заданиями shell.Для программистов-пользователей операционной системы UNIX.
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса.
Применение виртуальных машин дает различным категориям пользователей — от начинающих до IT-специалистов — множество преимуществ. Это и повышенная безопасность работы, и простота развертывания новых платформ, и снижение стоимости владения. И потому не случайно сегодня виртуальные машины переживают второе рождение.В книге рассмотрены три наиболее популярных на сегодняшний день инструмента, предназначенных для создания виртуальных машин и управления ими: Virtual PC 2004 компании Microsoft, VMware Workstation от компании VMware и относительно «свежий» продукт — Parallels Workstation, созданный в компании Parallels.
Книга содержит подробные сведения о таких недокументированных или малоизвестных возможностях Windows XP, как принципы работы с программами rundll32.exe и regsvr32.exe, написание скриптов сервера сценариев Windows и создание INF-файлов. В ней приведено описание оснасток, изложены принципы работы с консолью управления mmc.exe и параметрами реестра, которые изменяются с ее помощью. Кроме того, рассмотрено большое количество средств, позволяющих выполнить тонкую настройку Windows XP.Эта книга предназначена для опытных пользователей и администраторов, которым интересно узнать о нестандартных возможностях Windows.