所以我有这个任务,他们告诉我必须创建一个进程树(带有number_of_children分支),将一些消息从底层工作人员发送到进程树的根,最后在工作人员退出之前,他们必须发送一个 SIGUSR1 信号扎根。经过一些(与我的问题无关)打印后,必须打印接收到的信号数量。
首先,我设置了信号处理程序,调用了这个例程(我在网上找到了它,我认为它工作得很好):
void set_signal_handler(int signo, void (*handler)(int, siginfo_t *, void *)) {
struct sigaction act;
memset(&act, '\0', sizeof(act));
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;
// set up signal handler
if (sigaction(signo, &act, NULL) < 0) {
perror ("sigaction");
exit(1);
}
}
然后我使用for循环为每个孩子创建一个未命名的管道数组,然后派生孩子,最后调用一个监视文件描述符的例程,以便我可以以非阻塞方式读取。轮询的逻辑如下:
while(open_files>0) {
int retval = poll(fds, number_of_children, 0);
// try to read only if poll does not fail
if (retval > 0) {
for(int i = 0; i < number_of_children; i++){
reading from children
}
}
}
通过这种方式,我读取了所有写入的内容(尽管 poll 有时会被信号中断)并且读取没有问题。
实际问题是,当我打印根收到的 SIGUSR1 信号时,我没有得到一致的值。在几次运行中,假设每个进程节点有 3 个子进程,我得到的值从 3 到 9(这是正确的)。有没有更安全的方法来处理信号而不是使它们变笨。
注意:经过一些研究,我知道我不能使相同类型的信号处于待处理状态(我尝试使用 sigqueue 发送信号)。我还尝试在轮询期间忽略信号,并在轮询结束时重新设置处理程序,但当然,由于信号已经被屏蔽,因此它不起作用。我还检查了一个相关的堆栈帖子,并将我的 signal_counter 声明为
volatile sig_atomic_t
,但它仍然不一致。