Если поток-обработчик блокирован (например, в ожидании ресурса), то поток, получивший сообщение разблокирования, должен его разбудить. Когда поток-обработчик активизируется, он должен проверить состояние флага _NTO_MI_UNBLOCK_REQ и, если флаг установлен, дать ответ о ненормальном завершении. Если флаг сброшен, то поток может спокойно выполнять все, что ему необходимо для нормальной обработки запроса.
В противном случае, если поток-обработчик активен, он должен периодически проверять «флаг, выставляемый в его отношении» потоком, принимающим сообщение разблокирования, и если флаг установлен в 1, он должен ответить клиенту с кодом ошибки. Заметьте, что это всего-навсего оптимизация: в неоптимизированном случае поток-обработчик постоянно вызывал бы функцию
Обмен сообщениями в сети
Чтобы не вносить излишней путаницы, до сих пор я избегал вопроса о применении обмена сообщениями в сети, хотя реально это основополагающий фактор гибкости QNX/Neutrino!
Все, что вы узнали из книги до этого момента, применимо и к передаче сообщений по сети.
Ранее в этой главе я демонстрировал пример:
#include
#include
int main (void) {
int fd;
fd = open("/net/wintermute/home/rk/filename", O_WRONLY);
write(fd, "Это обмен сообщениями\n", 24);
close(fd);
return(EXIT_SUCCESS);
}
В то время, я говорил, что это был пример «обмена сообщениями в сети». Клиент соединяется с сервером, определяемым тройкой ND/PID/CHID (и который оказывается на другом узле), а сервер выполняет на своем канале
Теперь, когда мы уже рассмотрели в подробностях особенности локального обмена сообщениями, мы можем более углубленно обсудить, как осуществляется передача сообщений в сети. И хотя это обсуждение может показаться сложным, на самом деле все сводится к двум этапам: этапу разрешения имен и этапу собственно передачи сообщений.
Вот рисунок, иллюстрирующий эти этапы:
Обмен сообщениями в сети. Отметьте, что модуль qnet разделен на две части.
На данном рисунке наш узел называется magenta
, а целевой узел по аналогии с примером называется wintermute
.
Рассмотрим взаимодействия, которые происходят, когда программа-клиент использует qnet
, чтобы обратиться к серверу через сеть:
1. Функции /net
. (Имя /net
— имя по умолчанию, объявляемое администратором qnet
— см. документацию по QNX/Neutrino, раздел npi-qnet
). Клиент понятия не имеет, кто именно отвечает за конкретное имя пути, поэтому он соединяется с администратором процессов (шаг 1), чтобы выяснить, кому принадлежит ресурс. Это выполняется автоматически и не зависит от того, передаем ли мы сообщения по сети или нет. Поскольку все ресурсы, имена которых начинаются с /net
, принадлежат администратору qnet
, администратор процессов отвечает клиенту, что относительно этого имени пути надо спросить администратор qnet
.
2. Клиент теперь посылает сообщение потоку администратора qnet
, надеясь, что тот будет способен обработать запрос. Однако администратор qnet
на этом узле не может предоставить клиенту конечный сервис, поэтому он сообщает клиенту, что тот должен обратиться к администратору процессов на узле wintermute
. (Это делается специальным перенаправляющим сообщением, в котором содержатся ND/PID/CHID сервера, к которому надо обратиться взамен.) Это перенаправление также автоматически обрабатывается клиентской библиотекой.