【问题标题】:How to make synchronization between processes using signals? [duplicate]如何使用信号在进程之间进行同步? [复制]
【发布时间】:2021-04-25 07:45:43
【问题描述】:

目标是父进程应该生成一个子进程,父进程打印 1 到 100 之间的偶数,子进程打印奇数。这种机制应该使用信号来实现(数字应该是按顺序排列的,例如 parent:0、child:1、parent:2...)我编写了以下代码:

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>

int main(){
    pid_t pid;

    pid = fork();

    if (pid == -1){
        return 1;
    }
    
    if (pid == 0){
            
        for(int i=0; i<=100; i++){
            if (i % 2 != 0){
                printf("I am the child: %d\n", i);
            }
        }

    } else {
        kill(pid, SIGSTOP);
        for(int i=0; i<=100; i++){
            if(i % 2 == 0){
                printf("I am the parent: %d\n", i);
                kill(pid, SIGCONT);
            }
        }
        wait(NULL);
    }

    return 0;
}

但是输出的顺序不是应该的,父母先打印他所有的数字,孩子跟着他。我想知道 SIGSTOP 和 SIGCONT 是否不是适合使用的信号,但没有其他合乎逻辑的解决方案。

任何建议都会有所帮助。谢谢。

【问题讨论】:

  • 父项中没有代码等待子项进行打印。建议使用sigwaitSUGUSR 信号。请参阅上面的重复帖子。

标签: c unix process signals fork


【解决方案1】:

阻止信号并仅在收到该信号时恢复。关于使用哪个信号,您可以使用任何可以阻止的信号(除SIGKILLSIGSTOP 之外的任何信号)。我使用了SIGRTMIN,因为它用于应用程序定义的目的。

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>

int main(){
    /* Block SIGRTMIN */

    sigset_t sigmask;

    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGRTMIN);

    if (sigprocmask(SIG_BLOCK, &sigmask, NULL) != 0)
        exit(1);
    
    int signo;

    /* Spawn a new child */

    pid_t pid;

    pid = fork();

    if (pid == -1){
        return 1;
    }
    
    if (pid == 0){
        sigwait(&sigmask, &signo);  // This is to make parent start first.
        for(int i=1; i<=100; i=i+2){
            printf("I am the child: %d\n", i);

            kill(getppid(), SIGRTMIN);  // Resume parent
            sigwait(&sigmask, &signo);  // Wait for parent
        }

    } else {
        for(int i=0; i<=100; i=i+2){
            printf("I am the parent: %d\n", i);

            kill(pid, SIGRTMIN);    // Resume child
            if (i == 100)   // Parent stucks at sigwait after printing 100.
                break;
            sigwait(&sigmask, &signo);  // Wait for child
        }
        wait(NULL);
    }

    return 0;
}

我们在父级中阻止了 SIGRTMIN,但它如何在子级中被阻止?

根据signal(7) 手册页。

通过 fork(2) 创建的子代会继承其父代的副本 信号掩码;信号掩码在 execve(2) 中保留。

【讨论】:

    猜你喜欢
    • 2016-07-31
    • 2023-01-29
    • 2011-09-06
    • 2015-04-13
    • 2017-02-06
    • 1970-01-01
    • 2017-08-31
    • 2012-01-04
    相关资源
    最近更新 更多