Signal和SIGCHLD,它有什么作用?

问题描述 投票:0回答:4

我被要求找出这个问题中所有可能的输出:

#define N 4
int val = 9;
void handler(sig) {
   val += 3;
   return;
}
int main() {
  pid_t pid;
  int i;
  signal(SIGCHLD,handler);
  for (i=0;i<N;i++) {
    if ((pid =fork()) == 0) {
        val -= 3;
        exit(0);
    }
  }
  for (i=0;i<N;i++) {
    waitpid(-1,NULL,0);
  }
  printf("val = %d\n",val);
}

我不知道线路信号(SIGCHLD,处理程序)的作用。我只找到以下内容:

SIGABRT - abnormal termination.
SIGFPE - floating point exception.
SIGILL - invalid instruction.
SIGINT - interactive attention request sent to the program.
SIGSEGV - invalid memory access.
SIGTERM - termination request sent to the program.

SIGCHLD 是做什么的?你也能解释一下这个问题中的for循环吗?

我需要哪些必要的库来编译和运行这段代码?

c signals fork
4个回答
8
投票

当您从父进程派生子进程时,会设置 SIGCHLD 但不会执行处理函数。 孩子退出后,它会触发 SIGCHLD,从而导致处理程序函数中的代码执行……


6
投票

奇怪的节目。

我认为它试图向您展示的是

SIGCHLD
的原因以及子进程中的变量如何被子进程更改,对父进程没有影响。

当你

fork()
创建一个子进程。听起来有点熟?父进程(调用 fork() 的进程)接收信号。处理程序被执行。当你运行程序时,你应该看到 21.

这是因为每执行一次信号处理程序

val
9 + ( 3*4)=21
就会递增三。 该代码创建了四个孩子。

子进程

val -= 3;
exit(0);

递减值。但是因为这发生在另一个进程中,而不是原始子进程,它不会触及“原始”

val
变量,因为它有自己的本地副本。


2
投票

我相信@jim mcnamara 的回答没有列出所有可能的输出。

9+(3*k) 对于 1 <= k <= 4 should be possible because multiple signals can get collapsed into one.


0
投票

输出比@ArseniyAlekseyev 的回答更受限制。

根据5.1.2.3程序执行,(草案)C11标准(bolding mine)第5段:

当抽象机的处理因收到信号而中断时,既不是无锁原子对象也不是 volatile sig_atomic_t 类型的对象的值是未指定的,浮点环境的状态也是如此。 处理程序修改的任何对象的值,如果它不是无锁原子对象,也不是 volatile sig_atomic_t 类型,当处理程序退出时,它的值变得不确定,如果它被处理程序修改,浮点环境的状态也是如此,并且没有恢复到原来的状态。

任何结果都是可能的,即使使用

fork()
SIGCHLD
强烈暗示POSIX系统,
signal()
的语义不受POSIX保证

当一个信号发生时,func 指向一个函数,是否等价于 a:

是实现定义的
signal(sig, SIG_DFL);

被执行...

如果

SIGCHLD
的默认处理是退出,父进程可以简单地在收到第二个
SIGCHLD
时结束并且不发出任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.