0

所以我有这个任务,他们告诉我必须创建一个进程树(带有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,但它仍然不一致。

4

0 回答 0