C Signal Handler教授实例讲解

C Signal Handler professor example explanation

我的 QNX class 笔记有这个例子,我似乎无法弄清楚我的教授是如何得出这个输出的。任何人都可以向我彻底解释这个吗?

当这个程序运行时,父进程的PID为1234,子进程为5678。

输出 5678: 计数器 = 0 1234: 计数器 = 10

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

/*
 * getpid() - returns the current processes pid.
 * getppid() - returns the parent processes pid.
 */

int counter = 0;

void signal_handler(int signo)
{
    counter++;
}

int main(int argc, char *argv[]) {
    int i = 0;
    int rv;

    struct sigaction sa;

    sa.sa_handler = signal_handler;
    //queue signals.
    sa.sa_flags = SA_SIGINFO;
    sigemptyset(&sa.sa_mask);

    sigaction(SIGUSR1, &sa, NULL);

    switch(fork())
    {
        case 0:
            for(i = 0; i < 10; i++)
            {
                kill(getppid(), SIGUSR1);
            }
            break;
        default:
            wait(&rv);
            break;
    }

    printf("%d: counter = %d\n", getpid(), counter);
    return 0;
}

fork 使用自己的 counter 副本创建了一个 child 进程。

child 进程调用的 kill 正在向 parent 进程发送 SIGUSR1,因为它使用 getppid() 获取pid.

parent 进程要么在 wait 中被阻止,要么在 forkwait 之间的某处被阻止。对于 child 发送的每个 SIGUSR1,parent 将跳转到信号处理程序,将其副本 counter 和 return 递增到它正在做的任何事情.

一般来说,如果信号在等待时被处理,wait 可能会 return 并出现 EINTR 错误。在sa.sa_flags中设置SA_RESTART保证系统调用会重启,但是这里假设wait不会被信号打断(QNX保证吗?)。

child 的 counter 副本不受影响。 wait 导致 parent 阻塞,直到 child 退出。 child 因此打印其值 counter,即 0,然后退出,parent 从 wait 中唤醒并打印其值 counter,也就是 10.