C中的叉子和信号

时间:2014-05-08 05:29:37

标签: c signals fork flags

有人可以帮助我逐步完成以下C代码,以了解输出应该是什么。

int x = 0;
pid_t pid;
int flag=1;

void handler1(int sig) {
    x=x+1;
    printf("%d\n",x);
    fflush(stdout);
    exit(0);
}

void handler2(int sig) {
    x = x + 2;
    flag = 0;
    waitpid(-1,NULL, 0);
}

int main() {
    signal(SIGUSR1, handler1);
    signal(SIGCHLD, handler2);
    printf("%d\n",x);
    fflush(stdout);
    if ((pid = fork()) == 0) {
        while(1) {};
    }
    kill(pid, SIGUSR1);
    while(flag) {};
    printf("%d\n",x);
    fflush(stdout);
    exit(0);
}

我认为输出应该是" 213"但我不确定。

2 个答案:

答案 0 :(得分:0)

从技术上讲,它是未定义的,因为您使用信号处理程序中的 stdio 函数。我将printf / fflush组合替换为单个write(但实际刷新流的奖励积分)。退出信号处理程序也被视为不良形式。

Also, both x and flag need to be made volatile

  1. 首先发生的是x已打印,但仍具有值0
  2. 然后,该过程为fork() ed。
  3. SIGUSR1传递给子节点,并在其中调用处理程序。处理程序在子项内递增x,并打印1
  4. 子进程退出,并且调用父级的SIGCHLD处理程序,将父级的x副本(仍为0)递增2。
  5. 父级退出flag的循环轮询,并打印当前值2
  6. 因此输出应为012

答案 1 :(得分:0)

此代码是父线程' main()'以及由' fork()'创建的子线程的故事。

故事从父线程开始,它使用信号处理程序设置舞台,然后打印出之前初始化为x的{​​{1}}的值。

然后,父母生下一个孩子'线程,向子节点发送SIGUSR1信号,然后陷入while循环。离开循环的唯一方法是清除父母的内容(副本)'标记'变量

现在故事转向了孩子;事实证明,孩子能够继承父母的所有财富,包括它自己的“x&x; (由父母初始化为0)。

不幸的是,孩子出生后进入无限循环。孩子退出循环的唯一方法是处理一个“信号”。幸运的是,对于孩子来说,父母碰巧就是这么做的。正如在故事的早期所述,父母在父母陷入循环之前就向孩子发送了一个SIGUSR1信号。

因此,子线程会赶到' handler1()'(父母之前已指定为' SIGUSR1'处理程序)。在那里,它增加了它(孩子的)副本' x'从0到1,并打印新值(1)。在打印之后,子线程被“退出”()'立即暗杀。功能。

......但孩子们的故事还有更多内容!随着孩子最后喘着粗气,它呼喊着一个' SIGCHLD'发信号给父母(感谢'退出()'功能)。然后,孩子最后休息。 (安息儿,安息吧。)

与此同时,父母一直陷入困境;但是' SIGCHLD'信号已导致父母运行到' handler2()',(父母之前已指定为' SIGCHLD'处理程序)。在处理程序中,父母首先更改了' x'的副本。从0到2.然后猜猜父母发现了什么? '标志'这导致父母被困在一个循环中。因此,父对象将清除该标志,该标志将(从' handler2()'返回循环后,从循环中释放父对象。

然而,在离开' handler2()'之前父母会做最后一次检查,以确保失散多年的孩子能够做到最后一次检查。线程死了。在发现这种情况后,父母遗憾地回到了被限制的循环中。

重新进入循环后,父级发现该标志现在已清除,并突然出现循环!然后它打印出来的' x' (2)然后杀死自己。

结束。

0

输出:

0
   1
   2