QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович
Шрифт:
Интервал:
Закладка:
ChannelDestroy(Pchanid);
ConnectDetach(CChanid);
return(0);
}
Пример кода порожденного процесса
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <process.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>
#include <errno.h>
#include <locale.h>
int main(int argc, char **argv) {
int nid; // Дескриптор текущего узла
int CChanid; // Идентификатор созданного канала
int coid; // Идентификатор связи с родителем
// по созданному им каналу
pid_t Parpid; // Идентификатор родительского процесса
int rcvid; // Идентификатор отправителя
// полученного сообщения
char BufName[100];
char SendBuf[100], RecBuf[100];
setlocale(LC_CTYPE, "C-TRADITIONAL");
if ((CChanid = ChannelCreate(0)) == -1)
printf("Ребенок: странно, но не удалось создать"
" каналn");
else
printf("Ребенок: канал CChanid = %i созданn", CChanid);
Parpid = atoi(argv[1]);
printf("Ребенок сообщает: он жив благодаря папане"
" Parpid = %in", Parpid);
strcpy(BufName, "904-3");
if ((nid = netmgr_strtond(BufName, NULL)) == -1)
printf("Ребенок: узел "%s" не найден!n", BufName);
else
printf("Ребенок: узел "%s" найден, его nid = %in", BufName, nid);
if ((coid =
ConnectAttach(nid, Parpid, atoi(argv[2]), _NTO_SIDE_CHANNEL, 0)) == -1) {
printf("Ребенок: странно, но дитя не смогло"
" установить канал связи с папанейn");
return(-1);
}
printf("Ребенок: установил связь coid = %i с процессом"
" Parpid = %i на узле %in", coid, Parpid, nid);
// Вот здесь хорошее место, чтобы выполнить все действия,
// необходимые для развертывания данного процесса
itoa(CChanid, SendBuf, 10);
errno = 0;
if (MsgSend(coid, SendBuf, 100, SendBuf, 100) == -1)
printf("Ребенок: на MsgSend() к отцу получил"
" errno = %in", errno);
else
printf("Ребенок: на MsgSend() получен отклик"
" от родителя."%s"n", SendBuf);
rcvid = MsgReceive(CChanid, RecBuf, 100, NULL);
printf("Ребенок: от папани получено сообщение:"
" "%s"n", RecBuf);
strcpy(RecBuf, "я здесь, папаня!");
if (MsgReply(rcvid, EOK, RecBuf, 100) == -1)
printf("Ребенок: почему-то не удалось ответить"
" папаше. Ау, где ты?n");
printf("Ребенок: дитятко работу закончилоn");
ChannelDestroy(CChanid);
ConnectDetach(coid);
return(0);
}
Обмен сообщениями на основе менеджера ресурсов
Описанный выше способ построения функционирующей в сети системы процессов может быть реализован далеко не всегда. Зачастую клиенту не известна полная триада, позволяющая ему создать соединение с сервером. Вспомним, что в QNX 4, где для создания связи с другим процессом был необходим его идентификатор, существовала служба пространства имен, обеспечиваемая сервером службы nameloc. Сервер объявлял свое имя в пространстве имен с помощью функции qnx_name_attach(), а затем клиент, вызвав функцию qnx_name_locate(), получал от системы идентификатор сервера, по которому мог далее с ним общаться.
Разработчики QNX 6 настоятельно рекомендуют вместо использования службы имен выполнять сервер в виде менеджера ресурсов, причем настолько настоятельно, что до версии 6.3 аналог этой службы — менеджер службы глобальных имен gns— функционировал только локально. И надо признать, что мощь и изящество менеджера ресурсов являются очень убедительным подкреплением этих рекомендаций.
При использовании механизма менеджера ресурсов процесс, выступающий в качестве сервера, регистрирует свой так называемый префикс путевого имени файла в пространстве файловых имен, после чего другие процессы (клиенты) могут открывать это имя как файл, используя стандартную библиотечную функцию open(). Получив в результате выполнения этой функции дескриптор файла, они затем могут обращаться к серверу, используя стандартные библиотечные функции С, такие как read(), write()и т.д.