萌新请问下, Linux 中是子进程 exit()中的_exit()触发中断进而要求内核 kenerl 发送 SIGCHLD 给父进程吗?

2020-08-13 02:45:34 +08:00
 ashiamd

查阅了几个小时关于 SIGCHLD 和 exit()相关的文章、Linux 守护进程 daemon 相关的文章之后。 现在有个疑惑。就是 SIGCHLD 到底是谁发出的?进而如果需要无视该信号,那么 signal(SIGCHLD,SIG_IGN)是要写在父进程中,还是被新建的 daemon 进程中??

这方面不太了解,网上查了 7-10 篇文章,感觉可能我语文阅读能力有问题?总感觉没有人说清楚这个 SIGCHLD 到底到底是哪里出现,最后又会被谁接收?

1716 次点击
所在节点    问与答
9 条回复
ashiamd
2020-08-13 02:49:19 +08:00
附上几篇看到的文章中比较标志性的,比如[创建守护进程为什么要 fork 两次]( https://blog.csdn.net/dream_1996/article/details/73467969)下方 "(6)其他:忽略 SIGCHLD 信号"的代码,我不是很懂为为什么是需要在新建出来的 daemon 进程执行 signal(SIGCHLD,SIG_IGN),这个 SIGCHLD 不应该是内核发送给父进程的吗?为什么反而是在子进程中声明无视 SIGCHLD ??
ashiamd
2020-08-13 02:50:27 +08:00
附上几篇看到的文章中比较标志性的。
比如[创建守护进程为什么要 fork 两次]( https://blog.csdn.net/dream_1996/article/details/73467969)

"(6)其他:忽略 SIGCHLD 信号"的代码,我不是很懂为为什么是需要在新建出来的 daemon 进程执行 signal(SIGCHLD,SIG_IGN)。
这个 SIGCHLD 不应该是内核发送给父进程的吗?为什么反而是在子进程中声明无视 SIGCHLD ??
Nitroethane
2020-08-13 07:57:48 +08:00
当一个进程得子进程退出时,其父进程会收到 SIGCHLD 信号。调用 signal(SIGCHLD, SIG_IGN) 的目的是避免在父进程提前退出的情况下,子进程退出时不会变成 zombie 。
至于你说的那篇文章中调用 signal 函数,应该跟创建 daemon 进程没多大关系
feather12315
2020-08-13 08:39:26 +08:00
Q1:SIGCHLD 是子进程在进行 exit 系统调用的时候,在子进程的执行逻辑中子进程向父进程的 PCB 中添加的一个标志。有专门的函数进行这一逻辑。

Q2:SIGHUB 在执行 exit 系统调用的过程中出现,被父进程接收。比如三个进程,1 是 2 的子进程,2 是 3 的子进程,当 2 退出后,1 号的父进程变为 3,1 号的 SIGCHLD 发送给 3 号。
ashiamd
2020-08-13 17:34:09 +08:00
@feather12315
@Nitroethane
昨晚深夜 找了不少 google 上的 wiki 什么的,好像也比较直观的说法。下午又下载 glib-c 的 C 代码,可惜没怎么看懂。

然后刚才看到一篇对 SIGCHLD 有代码示例的文章 ==>[ [Linux]关于 SIGCHLD ]( https://blog.csdn.net/xxpresent/article/details/73028750)

我按着里面的代码,在 Linux 服务器上,移动了 `signal(SIGCHLD,myhandler);` 这一句的位置;写几份 C 代码运行看效果

(1 )没移动,按文章那样,应该 父 /子进程 都等于 受到了这句函数最后导致的 PCB 变化等影响。有输出 sig
(2 ) 移动到`if( id == 0)` 条件语句块里,子进程范围, 没有输出 sig
(3) 移动到 `else` 条件语句块里,原进程(父进程)范围,有输出 sig 。

-------------------------------
以上,结合我之前所学。我认为 SIGCHLD,是 exit()中的_exit()像操作系统 注册了 SIGCHLD 的 handler,要求当前进程执行 exit()内的逻辑时,要求内核向父进程通知 SIGCHLD 。而操作系统内部默认对 SIGCHLD 采取动作为忽略==>这个我认为是指 C 库代码里有对一些 SIG 系列信号预设了处理函数 handler,其中如果一个进程收到 SIGCHLD 信号,那么默认触发 C 库里面自动忽略 该信号的逻辑。==> 也就是 除非 父进程主动写 signal(SIGCHLD,自定义 handler 函数),来处理子进程 C 库代码预设的 exit()逻辑中要求内核向父进程发送的 SIGCHLD 信号;否则父进程其实收到 SIGCHLD 就直接调用 C 库里逻辑,忽略 SIGCHLD 信号了。

不知道这样说对不对?
julyclyde
2020-08-14 23:56:41 +08:00
信号从概念上并不重视谁发出的啊
julyclyde
2020-08-14 23:58:25 +08:00
子进程无视 child 信号,主要是为了清除从父进程继承过来的 handler 避免副作用吧?
ashiamd
2020-08-15 00:40:56 +08:00
@julyclyde 谢谢老哥回答。
是不是意思说,为了保险起见(因为有时候无法确定父进程是否有自定义处理 SIGCHLD 信号的 handler ),所以才在子进程中执行 signal(SIGCHLD,SIG_IGN)。
即,保证不管父进程之前如何,至少新建的这个子进程,对 SIGCHLD 信号量一定是采取"忽略“的操作。
julyclyde
2020-08-17 11:17:21 +08:00
@ashiamd 不是一定忽略,是一定不要继承,而要明确设置自己的行为

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/697829

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX