一 . 僵尸进程: 子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程
处理僵尸进程的方法:wait 和 waitpid
调用wait和waitpid不仅可以获得子进程的终止信息,还可以使父进程阻塞等待子进程终止,起到进程间同步的作用。
1. waitpid的原型:
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid,int *status,int options)
第一个参数pid :
参数值 | 说明 |
pid<-1 | 等待进程组号为pid绝对值的任何子进程。 |
pid=-1 | 等待任何子进程,此时的waitpid()函数就退化成了普通的wait()函数。 |
pid=0 | 等待进程组号与目前进程相同的任何子进程,也就是说任何和调用waitpid()函数的进程在同一个进程组的进程。对已经加入了别的进程组子进程不理睬 |
pid>0 | 等待进程号为pid的子进程。 |
第二个参数 int* status:获取子进程的退出状态,不关心可以置为NULL
宏 | 说明 |
WIFEXITED(status) | 如果子进程正常结束,它就返回真;否则返回假。 |
WEXITSTATUS(status) | 如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的结束代码。 |
WIFSIGNALED(status) | 如果子进程因为一个未捕获的信号而终止,它就返回真;否则返回假。 |
WTERMSIG(status) | 如果WIFSIGNALED(status)为真,则可以用该宏获得导致子进程终止的信号代码。 |
WIFSTOPPED(status) | 如果当前子进程被暂停了,则返回真;否则返回假。 |
WSTOPSIG(status) | 如果WIFSTOPPED(status)为真,则可以使用该宏获得导致子进程暂停的信号代码。 |
例如:
if(WIFEXITED(status)){ /* 如果WIFEXITED返回非零值 */ printf("the child process %d exit normally./n",pr); printf("the return code is %d./n",WEXITSTATUS(status));
}
第三个参数:int opotion
参数 | 说明 |
WNOHANG | 设为非阻塞 |
WUNTRACED | 如果子进程进入暂停状态,则马上返回。 |
返回值:
如果waitpid()函数执行成功,则返回子进程的进程号;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果有错误发生,则返回-1,并且将失败的原因存放在errno变量中。
失败的原因主要有:没有子进程或此进程存在,但不是调用进程的子进程(errno设置为ECHILD),调用被某个信号中断(errno设置为EINTR)或选项参数无效(errno设置为EINVAL)
2. wait:阻塞函数 ,相当于waitpid(-1, status, 0)
原型:
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status)
返回值:
如果成功,wait会返回被收集的子进程的进程ID。
如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。
我们知道一个进程的退出状态可以在Shell中用特殊变 量$?查看,因为Shell是它的父进程,当它终止时Shell调用wait或waitpid得到它的退出状态同时彻底清除掉这个进程。
二 . 孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号 进程init进程,称为init进程领养孤儿进程
处理孤儿进程:kill(pid_t,signal_no);
1.通过kill查看父进程是否终止
2.杀死一个进程组
组长的终止不会终止进程组。进程组的终止直到进程组的最后一个进程终止或转移走。