繁体   English   中英

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

[英]C - Multiple children - signals overwriting each other

我有一个父进程,它使用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;
}

如果我正确理解了您的问题,则可能是您分别在父亲和孩子中遇到了所需的信号功能。 如果不是您的情况,请纠正我。

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

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

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

除了其他人已经指出的有关在信号处理程序中使用非异步安全功能的内容之外,我还要大胆地猜测问题可能出在以下两件事中:

  1. 您错误地认为通过kill发送的信号已排队等待发送到的进程。 它们不会排队(除非您在支持它的操作系统上使用sigqueue ); 相反,将更新目标进程的未决(尚未处理)信号集。 请参阅C中的信号排队 要么,
  2. 您正在不支持“可靠信号语义”的操作系统上运行此代码。 请参阅man 3 sysv_signal以获取洞察(恐怖),例如:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM