萌新请问下, Linux 中是子进程 exit()中的_exit()触发中断进而要求内核 kenerl 发送 SIGCHLD 给父进程吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ashiamd
V2EX    问与答

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

  •  
  •   ashiamd 2020-08-13 02:45:34 +08:00 2160 次点击
    这是一个创建于 1963 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    9 条回复    2020-08-17 11:17:21 +08:00
    ashiamd
        1
    ashiamd  
    OP
       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
        2
    ashiamd  
    OP
       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
        3
    Nitroethane  
       2020-08-13 07:57:48 +08:00 via iPhone   1
    当一个进程得子进程退出时,其父进程会收到 SIGCHLD 信号。调用 signal(SIGCHLD, SIG_IGN) 的目的是避免在父进程提前退出的情况下,子进程退出时不会变成 zombie 。
    至于你说的那篇文章中调用 signal 函数,应该跟创建 daemon 进程没多大关系
    feather12315
        4
    feather12315  
       2020-08-13 08:39:26 +08:00 via Android   1
    Q1:SIGCHLD 是子进程在进行 exit 系统调用的时候,在子进程的执行逻辑中子进程向父进程的 PCB 中添加的一个标志。有专门的函数进行这一逻辑。

    Q2:SIGHUB 在执行 exit 系统调用的过程中出现,被父进程接收。比如三个进程,1 是 2 的子进程,2 是 3 的子进程,当 2 退出后,1 号的父进程变为 3,1 号的 SIGCHLD 发送给 3 号。
    ashiamd
        5
    ashiamd  
    OP
       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
        6
    julyclyde  
       2020-08-14 23:56:41 +08:00 via iPad   1
    信号从概念上并不重视谁发出的啊
    julyclyde
        7
    julyclyde  
       2020-08-14 23:58:25 +08:00 via iPad
    子进程无视 child 信号,主要是为了清除从父进程继承过来的 handler 避免副作用吧?
    ashiamd
        8
    ashiamd  
    OP
       2020-08-15 00:40:56 +08:00
    @julyclyde 谢谢老哥回答。
    是不是意思说,为了保险起见(因为有时候无法确定父进程是否有自定义处理 SIGCHLD 信号的 handler ),所以才在子进程中执行 signal(SIGCHLD,SIG_IGN)。
    即,保证不管父进程之前如何,至少新建的这个子进程,对 SIGCHLD 信号量一定是采取"忽略“的操作。
    julyclyde
        9
    julyclyde  
       2020-08-17 11:17:21 +08:00   1
    @ashiamd 不是一定忽略,是一定不要继承,而要明确设置自己的行为
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2583 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 06:35 PVG 14:35 LAX 22:35 JFK 01:35
    Do have faith in whatyou're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86