wait,waitpid的学习使用
man wait
man waitpid
从中可知
函数原型
pid_t wait(int* status);
pid_t waitpid(pid_t pid, int* status, int options);
函数说明
父进程创建子进程之后,父进程使用wait和waitpid具有监视子进程的运行状态的能力。这两个函数用于等待子进程的状态发生变化回调并且获取状态发生变化的信息,所能获取的状态变化包括:子进程运行结束,子进程被信号量暂停,子进程被信号量回复运行。
父进程执行wait函数之后,父进程会被阻塞在此处,如果子进程状态发生变化,则wait函数会立即返回结果;否则wait函数会一直阻塞直到子进程状态发生变化。
通常意义上,,如果子进程状态发生了变化,但是还是未被其父进程或者其他系统回调执行wait函数,此时的子进程被称为可等待的。
子进程运行结束后父进程执行wait函数可以推动系统释放与子进程相关的资源;否则子进程将会被维持在僵尸进程(子进程已结束,而父进程还在运行)的状态下一直存在。
返回值说明
上述函数的返回值有-1,0,>0三种情况。分别对应于以下三种情况返回。
-1:调用出错,此时出错信息在errno中
0:若waitpid的options设置了WNOHANG,且调用中没有子进程退出,立即返回0
0:若大于0,返回退出进程的pid。
参数说明
pid:要监听的进程的ID(<-1, =-1, =0, > 0)
status: 用于存储出发状态变化时的信号值和exit(code)中的code值。
options 提供一些额外的选项控制waitpid,目前linux中只支持WNOHANG和WUNTRACED两个选项,这是两个常数宏,可以使用|连接使用.
pid详细说明:
pid < -1 : 监听范围为进程组为-pid的所有子进程
pid = -1 : 监听范围为调用wait/waitpid的所有子进程
pid = 0: 监听范围为子进程的进程组ID(与父进程相等)
pid > 0: 监听特定pid的进程
status详细说明
status用于保存出发wait的信号值或者退出时exit(code)中的code值
options详细说明
WNOHANG : 使用此参数调用waitpid,即使子进程没有退出,他也会立即返回,而不是像wait一直等下去
WUNTRACED : 用于调试,极少用
一般情况下使用值为0即可。
wait与waitpid关系
wait实质上是waitpid中pid=-1,options=0时封装,即
wait(&status)与waitpid(-1, &status, 0)完全相同,这是wait函数和waitpid的最本质关系。
函数调用示例:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
main()
{
pid_t pc,pr;
int a;
pc=fork();
if(pc<0)
printf("error ocurred!/n");
else if(pc==0){
printf("This is child process with pid of %d\n",getpid());
}
else{
printf("this is parent process\n");
pr=wait(&a);
printf("I catched a child process with pid of %d\n",pr);
}
exit(0);
}
执行可以发现,父进程执行到wait函数时阻塞,然后系统执行子进程,结束之后通过pr返回结束进程的进程号,同时给一个int指针a,可以查看进程的情况。
因为wait函数本质是,waitpid函数的定参封装,内部实现相同,故给出一个waitpid()的调用实例:
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main(){
pid_t pc,pr;
pc=fork();
if(pc<0) printf("error");
else
if(pc==0){
sleep(10);
exit(0);
}
do{
pr=waitpid(pc,NULL,WNOHANG);
if(pr==0){
printf("we haven't get the child process\n");
sleep(1);
}
}while(pr==0);
if(pr==pc)
printf("we get the child process\n");
}
如果判断自身为子进程,则睡眠十秒钟,在此期间的父进程并没有被阻塞,还在不断的通过do循环接收子进程的执行情况,每次判断间隔
一秒钟。最终十秒后获得了子进程结束的标志,打印we get the child process