linux_SIGCHLD信号-子进程回收

文章介绍了SIGCHLD信号的产生条件,如何借助SIGCHLD信号回收子进程,包括waitpid函数的使用和子进程结束状态的处理方式,同时强调了处理SIGCHLD信号时的注意事项,如注册信号处理函数和子进程状态的检查。
摘要由CSDN通过智能技术生成

接上一篇:linux_时序竞态-pause函数-sigsuspend函数-异步I/O-可重入函数-不可重入函数

  今天来分享通过SIGCHLD信号来回收子进程,也介绍一下该信号的一些知识点,开始上菜:

此博主在CSDN发布的文章目录:【我的CSDN目录,作为博主在CSDN上发布的文章类型导读

1.SIGCHLD的产生条件

  ①子进程终止时;
  ②子进程接收到SIGSTOP信号停止时;
  ③子进程处在停止态,接受到SIGCONT后唤醒时;

2.借助SIGCHLD信号回收子进程

  子进程结束运行,其父进程会收到SIGCHLD信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函数中完成子进程状态的回收。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

void do_sig_child(int signo)
{
    int status;    
    pid_t pid;
    //waitpid:回收子进程
    //0 回收和当前调用waitpid一个组的所有子进程
    while ((pid = waitpid(0, &status, WNOHANG)) > 0) 
    {
        //为非0,进程正常结束
        if (WIFEXITED(status))
        {
            //获取进程退出状态 (exit的参数)
            printf("子进程 %d 退出 %d\n", pid, WEXITSTATUS(status));
        }
        else if (WIFSIGNALED(status))//为非0,进程异常终止
        {
            //取得使进程终止的那个x信号的编号。
            printf("子进程 %d 取消 信号 %d\n", pid, WTERMSIG(status));
        }
    }
}

int main(void)
{
    pid_t pid;    
    int i;
    for (i = 0; i < 5; i++) 
    {
        //创建子进程
        if ((pid = fork()) == 0)
        {
            break;
        }    
        else if (pid < 0)
        {
            perror("fork error");
            exit(1);
        }
    }
    if (pid == 0) 
    {    
        int n = 1;
        while (n--) 
        {
            printf("子进程 ID %d\n", getpid());
            sleep(1);
        }
        return i+1;
    } 
    else if (pid > 0) 
    {
        struct sigaction act;
        act.sa_handler = do_sig_child;
        sigemptyset(&act.sa_mask);//清零信号集合
        act.sa_flags = 0;
        sigaction(SIGCHLD, &act, NULL);//注册SIGCHLD信号捕捉函数
        while (1) 
        {
            printf("父进程 ID %d\n", getpid());
            sleep(1);
        }
    }
    return 0;
}

3.子进程结束status处理方式

waitpid函数:
函数作用:
  作用同wait,但可指定pid进程清理,可以不阻塞。
头文件:
  #include <sys/types.h>
  #include <sys/wait.h>
函数原型:
  pid_t waitpid(pid_t pid, int *status, in options);
函数参数:

pid:
	>0  回收指定ID的子进程,回收指定子进程时,只要该子进程结束,就可回收,回收时间>=子进程结束时间。
	-1  回收任意子进程(相当于wait)
	0   回收和当前调用waitpid一个组的所有子进程
	<-1 回收指定进程组内的任意子进程    可以和kill命令一起使用,例如:kill -9 -进程组ID
options:
	0 :表示阻塞状态回收子进程
	WNOHANG:表示非阻塞状态回收子进程
status:保存进程退出的状态,可看wait函数参数的用法。
	借助宏函数来进一步判断进程终止的具体原因。
	宏函数可分为如下三组:
	 1. WIFEXITED(status) 为非0	→ 进程正常结束
		WEXITSTATUS(status) 如上宏为真,使用此宏 → 获取进程退出状态 (exit的参数)
	 2. WIFSIGNALED(status) 为非0 → 进程异常终止
		WTERMSIG(status) 如上宏为真,使用此宏 → 取得使进程终止的那个信号的编号。
	*3. WIFSTOPPED(status) 为非0 → 进程处于暂停状态
		WSTOPSIG(status) 如上宏为真,使用此宏 → 取得使进程暂停的那个信号的编号。
		WIFCONTINUED(status) 为真 → 进程暂停后已经继续运行

返回值:
  成功:返回清理掉的子进程ID;
  失败:-1(无子进程)
特殊返回值:
  当返回0:参数3为WNOHANG,表示子进程正在运行。

想要了解更多回收子进程的方法,请看这篇文章:
linux_回收子进程(何为孤儿进程、僵尸进程、wait函数、waitpid函数)

4.SIGCHLD信号注意问题

  1.子进程继承了父进程的信号屏蔽字和信号处理动作,但子进程没有继承未决信号集spending。
  2.注意注册信号捕捉函数的位置,应该在fork之前,阻塞SIGCHLD信号。注册完捕捉函数后解除阻塞。

以上就是本次的分享了,希望能对大家有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

futureCode.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值