上一篇进程退出时释放了用户空间资源,但进程PCB和in个没有释放,这一工作显然不是有自己完成的,而是有当前进程的附近承完成的,附近承可以显式调用wait()和waitpid()函数完成
一、wait()等待子进程结束
调用wait函数的父进程将阻塞式等待该进程的任意一个子进程结束后莫回首该子进程的内核进程资源
extern _pid_t wait(_WAIT_SATSUS _stat_loc)
如果等待到任意一个子进程结束,将返回子进程PID同时将子进程退出状态存在stat_loc中,失败返回-1,错误远近存在errno中
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
printf("child process pid: %d\n",getpid());
exit(EXIT_SUCCESS);
}
else if(pid<0)
{
perror("create child process");
exit(EXIT_FAILURE);
}
else
{
int status;
wait(&status);
if(WIFEXITED(status))
printf("child exit status: %d\n",status);
if(WIFSIGNALED(status))
printf("child exit by signal satus: %d\n",status);
return 0;
}
}
其中宏WIFEXITED和WIFSIGNALED为判断子进程退出方式是exit退出还是父进程发送信号退出
二waitpid等待特定子进程退出
extern _pid_t waitpid(_pid_t _pid,int *_stat_loc,int options)
第3个参数可以为 WNOHANG 1 不阻塞等待
WUNTRACED 2 报告状态信息
三、孤儿进程与僵死进程
孤儿进程:因父进程现推出而导致子进程被init进程收养
僵死进程:进程已经退出但该进程内核空间的PCB还没有释放
孤儿进程示例,让父进程先退出
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid;
pid=fork();
if(pid<0)
perror("child create");
else if(pid==0)
{
printf("child process ppid=%d\n",getppid());
sleep(5);
printf("child process ppid=%d\n",getppid());
}
else
{
printf("parent process pid=%d\n",getpid());
exit(0);
}
}
前后ppid不一样,ubuntu系统子进程可能被upstar --user收养
理论上应该被init 1 号进程收养,ubuntu好像是upstart代替init进程收养
僵死进程父进程让子进程退出不处理
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
int main()
{
pid_t pid;
if((pid=fork())==-1)
perror("fork");
else if(pid==0)
{
printf("child_pid pid=%d\n",getpid());
exit(0);
}
else
{
// wait(NULL);在这加上wait便不会产生僵死进程
sleep(3);
system("ps");
exit(0);
}
}
输出:child_pid pid=2699
PID TTY TIME CMD
2046 pts/3 00:00:00 bash
2698 pts/3 00:00:00 b6
2699 pts/3 00:00:00 b6 <defunct>//僵死进程
2700 pts/3 00:00:00 sh
2701 pts/3 00:00:00 ps