首先我要注意,我的程序只需要在Linux上工作,使用现代版本的GCC构建,因此可移植性问题在这里并不十分相关(该软件已经在低级硬件功能中使用了高度平台特定的功能)。
我遇到了一个问题,我有很多进程,父母和一些孩子。父节点具有POSIX消息队列的接收端,并且每个子节点都有一个发送端。孩子们实际上通过网络接收消息(这里的细节不相关)并将它们发送给父母,然后父母处理数据并存储它。这对我的绝大部分用例都很好。
但是,我只需添加一些功能,通过网络的客户端需要请求少量数据以及发送它,但发送仍然是主要情况。
我最初的计划是在收到这个neq类型的请求时在子节点中使用pipe()
系统调用,并让它向父节点发送特殊消息,请求父节点打开管道并将一些数据发送回儿童。然而,当我发现文件描述符只能通过域套接字而不是消息队列发送时,这种方法被缩短了。
然后我在使用bash shell时意识到可以使用/ proc / $ pidofchild / fd / $ pipefd(其中pidofchild是子进程的PID,而pipefd是写入结尾的文件描述符)在孩子的管子里抓住孩子的管道而不必将它送到我们这里。
所以,我目前的计划是让孩子发送它的PID并将其写入端的文件描述符从消息队列向下传递给父节点,然后父节点可以通过proc文件系统打开管道,写给孩子的信息然后再关闭。
然而,在线查看我无法找到任何人在任何程序中使用这种技术进行IPC的单个案例,因此我担心会有一些我没有考虑过的巨大警告并且会使整个计划失败,在通过/ proc / x / fd / y接口打开另一个进程管道时需要注意的问题是什么?
以下是我当前代码的片段(注意错误检查是为了简短而删除,也删除了不相关的行):
/* Parent Code */
static inline void ParentFunc(void)
{
struct EasySMessage *IncomingMQMessage = malloc(MQMESSAGESIZE + 1);
ssize_t MQueueMesSize = mq_receive(Globals->EasySMQueue
, IncomingMQMessage, MQMESSAGESIZE + 1, NULL);
switch(IncomingMQMessage->OpType)
{
case WriteMessage:
/* Process and write the message */
/* SNIP */
break;
case ReadMessage:
char * MyString = FormatProcFDString(IncomingMQMessage);
OpenPipeAndReply(IncomingMQMessage, MyString);
break;
default:
printf("Unrecognised easy_s message type: %d!\n"
, IncomingMQMessage->OpType);
exit(-1);
}
free(IncomingMQMessage);
}
/* Child Code */
static int ChildCode(mqd_t EasySChildMQueue, struct EasySMessage *MessageProcessed)
{
size_t SizeToSend = SizeOfMessage(MessageProcessed);
int Pipes[2];
pipe(Pipes);
MessageProcessed->Pipe = Pipes[1];
MessageProcessed->Pid = getpid();
mq_send(EasySChildMQueue, MessageProcessed, SizeToSend, 0);
ReadFromPipeAndReply(Pipes);
return 0;
}