我从CMU过去的考试中发现了这个问题,我无法得到输出是如何可能的。孩子和父母信号之间的并发竞争
基本上,它背后的想法是,有一个父进程阻止用户定义的信号,然后父母分岔一个孩子。并且基于哪个进程首先运行(又名:赢得比赛),则可能有不同的输出。 Here is the question that is being asked in the exam(请阅读)
,这里是从考试代码:
int i = 1;
void handler (int sig) {
i++;
}
int main() {
pid_t pid;
sigset_t s;
sigemptyset(&s);
sigaddset(&s, SIGUSR1);
signal(SIGUSR1, handler);
sigprocmask(SIG_BLOCK, &s, 0);
pid = fork();
<LINE A>
if (pid != 0) {
i = 2;
<LINE B>
} else {
i = 3;
<LINE C>
}
sigprocmask(SIG_UNBLOCK, &s, 0);
pause(); /* pause to allow all signals to arrive */
printf("%d\n", i);
exit(0);
}
有3种情况需要进行测试,因为我们需要把功能:
kill(pid,USRSIG1);
在LINE A或LINE B或LINE C中找到可能的输出。
现在,这里是我做的,我把功能LINE A.
比方说,我们运行程序,那么家长会创建一个空的集合S,信号SIGSUR1添加到它,那么它将为SIGUSR1信号分配一个自定义处理程序,并阻止该集合中的信号。这是这些线路
sigset_t s;
sigemptyset(&s);
sigaddset(&s, SIGUSR1);
signal(SIGUSR1, handler);
sigprocmask(SIG_BLOCK, &s, 0);
然后上级将运行线
pid = fork();
将从过程创建一个新的孩子。
现在有两种情况将确定输出。操作系统安排父母或孩子首先运行。
比方说,父母先跑。然后它将执行LINE A(这是kill函数)
并且由于它是父级,所以pid值将是子级的进程ID。所以它会发送USRSIG1给孩子,但是由于它被阻塞,它什么都不会做
if语句为全局变量i分配一个值。如果这个过程是父母的话,我= 2,否则的话,我= 3,所以在我们的父进程中,我们将有I = 2
if (pid != 0) { //if i am a parent then i = 2
i = 2;
<LINE B>
} else { //if i am a child then i = 3
i = 3;
<LINE C>
}
下一行会在父被执行,它会解锁在SIGUSR1信号 sigprocmask(SIG_UNBLOCK, &s, 0);
与父进程将暂停,直到它接收到的信号
现在孩子会跑,它会包括自己的过程组中的杀(0,SIGUSR1)信号发送给所有的进程。但是由于它在孩子身上受到阻碍,什么都不会发生。父母会收到信号,它会使我增加1(所以现在我在父母中= 3)。并且它将从函数暂停中恢复,以打印I(它是3)的值并退出。
孩子现在从kill函数恢复,因为它是一个孩子,if语句不会是真的(所以我的孩子的值= 3)。孩子解除设置和暂停()的信号。
由于没有其他进程向小孩发送信号,它将永远保持暂停状态,并且仅由父级输出3。如果我们按照其他方式(孩子在父母之前跑步),那么输出将仅为4。
什么令我困惑的是,考试的解决方案说每次运行有2个输出?我不明白这是怎么可能的,因为其中一个进程将停留在()。
该解决方案的关键认为,对于A线的可能的输出是:
3 4, 4 3, 3 5, or 5 3
这是所有我可以从问题的理解。任何帮助或暗示将不胜感激。