C - 多个孩子 - 信号互相覆盖

时间:2017-05-23 17:59:36

标签: c multiprocessing signals handler

我有一个父进程在循环中使用fork创建了16个子进程。最终,每个子节点都发送一个SIGUSR1信号,该信号由父进程中的处理函数处理。

我的问题是 - 有些孩子在处理来自另一个孩子的信号时发出信号。我读到处理程序函数然后停止并处理新信号,忽略它正在处理的当前信号。

我尝试通过在处理程序函数的开头发送:kill(0,SIGSTOP)来修复它,但看起来也会停止父进程。有没有办法只向孩子们发送这个信号?

如果不可能,我的目标是否可以使用wait, waitpid and kill实现?

添加了下面的代码,我遗漏了诸如检查读取,打开等的返回值之类的内容。

处理程序功能:

void my_signal_handler( int signum, siginfo_t* info, void* ptr)
{
    kill(0, SIGSTOP);
    int sonPid = info->si_pid;
    char* pipeName = malloc(14 + sizeof(int));//TODO ok?
    sprintf(pipeName, "//tmp//counter_%d" , (int) sonPid); //TODO double //?
    size_t fdPipe = open(pipeName, O_RDONLY);
    int cRead;
    int countRead = read(fdPipe,&cRead,sizeof(int));
    COUNT+= cRead;
    kill(0, SIGCONT);
    return;
}

创建子进程:

struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = my_signal_handler;
new_action.sa_flags = SA_SIGINFO;
if( 0 != sigaction(SIGUSR1, &new_action, NULL) )
{
    printf("Signal handle registration failed. %s\n", strerror(errno));
    return -1;
}
for(int i=0; i<16; i++){
    pid_t cpid = fork();
    if(cpid == 0) // child
    {
        execv("./counter",argvv); // some arguments to the function
        printf("execv failed: %s\n", strerror(errno));
        return -1;
    }
    else{
        continue;
    }

子项的计数器程序,简而言之,它会计算文件某些部分中char counc的外观,然后将其打印到管道中。:

int main(int argc, char** argv){
    int counter = 0;
    char counc = argv[1][0];
    char* filename = argv[2];
    off_t offset = atoll(argv[3]);
    ssize_t length = atoll(argv[4]); 
    int fd = open(filename, O_RDWR | O_CREAT);
    char* arr = (char*)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); 
    for(int i=0; i<length; i++){
        if(arr[i] == counc){
            counter++;
        }
    }
    pid_t proid = getpid();
    pid_t ppid = getppid();
    char* pipeName = malloc(14 + sizeof(pid_t));
    sprintf(pipeName, "//tmp//counter_%d" , (int) proid);
    size_t fdPipe = mkfifo(pipeName, 0777);
    int didopen = open(pipeName,O_WRONLY);
    size_t wrote = write(fdPipe,&counter , 1 );
    if(wrote < 0){
        printf(OP_ERR, strerror( errno ));
        return errno;
    }
    kill(ppid, SIGUSR1);
//close the pipe and unmap the array
return 1;
}

2 个答案:

答案 0 :(得分:0)

如果我正确理解你的问题,你就无法分别在父亲和孩子身上找到所需的信号功能。如果不是这种情况,请纠正我。

如果您的问题是这样,您可以简单地创建一些if语句,以测试pid调用返回的fork(),然后仅在您是父亲的情况下执行。所以......

if (pid == 0) 
          //ChildProcess();
          // do nothing!
     else 
          //ParentProcess();
          // do something!

请注意,您必须将size_t pid定义为全局变量,以便在您正在实现的main和信号处理函数中可见!

答案 1 :(得分:0)

除了其他人已经指出的关于在信号处理程序中使用非异步安全函数的内容之外,我还要走出困境并猜测问题是这两件事中的任何一个:

  1. 您错误地认为通过kill发送的信号已排队等待他们发​​送的进程。他们没有排队(除非你在支持它的操作系统上使用sigqueue);相反,更新目标进程的未决(但未处理)信号集。见signal queuing in C。或者,
  2. 您在不支持“可靠信号语义”的操作系统上运行此代码。有关见解(恐怖),请参阅man 3 sysv_signal
  3.   

    然而,sysv_signal()提供System V不可靠的信号语义,即:a)在调用处理程序时,信号的处置被重置为默认值; b)在执行信号处理程序时,不阻止传送信号的其他实例;