子进程的资源回收
-
对于子进程任何方式的结束,都希望父进程能够知道,可以通过wait\waitpid函数可以知道子进程是如何结束的以及它结束状态码
pid_t wait(int *status);
功能:以阻塞状态等待任意一个子进程的结束,并回收它的相关资源,获取到结束状态码
status:获取结束的子进程的结束状态码 是输出型参数
返回值:成功返回结束的子进程的pid,失败的返回-1
1、如果所有子进程都在运行中,则阻塞等待
2、如果有一个子进程结束,则立即返回该子进程的状态码和pid
3、如果当前没有子进程运行,返回-1
对于子进程的结束状态码status可借助宏函数解析判断:
WIFEXITED(status) - 子进程是否正常结束
WEXITSTATUS(status) - 当子进程是正常结束时,该宏可以获取到正确的结束状态码的低8位数据
WTERMSIG(status) - 如果进程是异常终止的,该宏可以获取到杀死该子进程的信号编号
注意:由于wait函数可能会阻塞父进程的执行,因此不适合在父进程的主业务逻辑中调用,可以通过给SIGCHLD信号注册信号处理函数,在信号处理函数中调用wait
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
void sigchld(int num)
{
int status = 0;
pid_t pid = wait(&status);
if(-1 == pid)
{
printf("子进程都死了\n");
return;
}
if(WIFEXITED(status))
{
printf("是正常结束的 状态码是%d\n",WEXITSTATUS(status));
}
else
{
printf("是异常终止的,被信号%d杀死\n",WTERMSIG(status));
}
}
int main(int argc,const char* argv[])
{
signal(SIGCHLD,sigchld);
for(int i=0; i<10; i++)
{
if(0 == fork())
{
printf("我是子进程%u i=%d\n",getpid(),i);
sleep(rand()%8+3);
if(0 == i%2)
{
kill(getpid(),3);
}
return 88+i;
}
}
for(;;)
{
printf("*\n");
sleep(1);
}
}
pid_t waitpid(pid_t pid, int *status, int options);
功能:等待子进程结束
与wait不同的是,可以选择等待哪些\哪个子进程结束,并且可以选择是否阻塞
pid:要等待的子进程的pid
< -1 等待abs(pid)编号的进程组中的任意进程结束
-1 等待任意进程结束,等待范围等同于wait
0 等待同组的任意进程结束
>0 等待pid进程结束
status:获取结束的子进程的结束状态码 是输出型参数 等同wait
options:
0 表示忽略该参数 功能与wait一致
WNOHANG 如果此时没有子进程结束会立即返回,不再阻塞
WUNTRACED 如果有子进程转入暂停态也会立即返回
WCONTINUED 如果有子进程从暂停态转回继续执行也会立即返回
返回值:
如果有子进程,且子进程状态改变 返回pid
如果有子进程 且都没改状态 返回0
如果没有子进程 返回-1

被折叠的 条评论
为什么被折叠?



