Linux学习之系统编程篇:利用 SIGCHLD 回收子进程

子进程死亡会给父进程发送 SIGCHLD 信号!(默认动作:父进程忽略该信号)此时父进程就可以捕捉该信号,利用回调函数使用 waitpid 回收子进程。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void catch_sig(int sig) // 参数:是捕捉的信号编号
{
 pid_t pid;
while(1)
{
 pid = waitpid(-1, NULL, WNOHANG);
 if(pid <= 0)
{
 break;
 }
 printf("died child_id=%d\n",pid);
 } }
int main()
{
 // 问题:父进程注册捕捉的时候,子进程已经死亡,这样信号根本捕捉不到
 // 重要思想:先屏蔽信号,再解除屏蔽
 // 这样:即使子进程先死,内核产生的信号也会被屏蔽掉,然后再解除屏蔽,信号就可以被顺利捕捉了
 // 父进程先设置屏蔽信号集,屏蔽SIGCHLD信号
 sigset_t proc; // 定义自定义信号集
 sigemptyset(&proc); // 第一步:清空自定义信号集,防止随机数干扰其他信号
 sigaddset(&proc, SIGCHLD); // 将 sigchld 信号 添加到自定义集合
 sigprocmask(SIG_BLOCK, &proc, NULL); // 通过 自定义信号集 设置 屏蔽信号集
 
// 创建5个子进程
int i = 0;
for(i = 0 ;i < 5; i ++)
{
 pid_t pid = fork();
 if(pid == 0){
 break;
 }
 }
 // 此时,6个进程在运行
 if(i < 5){
 // 子进程
 printf("I am %d child, mypid=%d\n", i+1, getpid());
 }
 else if(i == 5){
 // 父进程逻辑 前期已经将信号屏蔽掉了,此时使用 sigaction 进行捕捉
 struct sigaction act;
 act.sa_flags = 0;
 act.sa_handler = catch_sig;
 sigemptyset(&act.sa_mask); // 不设置临时屏蔽信号
 sigaction(SIGCHLD, &act, NULL);
// 注意:先注册捕捉,再解除屏蔽,顺序不能反
 sigprocmask(SIG_UNBLOCK, &proc, NULL);
 while(1){
 sleep(1); // 父进程一直存活,使子进程先执行return死亡
 }
 }
 return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值