博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

子进程退出状态回收

Posted on 2016-03-23 16:45  bw_0927  阅读(785)  评论(0)    收藏  举报

http://www.zyfforlinux.cc/2015/01/02/%E5%AD%90%E8%BF%9B%E7%A8%8B%E7%8A%B6%E6%80%81%E5%9B%9E%E6%94%B6/

 

wait和waitpid

在父子进程中,子进程执行结束后,如果不对其进行回收,那么子进程就会变成僵尸进程,
随着僵尸进程变多会占用大量的pid等资源所以需要使用wait或者waitpid对子进程进行回收。
下面是两个API函数的函数原型:

1
2
3
4
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

wait是阻塞的,只要有子进程退出就回收,子进程退出的信息保存在status中(需要使用一些封装好的宏来提取status中的信息)
waitpid则功能更加强大:
pid == -1 等待任意子进程退出 此时和wait效果一样
pid > 0 等待进程ID和pid相同的进程
pid == 0 等待组ID等于调用进程组ID的任一子进程
pid < -1 等待组ID等于pid的绝对值的任意子进程

options常用的选项是WNOHANG,表示waitpid是非阻塞的。
这两个函数的一般应用场景都是放在信号处理函数中,当子进程结束的时候会发送SIGCHLD信号,
那么在SIGCHLD信号对应的处理函数中去调用wait或waitpid来实现对子进程的回收。
下面给出waitpid的用法:

1
2
3
4
5
6
7
8
9
10
static void handle_child(int sig)
{
pid_t pid;
int stat;
while((pid = waitpid(-1,&stat,WNOHANG)) > 0)
{
//进行后续的处理
//处理完 break;
}
}

子进程的状态获取

通过使用wait和waitpid可以得到子进程退出的状态status,但是还是需要使用一个宏来解析出退出的状态码或者其他信息
linux本身提供了一系列的宏可以帮助我们完成这个工作:
每一组宏都是对应的:

1
2
3
4
5
6
7
8
WIFEXITED(status) 如果子进程是正常退出的就返回true
WEXITSTATUS(status) 获取子进程正常退出的退出码

WIFSIGNALED(status) 如果子进程是因为未捕获信号停止的返回true
WTERMSIG(status) 获取未捕捉信号的值

WIFSTOPPED(status) 如果进程是意外终止返回true
WSTOPSIG(status) 获取导致进程意外终止的信号值

下面是这组宏的常见用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
void print_exit(int statu)
{
if(WIFEXITED(status)) //是正常退出
cout << "normal termination,exit status" << WEXITSTATUS(status) << endl;
else if(WIFSIGNALED(status)) //子进程异常终止
{
cout << "abnormal termination,signal number" <<WTERMSIG(status)<< endl;
#ifdef WCOREDUMP
if(WCOREDUMP(status)) //判断该信号时候会产生coredump文件
cout << "core file generated" << endl;
#else
#endif
else if(WIFSTOPPED(status)) //子进程暂停
cout << "child stopped,signal number" << WSTOPSIG(status) << endl;
}
}