父进程先于子进程结束,子进程的父进程成为init进程,称为进程孤儿院
##僵尸进程
僵尸进程:进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,为僵尸进程。
ps ajx pid ppid gid sid
##wait函数
1、阻塞等待子进程退出
2、回收子进程残留资源
3、获取子进程结束状态
pit_t wait(int *status); 成功:清理掉的子进程ID,失败:-1.
当进程终止时,操作系统的隐式回收机制会:1.关闭所有文件描述符。2.释放用户空间分配的内存。内核的PCB仍存在。其中保存该进程的退出状态。
可使用wait函数传出参数status来保存进程的退出状态。借助宏函数来进一步判断进程终止的具体原因。宏函数分为以下三组:
1.WIFEXITED(status)为非0,进程正常结束
WEXITSTATUS(status)如果上宏为真,使用此宏,获取进程退出状态(exit的参数)
2.WIFSIGNALED(status)为非0,进程异常终止。
WTERMSIG(status)如上宏为真,使用此宏,得到使进程终止的那个信号的编号
3.WIFSTOPPED(status)为非0, 进程处于暂停状态。
WTOPSIG(status) 若上宏为真,使用此宏得到使进程处于暂停的信号编号
WIFCONTINUED(status) 为真,进程暂停后已经继续运行。
##waitpid(pid_t pid, int *status, int options)
pid的值:
<-1: 回收指定进程组内的任意子进程 > 0: 回收指定id的子进程 -1 :回收任意子进程 0 :回收指定进程组内的任意子进程
返回值:
> 0:表示成功回收的子进程id。 = 0:函数调用时参3指定了WNOHANG,如果没有子进程就直接返回。 = -1:失败,设置errno。
回收指定id的子进程代码:
#include#include #include #include #include #include int main(int argc, char *argv[]){ int i; pid_t pid, wpid, tmpid; for(i = 0; i < 5; i++){ pid = fork(); if (pid == 0){ break; } if(i == 2){ tmpid = pid; printf("pid is %dn", tmpid); } } if(i == 5){ // sleep(5); // printf("i am parent, before waitpid, pid = %dn", tmpid); wpid = waitpid(tmpid, NULL, 0);//0阻塞,WNOHANG是非阻塞 if(wpid == -1){ perror("wait error"); exit(1); } printf("i am parent, wait a child finish:%dn", wpid); }else{ sleep(i); printf("i am %dth child, my pid is %dn", i+1, getpid()); } return 0; }
运行结果为:
ymyy@ymyy-virtual-machine:~/systemcode$ ./loop_fork pid is 24003 i am 1th child, my pid is 24001 i am 2th child, my pid is 24002 i am 3th child, my pid is 24003 i am parent, wait a child finish:24003 ymyy@ymyy-virtual-machine:~/systemcode$ i am 4th child, my pid is 24004 i am 5th child, my pid is 24005
需要注意的是:传入的第一个参数tmpid不能是pid, 否则回收的将永远是最后一个进程。
###waitpid回收多个子进程
#include#include #include #include #include int main(){ int i; pid_t pid, wpid; for(i = 0; i < 5; i++){ pid = fork(); if(pid == 0){ break; } } if(i == 5){ while((wpid = waitpid(-1, NULL, WNOHANG)) != -1){ if(wpid > 0){ printf("wait child %dn", wpid); }else if(wpid == 0){ sleep(1); continue; } } }else{ sleep(1); printf("i am %dth, pid = %dn", i+1, getpid()); } return 0; }
运行结果为:
ymyy@ymyy-virtual-machine:~/systemcode$ ./waitpid_while i am 3th, pid = 24857 i am 2th, pid = 24856 i am 5th, pid = 24859 i am 1th, pid = 24855 i am 4th, pid = 24858 wait child 24855 wait child 24856 wait child 24857 wait child 24858 wait child 24859



