我正在尝试理解阻塞和解锁信号是如何工作的,并且我正在尝试理解下面这段代码。具体地说,我看的是第28行(代码中的注释):int a = sigprocmask(SIG_UNBLOCK, &mask, NULL);
,也就是信号在子对象中被解锁的地方。
我得到代码的教科书说,代码使用信号阻塞,以确保程序在执行删除功能(简化为printf("deleting %d\n", pid);
)之前执行其添加功能(简化为printf("adding %d\n", pid);
)。这对我来说很有意义;通过阻塞SIGCHLD
信号,然后在执行add函数后解除阻塞,我们确保在执行add函数之前不会调用处理程序。然而,我们为什么要解锁孩子身上的信号呢?这难道不是通过立即解除阻塞来消除整个阻塞的点,允许孩子在父节点添加之前删除它吗?
然而,无论我是否注释掉了该行,输出(在代码之后描述)都是相同的,这意味着这显然不是所发生的事情。教科书上写道:
“请注意,子级继承了父级的阻塞集,因此在调用
execve
之前,我们必须小心解锁子级中的SIGCHLD
信号。”
但在我看来,解锁仍然会导致处理程序被调用。这一行到底是做什么的?
void handler(int sig) {
pid_t pid;
printf("here\n");
while ((pid = waitpid(-1, NULL, 0)) > 0); /* Reap a zombie child */
printf("deleting %d\n", pid); /* Delete the child from the job list */
}
int main(int argc, char **argv) {
int pid;
sigset_t mask;
signal(SIGCHLD, handler);
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, NULL); /* Block SIGCHLD */
pid = fork();
if (pid == 0) {
printf("in child\n");
int a = sigprocmask(SIG_UNBLOCK, &mask, NULL); // LINE 28
printf("a is %d\n",a);
execve("/bin/date", argv, NULL);
exit(0);
}
printf("adding %d\n", pid);/* Add the child to the job list */
sleep(5);
printf("awake\n");
int b = sigprocmask(SIG_UNBLOCK, &mask, NULL);
printf("b is %d\n", b);
sleep(3);
exit(0);
}
输出:
adding 652
in child
a is 0
Wed Apr 24 20:18:04 UTC 2019
awake
here
deleting -1
b is 0
https://stackoverflow.com/questions/55838182
复制相似问题