关于 unix SIGCHLD 信号的一些思考

本文详细解析了在Linux环境下,子进程的各种死亡方式及其对父进程的影响。子进程无论正常退出还是异常终止,内核都会发送SIGCHLD信号通知父进程,若父进程不处理将导致僵尸进程。孤儿进程会被init进程收养,避免僵尸进程产生。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在看项目的代码,对父进程fork的子进程的各种死法,父进程会受到子进程什么样的信号产生了疑虑。

通过细看apue,可以整理出一下流程:

对于子进程(abort, ctrl+c, a/0, 被kill, *invalid_addr 等等)各种死法,子进程会收到对应的信号(如 SIGABRT, SIGKILL,SIGFPE ..等等信号),这些信号是按照 [硬件/软件] -> 内核 -> 进程  顺序发送给子进程的。

这只是子进程接收信号的表述,实际上子进程本身也可能是导致发送信号的原因,比如子进程运行结束,会导致内核向父进程发送 SIGCHLD 信号。

因此不管子进程是正常死的(return 0)还是异常死的(kill),也不管异常死的方式。只要子进程运行结束了,内核都会负责向父进程报丧(发 SIGCHLD 信号)。而如果父进程不用wait或者waitpid接收报丧,那么子进程将会变成僵尸进程(没人收尸)。

如果父进程在子进程之前运行终止,那么内核会在一个进程终止时,逐个检查所有活动进程,以判断它是否是正要终止的进
程的子进程,如果是(此时子进程成为孤儿进程),则该进程的父进程 I D就更改为1 ( i n i t进程的I D ),由init进程收养。以确保系统每个子进程都有一个父进程。因为init进程会调用wait取得子进程的消亡状态,因此孤儿进程不会变成僵尸进程。

 

有了上面的理解,下面的代码就好看懂了:

sig_hander(int signo)

{

        int save_errno = errno;

        //switch(signo)

        //case SIGCHLD, SIGINT, SIGTERM

        //do something

        errno = save_errno;

}

父进程:

signal(SIGCHLD, sig_hander);  //处理子进程终止产生的信号,此时sig_hander 的参数是 SIGCHLD

signal(SIGINT, sig_hander);   //处理中断信号 ctrl + c,此时sig_hander 的参数是 SIGINT

signal(SIGTERM, sig_hander);  //处理终止信号,此时sig_hander 的参数是 SIGTERM

//注意不能捕获,SIGKILL 和 SIGSTOP 这两个信号。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值