> 文章列表 > linux_SIGCHLD信号-子进程回收

linux_SIGCHLD信号-子进程回收

linux_SIGCHLD信号-子进程回收

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

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

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

目录

  • 1.SIGCHLD的产生条件
  • 2.借助SIGCHLD信号回收子进程
  • 3.子进程结束status处理方式
  • 4.SIGCHLD信号注意问题

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信号。注册完捕捉函数后解除阻塞。

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