我需要创建一个项目,其中一个主程序创建一个给定数量的子进程,每个子启动exec,有2种类型的子进程,他们使用消息队列通信。每一秒所有的孩子都必须发送他们的状态和情况(如果你想了解更多的信息是什么信息需要让我知道)的主程序,我的问题是:所有的子程序如何将信息发送到主程序,而不会因为子程序正在等待/写入消息队列中的消息而得到“中断的系统调用”?
char *receiveMessage(int msgQId, long tipo) {
my_msg_buf msgBuf;
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, NULL );
while(1)
if (msgrcv(msgQId, (void *)&msgBuf, MAX_LINE_LENGTH, tipo, IPC_NOWAIT) == -1) {
if(errno != ENOMSG && errno != EINTR){
fprintf(stderr, "Ricevuto errore: %s\n", strerror(errno));
return NULL;
}
if(errno == ENOMSG)
return NULL;
}else break;
sigprocmask(SIG_UNBLOCK, &mask, NULL );
return strdup(msgBuf.testo);
}
我尝试使用循环等待消息,如果errno等于EINTR,则继续循环,但它似乎不起作用,子进程似乎永远不会结束。我还考虑在每个子进程中设置一个内部计时器,但我不知道如何处理消息队列,以及在执行过程中在哪里检查时间。
1条答案
按热度按时间r55awzrz1#
我以前在实际的商业产品中使用过IPC消息队列。
我不需要使用信号,而是使用
nanosleep
来等待,这样就避免了EINTR
的混乱。下面是一些 backbone 代码,它只使用了一个消息队列和几种消息类型(一个用于主,一个用于每个港口,一个用于每个船舶)。
它允许:
1.与所有船舶和港口通信的主要过程。
1.任何一个港口都可以与其他港口和所有船只通信。
1.任何一艘船都能与其他船只和所有港口通信。
在下面的代码中,我展示了一些港口代码。船舶代码将是类似的。同样,主进程代码也将是类似的。
代码是 backbone /不完整的。但是,它显示了基本的机制。
我为港口数据创建了一个单独的结构体,它同时用于消息中的港口"当前状态"数组 * 和 *。
最好将港口当前状态和港口特定数据的类型分开,也就是说,我们可以使用
struct harbor_state
和struct harbor_msg
来代替struct harbor
。不管怎样,这是代码。它编译了,但没有测试。它被注解了:
但是每艘船都必须与每个港口通信,这样我就可以结束成千上万的管道,但是我怎么能在每个"船"和"港口"过程中经过一定时间后中断执行呢?-瓦塞托
不幸的是,拥有"数千个管道"意味着拥有数千个 * 进程 *。这不会 * 伸缩 *。任何数量的线程/进程超过一定数量(例如16个左右),系统将花费大部分时间在它们之间进行上下文切换。
因此,另一个不同的模型是"工作线程"模型。定义处理消息的
N
线程。这里N
相对较小(例如16)。每个线程都从相同的msgtyp
中提取消息,进行处理和循环。使用线程比使用进程更好,或者使用一些拥有一定数量线程的进程。
所有这一切都更多地取决于船舶拥有哪些数据,港口拥有哪些数据,以及它们之间如何交互,因此,我们需要了解实际数据的细节,什么动作触发了船舶到船舶/港口的消息,以及/或者港口到船舶/港口的消息。