【进程信号拓展】SIG_CHLD 信号处理

SIGCHLD信号

​ 在学进程等待的时候我们用 waitwaitpid 函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞了就不能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一 下,程序实现复杂。

​ 其实,子进程在终止时会给父进程发 SIGCHLD 信号,该信号的默认处理动作是忽略,父进程可以自定义 SIGCHLD 信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用 wait 清理子进程即可。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void handler(int signo)
{
    pid_t id = waitpid(-1, NULL, WNOHANG); // 使用WNOHANG才能保证非阻塞查询
    while(id > 0) 
    {
        printf("wait child success: %d\n", id);
    }
    printf("child is quit! %d\n", getpid());
}
int main()
{
    signal(SIGCHLD, handler); // 将SIGCHLD信号进行自定义捕捉
    pid_t cid = fork();
    if(cid == 0)
    {  
        // child
        printf("child : %d\n", getpid());
        sleep(3);
        exit(1);
    }

    // father
    while(1)
    {
        printf("father proc is doing some thing!\n");
        sleep(1);
    }
    return 0;
}

​ 事实上,由于 UNIX 的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调用 sigactionSIGCHLD 的处理动作置为 SIG_IGN,这样 fork 出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。

​ 💥💥💥 此方法对于 Linux 可用,但不保证在其它 UNIX 系统上都可用

​ 下面我们来编写程序验证这样做不会产生僵尸进程:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main()
{
    signal(SIGCHLD, SIG_IGN); // 直接通过SIG_IGN忽略,即可回收僵尸子进程
    pid_t cid;
    if((cid = fork()) == 0)
    {  
        // child
        printf("child : %d\n", getpid());
        sleep(3);
        exit(1);
    }

    // father
    while(1)
    {
        printf("father proc is doing some thing!\n");
        sleep(1);
    }
    return 0;
}

​ 除此之外,系统默认的忽略动作 Ign 和用户用 sigaction 函数自定义的忽略动作 SIG_IGN 通常是没有区别的,但这是一个特例 。也就是说,SIG_IGN 其实做了更多的一些小动作!

相关推荐
OnlyEasyCode8 分钟前
快速上手!查看、拷贝、编辑、远程连接Linux命令
linux·运维·服务器
dualven_in_csdn14 分钟前
UDP广播接收小优化
linux·运维·服务器
阿沁QWQ42 分钟前
C++的map和set
开发语言·c++
Xの哲學1 小时前
Linux二层转发: 从数据包到网络之桥的深度解剖
linux·服务器·算法·架构·边缘计算
石像鬼₧魂石1 小时前
Termux ↔ Windows 靶机 反向连接实操命令清单
linux·windows·学习
啃火龙果的兔子1 小时前
如何将D:\BaiduNetdiskDownload所有目录下的所有图片复制提取到D:\bacPic
linux·运维·服务器
FF-Studio1 小时前
RTX 5060 Ti Linux 驱动黑屏避坑指南:CUDA 13.1, Open Kernel 与 BIOS 设置
linux·运维·服务器·cuda
坐吃山猪2 小时前
BrowserUse14-源码-ScreenShot模块-整理
linux·数据库·python
Jelly-小丑鱼2 小时前
Linux搭建syslog日志服务器
linux·服务器·docker·日志服务器·syslog服务器
yilan_n2 小时前
在Linux下使用Termony搭建HNP自验证环境全指南
linux·harmonyos·termony·hnp·命令行适配