进程等待于原因
一个进程虽然退出了,但是该进程还保留了很多对于程序员或者系统管理员来说有用 的信息。比如,该进程识如何退出的,是正常退出,还是出现了错误,还是被其他进程结束掉,总结来说这个进程的退出码是什么;这个进程占用的CPU时间还有用户时间是多少。
这个时候为了回收这些信息我们就需要父进程调用进程等待函数来进程 信息的一些回收工作,如果一个进程退出了但是一直没有父进程回收它,这个进程就变成了僵尸进程,又名僵死进程。
父进程调用等待函数会发生的情况
- 如果其所有子进程都还在运行,则父进程阻塞;可以这样理解,我们只有一个CUP,这个时候如果其他的子进程在运行的话,我们就没有其他的时间和精力去处理这个已经死亡的进程,所以这个时候父进程会一直阻塞住
- 如果一个子进程已经死亡,正在等待父进程回收其终止状态,则这个时候父进程调用等待函数,并立即返回
- 如果没有任何子进程终止,父进程依然调用了等待函数,则这个时候直接出错返回
进程等待函数
包含头文件
#include<sys/types.h>
#include<sys/wait.h>
- wait函数
pid_t wait(int*status);
返回值:成功则返回等待进程的PID,失败则返回-1
参数:这个status可以是我们之前已经定义的一个int status;我们通过下面即将介绍的一个宏函数,然后把status传入进去可以获取退出状态;如果我们不关心这个退出状态的话,我们可以给这个参数填写上NULL waitpid
pid_t waitpid(pid_t pid, int *status, int options
返回值:- 当正常返回的时候waitpid返回收集到的子进程的进程ID;
- 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,
则返回0; - 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
- 当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就
会出错返回,这时errno被设置为ECHILD.
参数:
- pid:
pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
Pid==0等待其组ID等于调用进程组ID的任一个子进程。
Pid<-1等待其组ID等于pid绝对值的任一子进程。
(这个时候我们可以在waitpid这个函数的第一个参数中填写如相应的数字,比如-1,这个时候就可以等待任意的一个进程;如果我们填写 的是一个大于0的一个数字,一般这个数字就是一个进程号,就是某一个特定的进程,我们就可以等待这个特定的进程;其他的一个参数设置类似) - status:
WIFEXITED(status) :
若为正常终止子进程返回的状态(这里就是一个返回状态),则为真。 (查看进程是
否是正常退出)
WEXITSTATUS(status) :
若WIFEXITED非零,提取子进程退出码。(查看进程
的退出码) - options:
WNOHANG :若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。
若正常结束,则返回该子进程的ID。
程序实例讲解
进程的阻塞等待方式
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main()
{
pid_t sunpid = fork();
if(sunpid < 0)
{
printf("fork error\n");
}
else if(sunpid == 0) //子进程
{
printf("i am sun\n");
//sleep(10);
printf("i will exit. my pid is %d\n",getpid());
sleep(10);
exit(9); //我刚刚测试这个代码的时候,一直是等待失败,可能 和我这个exit有关,我不用这个了,直接什么都不用,看看是什么效果
}
else //父进程
{
int status;
pid_t sun;
//这里调用的是阻塞式等待,所以预期的结果是子进程打印出了i am sun之后五秒中之后,子进程打印i will exit ...然后父进程打印子进程的id,等待成功
while(1)
{
sleep(10);
sun = wait(&status); //如果等待成功了返回等待进程的pid,如果失败则返回-1
if(sun == -1)
{
printf("等待失败\n");
sleep(1);
}
else
{
printf("等待成功,子进程id是%d\n",sun);
printf("返回码为%d\n",WEXITSTATUS(status));
printf("返回状态为%d\n",WIFEXITED(status));
break;
}
}
}
return 0;
}