一.函数原型
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
二.返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。
三.函数说明
参数 status 是一个整形指针。如果status不是一个空指针,则终止进程的终止状态将存储在该指针所指向的内存单元中。如果不关心终止状态,可以将 status参数设置为NULL。
status 不是NULL时子进程的结束状态值会由参数 status 返回,而子进程的进程识别码作为函数返回值返回。
调用 wait 函数时,调用进程将会出现下面的情况:
· 如果其所有子进程都还在运行,则阻塞。
· 如果一个子进程已经终止,正等待父进程获取其终止状态,则获取该子进程的终止状态然后立即返回。
· 如果没有任何子进程,则立即出错返回。
四。僵尸进程
僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果父进程先退出 ,子进程被init接管,子进程退出后init会回收其占用的相关资源
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = vfork();
if(pid > 0){//父进程没有调用wait()等待子进程
while(1){
printf("this is father pid, pid = %d\n",getpid());
printf("father cnt = %d\n",cnt);
sleep(3);
}
}else if(pid == 0){
while(1){
printf("this is child pid ,pid = %d\n",getpid());
cnt++;
printf("child cnt = %d\n",cnt);
sleep(3);
if(cnt == 5){
exit(0);
}
}
}
return 0;
}
运行结果:
五.父进程等待子进程的退出,并收集其状态
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
int status;
pid = fork();
if(pid > 0){
//wait(NULL);
wait(&status);//等待子进程
/* wait与waitpid的区别:
wait使调用者阻塞,waitpid有一个选项,可以使调用者不阻塞
*/ // waitpid(pid,&status,WNOHANG);
printf("child quit,child status = %d\n",WEXITSTATUS(status));//收集子进程返回状态
while(1){
printf("this is father pid, pid = %d\n",getpid());
printf("father cnt = %d\n",cnt);
sleep(3);
}
}else if(pid == 0){
while(1){
printf("this is child pid ,pid = %d\n",getpid());
cnt++;
printf("child cnt = %d\n",cnt);
sleep(3);
if(cnt == 5){
exit(3);
}
}
}
return 0;
}
运行结果
六.孤儿进程
在类UNIX操作系统中,子进程是通过父进程创建的,子进程再创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。当一个父进程由于正常完成工作而退出或由于其他情况被终止,它的一个或多个子进程却还在运行,那么那些子进程将成为孤儿进程。为避免孤儿进程退出时无法释放所占用的资源而僵死,进程号为1的init进程将会接受这些孤儿进程,这一过程也被称为“收养”。
代码展示:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
int status;
pid = vfork();
if(pid > 0){
printf("this is father pid, pid = %d\n",getpid());
}else if(pid == 0){
while(1){
printf("this is child pid ,pid = %d,father pid = %d\n",getpid(),getppid());
cnt++;
printf("child cnt = %d\n",cnt);
sleep(3);
if(cnt == 5){
exit(3);
}
}
}
return 0;
}
运行结果: