Шрифт:
Когда сервер принимает сообщение от клиента, функции сервера MsgReceive или MsgReceivev возвращают идентификатор отправителя (часто сокращенно в программах называемый «rcvid»). Этот идентификатор rcvid затем используется по отношению к заблокированному клиенту как дескриптор, позволяя серверу отправить клиенту ответ с данными, там самым разблокировав его. После использования rcvid для ответа клиенту, он перестает иметь значение для всех вызовов функций, кроме функции MsgDeliverEvent.
Дескриптор, возвращаемый функцией ConnectAttach (на клиентской стороне) и используемый для всех операций обмена данными между клиентом и сервером. Идентификатор соединения аналогичен дескриптору файла в терминах стандартной библиотеки языка Си — иными словами, когда функция open в QNX/Neutrino возвращает дескриптор файла, реально возвращается идентификатор соединения.
Принятая в QNX/Neutrino концепция, в силу которой отправляемые сообщения передаются в одном направлении, а ответы на сообщения — в другом. Основной целью реализации иерархического принципа обмена является необходимость исключения состояния взаимной блокировки потоков. Иерархический принцип реализуется назначением клиентам и серверам «уровней иерархии» и обеспечения того, чтобы сообщения передавались только на более высокий уровень иерархии. Это исключает ситуации взаимной блокировки, когда два потока посылают сообщения друг другу, потому что такая ситуация нарушила бы принцип — поток не должен отправлять сообщения другому, если тот находится на нижнем уровне иерархии.
Неблокирующее сообщение, получаемое аналогично обычному сообщению. Это сообщение является неблокирующим для отправителя; получатель же может ожидать его применением стандартных функций обмена сообщениями (MsgReceive и MsgReceivev) или же, если необходимо ждать именно импульса, то при помощи функции MsgReceivePulse. В то время как большинство сообщений обычно посылаются от клиента к серверу, импульсы обычно пересылаются в противоположном направлении, чтобы не нарушать иерархический принцип обмена (это вызвало бы взаимную блокировку). Сравните с сигналом.
Операционная система QNX/Neutrino может быть настроена для функционирования на различных аппаратных средствах без необходимости в лицензии на исходный код. Для этого необходимо предусмотреть в начальном загрузчике возможность обработки исходящих вызовов ядра. Механизм исходящих вызовов ядра позволяет разработчику добавлять в систему свой код, «знающий» о специфике оборудования — например, как опрашивать контроллер прерывания о том, какое прерывание произошло, или о том, как настроить таймер на регулярную генерацию прерываний, и т.п. Это очень подробно изложено в книге «Building Embedded Systems» («Построение встраиваемых систем»).
Абстрактный объект, через который сервер принимает сообщения. Это тот же самый объект, к которому клиент подключается, чтобы отправить сообщение серверу. При создании канала с помощью ChannelCreate возвращается идентификатор канала («channel ID», сокращенно «chid») — тот самый идентификатор канала, который назначается администратором ресурса каждой объявляемой им точке монтирования.
При карусельной диспетчеризации поток использует процессор до тех пор, пока либо не будет готов к работе поток с более высоким приоритетом, либо пока этот поток добровольно не освободит процессор, либо пока не истечет выделенный данному потоку квант времени. Если потоков с более высоким приоритетом нет, поток добровольно не освобождает процессор, и не существует других потоков с тем же самым приоритетом, поток будет выполняться вечно. Если удовлетворены все вышеизложенные условия, за исключением того, что становится готов к работе другой поток с таким же самым приоритетом, то предыдущий поток освободит процессор после того, как истечет выделенный ему квант времени — таким образом, другой поток будет иметь шанс на обслуживание. Сравните с диспетчеризацией FIFO.
Архитектура обмена сообщениями в QNX/Neutrino имеет клиент- серверную структуру. Клиент является тем, кто запрашивает услугу у определенного сервера. Обычно клиент запрашивает услуги, используя функции, ориентированные на работу со стандартными файловыми дескрипторами (например, lseek). Эти функции являются синхронными в том отношении, что вызов, сделанный клиентом, не возвращает ответ до тех пор, пока не будет завершена обработка запроса сервером. Любой поток может являться одновременно и клиентом, и сервером.