0

我想编写一个程序,使用 fork() 函数创建 N 个孩子。每个孩子将等待 0 到 3 秒,然后它将向其父母发送一个信号 SIGUSR1。Parent 处理所有这些信号。

问题是我的程序并不总是处理来自它的孩子的所有信号。如何修复它?

第二个问题:我知道我不应该在处理程序中使用 printf ,因为可能会发生不好的事情。我怎样才能替换这个指令?

主程序

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void error(char *s){
    printf("%s\n",s);
    perror("Program execution failed.");
    exit(EXIT_FAILURE);
}

volatile int N=8; //final number of children
volatile int k=0; //number of received SIGUSR1 signals

void childRequestHandler(int signo, siginfo_t* info, void* context){
    k++;
    printf("%d,Father received request from child: %d\n",k,info->si_pid);

}

int main() {
    struct sigaction act;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    act.sa_sigaction = childRequestHandler;
    if(sigaction(SIGUSR1,&act,NULL) == -1) printf("ERROR OCCURED");

    for(int i=0;i<N;i++){
        pid_t pid = fork();
        if(pid == 0) {
            execl("./child", "./child", NULL);
            error("Fork error happened\n");
        }
    }

    while (1){
        sleep(1);
    }

}

孩子.c

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>



int main() {
    time_t t;
    srand((unsigned int) getpid()+ time(NULL));


    int length_of_sleeping = rand() % 4 ;
    printf("I live: %d, sleeps %ds \n",getpid(),length_of_sleeping);
    sleep(length_of_sleeping);
    kill(getppid(),SIGUSR1);

    while(1){

    }

}

输出:

I live: 4195, sleeps 3s 
I live: 4196, sleeps 3s 
I live: 4197, sleeps 1s 
I live: 4202, sleeps 3s 
I live: 4198, sleeps 0s 
I live: 4201, sleeps 2s 
I live: 4199, sleeps 0s 
I live: 4200, sleeps 3s 
1,Father received request from child: 4198
2,Father received request from child: 4197
3,Father received request from child: 4201
4,Father received request from child: 4195
4

1 回答 1

1

当信号处理程序正在执行时,信号被阻塞。在此期间收到的所有SIGUSR1信号都不会被注意到。

您可以SA_NODEFER在建立信号时使用该标志,有关该标志的信息,请参阅手册sigaction

但是,如果您使用SA_NODEFER,请不要使用printf!这不是异步信号安全功能。有关更多信息,请参见例如有关信号安全的手册页


POSIXsigaction参考

当一个信号被 安装的信号捕获函数捕获时,在信号捕获函数sigaction()的持续时间内计算并安装一个新的信号掩码。这个掩码由当前信号掩码和传递的信号的值sa_mask,除非设置SA_NODEFERSA_RESETHAND设置,否则包括传递的信号。如果并且当用户的信号处理程序正常返回时,将恢复原始信号掩码。

[强调我的]

于 2018-04-07T15:22:37.557 回答