【问题标题】:C Signal Handler professor example explanationC Signal Handler 教授实例讲解
【发布时间】:2017-11-27 22:25:06
【问题描述】:

我的 QNX 课堂笔记有这个例子,我似乎无法弄清楚我的教授是如何得出这个输出的。谁能彻底地向我解释一下?

当这个程序运行时,父进程的 PID 为 1234,子进程的 PID 为 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;
}

【问题讨论】:

  • 那么..你自己运行过吗?
  • @EugeneSh.i 做了
  • 你认为它会做什么?为什么?
  • @rici 我无法弄清楚为什么输出首先是 0,然后是 10
  • @bob:孩子的计数器是如何增加的?父母的情况如何?

标签: c pid qnx


【解决方案1】:

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

子进程调用的kill 正在向父进程发送SIGUSR1,因为它使用getppid() 来获取pid。

父进程要么在wait 中被阻塞,要么在forkwait 之间的某个地方被阻塞。对于子级发送的每个SIGUSR1,父级将跳转到信号处理程序,增加其counter 的副本,然后返回它正在执行的任何操作。

一般来说,如果在等待时处理信号,wait 可以返回 EINTR 错误。在sa.sa_flags 中设置SA_RESTART 可确保系统调用将被重新启动,但这里假设wait 不会被信号中断(QNX 是否保证这一点?)。

counter 的孩子副本不受影响。 wait 导致父进程阻塞,直到子进程退出。因此,子进程打印其值counter,即0,然后退出,父进程从wait 唤醒并打印其值counter,即10

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 2011-08-11
    • 2023-03-24
    • 2014-05-08
    • 2022-12-02
    • 1970-01-01
    相关资源
    最近更新 更多