我被要求找出这个问题中所有可能的输出:
#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循环吗?
我需要哪些必要的库来编译和运行这段代码?
当您从父进程派生子进程时,会设置 SIGCHLD 但不会执行处理函数。 孩子退出后,它会触发 SIGCHLD,从而导致处理程序函数中的代码执行……
奇怪的节目。
我认为它试图向您展示的是
SIGCHLD
的原因以及子进程中的变量如何被子进程更改,对父进程没有影响。
当你
fork()
创建一个子进程。听起来有点熟?父进程(调用 fork() 的进程)接收信号。处理程序被执行。当你运行程序时,你应该看到 21.
这是因为每执行一次信号处理程序
val
,9 + ( 3*4)=21
就会递增三。
该代码创建了四个孩子。
子进程
val -= 3;
exit(0);
递减值。但是因为这发生在另一个进程中,而不是原始子进程,它不会触及“原始”
val
变量,因为它有自己的本地副本。
我相信@jim mcnamara 的回答没有列出所有可能的输出。
9+(3*k) 对于 1 <= k <= 4 should be possible because multiple signals can get collapsed into one.
输出比@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
时结束并且不发出任何内容。