надежности лучше просто передавать этот дескриптор в аргументах при порождении процесса.
Таким образом, родительский процесс при порождении дочернего процесса должен передать ему в списке аргументов свой идентификатор и дескриптор созданного канала и косвенно, посредством вызова chroot()
, имя узла, на котором дочерний процесс запускается. После этого порожденный процесс способен правильно собрать триаду, необходимую для выполнения MsgSend()
.
Теперь обсудим проблемы, стоящие перед родительским процессом. Если мы хотим отсылать сообщения с родительского процесса на порожденный, то два из трех членов триады родительский процесс может легко получить: дескриптор узла — с помощью функции netmgr_strtond()
, а идентификатор порожденного процесса возвращается функцией spawn()
. Но вот с дескриптором канала опять появляется риск «не угадать». Кроме того, если родитель породит дочерний процесс и немедленно после этого попытается подсоединиться к каналу, который должен создать этот процесс, то, вероятнее всего, функция ConnectAttach()
вернет -1, поскольку порожденный процесс еще не успеет к тому времени создать канал. Значит, понадобится цикл на N попыток с паузой в ожидании открытия.
Не проще ли тогда просто выполнить синхронизацию? То есть родительскому процессу дождаться сообщения от дочернего процесса, которое будет означать, что порожденный процесс выполнил все необходимые действия по своему развертыванию и в частности создал канал. И теперь совершенно естественно передать в этом синхронизирующем сообщении дескриптор созданного канала. После принятия сообщения родительский процесс имеет все необходимые ему данные для выполнения функции отсылки сообщения MsgSend()
.
При подобной иерархической структуре системы по типу «родитель-ребенок» общение между порожденными процессами, если таковое требуется, обеспечивается с помощью родительского процесса. Породив один из процессов и получив от него дескриптор канала, родительский процесс может при порождении еще одного процесса передать ему полную триаду «старшего» дочернего процесса, позволяющую новому процессу установить с ним соединение.
Ниже приводится образец кода, реализующего этот подход. Обратите внимание на значение аргумента index
, задаваемое в вызовах функции ConnectAttach()
равным _NTO_SIDE_CHANNEL
. В примерах из [1], книги, безусловно, основополагающей для любого программиста под QNX 6, для упрощения изложения это значение устанавливается в 0. Однако значение, равное _NTO_SIDE_CHANNEL
, гарантирует, что возвращаемое функцией значение идентификатора соединения будет взято не из того же пространства, из которого выделяются файловые дескрипторы; в противном случае возникают проблемы, достаточно определенно обрисованные в описании функции ConnectAttach()
, приведенном в технической документации QNX.
Пример кода родительского процесса
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <sys/neutrino.h>
#include <sys/netmgr.h>
#include <spawn.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <locale.h>
int main(int argc, char **argv) {
int nid; // Дескриптор удаленного узла
int PChanid; // Идентификатор созданного канала
int CChanid; // Идентификатор канала, созданного
// порожденным процессом на удаленном узле
int coid; // Идентификатор связи с порожденным
// процессом по созданному им каналу
int rcvid; // Идентификатор отправителя полученного
// сообщения int
ErrCode; // Код ошибки
char *args[] = {
'/net/904-3/home/ZZZ/BIN/TestChild',
'pid данного процесса',
'идентификатор канала',
NULL
};
char BufName[100], Bufpid[12],
Bufchanid[12], RecBuffer[100];
char SendBuf[100] = 'привет, сынок!';
pid_t procid, childid;
struct inheritance Inhproc;
setlocale(LC_CTYPE, 'C-TRADITIONAL');
if ((PChanid = ChannelCreate(0)) == -1)
printf('Родитель: странно, но не удалось '
'создать канал
');
else printf('Родитель: канал PChanid = %i создан
', PChanid);
strcpy(BufName, 'Bed-Test');
// Передаем порожденному процессу свой pid...
args[1] = itoa(procid = getpid(), Bufpid, 10);
// ... и дескриптор канала
args[2] = itoa(PChanid, Bufchanid, 10);
InhProc flags = SPAWN_SETND | SPAWN_NOZOMBIE;
if ((nid = netmgr_strtond(BufName, NULL)) == -1) {
printf('Родитель, отсутствует %s
', BufName);
return(-1);
} else printf('Родитель: найден узел %s, его nid = %i
', BufName, nid);
InhProc nd = nid;
sprintf(BufName, '/net/Bed-Test/');
chroot(BufName);
errno = 0;
childid = spawn(args[0], 0, NULL, &InhProc, args, NULL);
ErrCode = errno;
sprintf(BufName, '/net/904-3/');
chroot(BufName);
if (childid- = -1)
printf('Родитель: не удалось породить процесс,'
' errno = %i
', ErrCode);