1

我想要做的是创建一个持续 5 秒的父进程。SIGUSR1我也希望它每秒发送一个信号。在这个信号上,我希望孩子做点什么。

到目前为止,我放在一起的代码是:

void alarmHandler(int sig) {
    printf("\nalarm called\n");
    exit(0);
}


void childHandler(int sig) {
    printf("child called");
    signal(SIGUSR1, childHandler);
}

int main() {
    pid_t val;

    if((val = fork())) { //parinte
        signal(SIGALRM, alarmHandler);
        printf("parent");
        alarm(5);
        while(1) {
            kill(val, SIGUSR1);
            sleep(1);
        }
    }else { 
        signal(SIGUSR1, childHandler);
        printf("child");
    }

    return 0;
}  

我得到的是:

child
parent
alarm called  

我想要的是:

child 
parent
child called
child called
child called
child called
child called
alarm called
4

2 回答 2

1

你的父母有while循环。孩子会做以下事情:

signal(SIGUSR1, childHandler);
printf("child");

然后退出。

如果它SIGUSR在退出之前收到,这也将被执行

printf("child called");
signal(SIGUSR1, childHandler);

因此,您有一个竞争条件,因为打印了被调用的孩子的数量。

只需在while (1) {}后面放一个printf("child");

于 2012-12-04T19:49:52.977 回答
0

在原代码的基础上,添加两个块:

  • 冲洗 printf:setbuf(stdout, NULL);
  • 让孩子继续奔跑:while (1) pause();

代码清单如下:

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

    /* For a real-world program, printing from a signal handler is not very safe.
     * A signal handler should do as little as it can, preferably only setting a flag here or there.
     * And the flag should be declared `volatile`.
     * Real-world example:
     *   I once worked on a system that used an Access database as a back end,
     *   and under certain circumstances a printf() call in a signal handler would write to the .mdb file instead of stdout,
     *   hosing the database beyond repair.
     */
    void alarmHandler(int sig)
    {
        printf("\nparent signal alarm handler: times up\n");
        exit(0);
    }

    void childHandler(int sig)
    {
        printf("\nchild signal handler\n");
        // The old style should install the handler again.
        signal(SIGUSR1, childHandler);
    }

    int main()
    {
        pid_t val;

        signal(SIGALRM, alarmHandler);
        // If not set this, we cann't the child's output.
        // The stdout stream is buffered, so will only display what's in the buffer after it reaches a newline (or when it's told to).
        setbuf(stdout, NULL);
        if ((val = fork())) { //parinte
            printf("\nparent\n");
            // @Note that there is only one alarm clock per process.
            // the alarm() function will return a value if another alarm has been previously set.
            //
            // sets a timer that generates the SIGALARM signal when times up.
            // If we ignore or don’t catch this signal, the process is terminated.
            alarm(5);
            while(1) {
                sleep(1);
                kill(val, SIGUSR1);
            }
            printf("\nparent exit\n");
        } else {
            signal(SIGUSR1, childHandler);
            printf("\nchild\n");
            while (1)
                pause(); // The pause() function suspends the process until a signal is caught.
            printf("\nchild exit\n");
        }

        return 0;
    }     

和输出:

parent
child
child signal handler
child signal handler
child signal handler
child signal handler
parent signal alarm handler: times up
于 2019-01-29T21:21:45.660 回答