wait和waitpid函数

来源:互联网 发布:java窗口按钮大小 编辑:程序博客网 时间:2024/05/15 04:21

当一个进程正常或异常终止时,内核就向其父进程发送一个SIGCHLD信号。因为子进程终止是一个异步事件,所以发生这种信号也是内核向父进程发的异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数。对于这种信号的系统默认动作是忽略它。

调用wait或waitpid的进程可能会发生的情况: 

1.如果其所有子进程都还在运行,则阻塞 

2.如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回。 

3.如果它没有任何子进程,则立即出错返回


一、函数声明

1.wait函数

 pid_t wait(int *status);     

1) 返回值:成功返回被等待进程pid,失败返回-1。     

2) 参数: 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL 

2. waitpid函数

 pid_t waitpid(pid_t pid, int *status, int options);     

1) 返回值:         

a. 当正常返回的时候waitpid返回收集到的子进程的进程ID;         

b. 如果设置了选项WNOHANG, 而调用中waitpid发现没有已退出的子进程可收集, 则返回0;         

c. 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;       

d. 当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD.     

2) 参数:         

a.  pid:

Pid=-1,等待任一个子进程。与wait等效;  Pid>0,等待其进程ID与pid相等的子进程;Pid==0等待其组ID等于调用进程组ID的任一个子进程;Pid<-1等待其组ID等于pid绝对值的任⼀一⼦子进程。        

b.  status:           

 WIFEXITED(status)  : 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)  

 WEXITSTATUS(status) : 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码) 

 WIFSIGNALED(status) 若为子进程异常终止返回状态(收到一个未捕捉的信号),则为真  

 WIFSTOPPED 若为子进程意外终止,则为真      

 c.  options:            

 WNOHANG :若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。 若正常结束,则返回该子进程的ID。 

WUNTRACED: 若某个实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态。

3. status意义

status指出了子进程是正常退出还是被非正常结束的(一个进程也可以被其他进程用信号结束),以及正常结束时的返回值,或被哪一个信号结束或进程的退出码是多少等信息,这些信息都被放在整数的不同二进制位中,status的低8位为零,次低8位为真正退出码。

二、wait函数和waitpid函数的区别:

1. 在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。

2. waitpid并不等待第一个终止的子进程-----它有若干个选项,可以控制它所等待的进程。

3. waitpid函数等待一个特定的进程,而wait则返回任一终止子进程的状态。

4.waitpid提供了一个wait的非阻塞版本。

5.waitpid支持作业控制。

三、一些实例

1.进程的阻塞等待方式

#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/wait.h>int main(){pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n", __FUNCTION__);return 1;}else if(pid == 0){printf("child is run, pid is: %d\n", getpid());sleep(3);exit(257);}else{int status = 0;pid_t ret = waitpid(-1, &status, 0); //阻塞式等待printf("this is test for wait\n");if(WIFEXITED(status) && ret == pid) // WIFEXITED(status): 若为正常终止子进程返回的状态,则为真.(查看进程是否是正常退出) {printf("wait child  success, child return code is: %d\n", WEXITSTATUS(status)); // WEXITSTATUS(status): 若WIFEXITED非0,提取子进程退出码.(查看进程的退出码)}else{printf("wait child failed, return.\n");return 1;}}return 0;}
运行结果:


2. 进程的非阻塞等待方式

#include<stdio.h>#include<stdlib.h>#include<sys/wait.h>#include<unistd.h>int main(){pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n", __FUNCTION__);return 1;}else if(pid == 0){printf("child is running, pid is: %d\n", getpid());sleep(5);exit(1);}else{int status = 0;pid_t ret = 0;do{ret = waitpid(-1, &status, WNOHANG); //非阻塞等待if(ret == 0){printf("child is running\n");}sleep(1);}while(ret == 0);if(WIFEXITED(status) && ret == pid){printf("wait child success, child return code is: %d\n",WEXITSTATUS(status));}else{printf("wait child failed,return.\n");return 1;}}return 0;}

运行结果:


3. 等待多个子进程方式

#include<stdio.h>#include<stdlib.h>#include<sys/wait.h>#include<unistd.h>#include<time.h>#define _PROC_NUM_ 10#define _DEFAULT_PID_ -1int child_run(){srand(time(NULL));int _time = rand()%30;printf("this child pid is: %d, sleep time is: %d\n", getpid(), _time);sleep(_time);return 0;}int creat_proc(pid_t *pid, int num){if(pid != NULL && num > 0){int i = 0;for(; i < num; i++){pid_t id = fork();if(id < 0){printf("%s: creat %d proc failed\n", __FUNCTION__, i);return 1;}else if(id == 0){int child_ret = child_run();exit(1);}else{pid[i] = id;}}}return 0;}int wait_proc(pid_t *pid, int num){int wait_ret = 0;if(pid != NULL && num > 0){int i = 0;for(; i < num; i++){if(pid[i] == _DEFAULT_PID_){continue;}int status = 0;int ret = waitpid(pid[i], &status, 0);if(WIFEXITED(status) && ret == pid[i]){printf("wait child pid %d success, return code is: %d\n", pid[i], WEXITSTATUS(status));}else{printf("wait child pid %d failed\n", pid[i]);wait_ret = 1;}}}return wait_ret;}//wait子进程传入的status,它的低8位为零,次低8位为真正退出码.int main(){pid_t pid_list[_PROC_NUM_];int i = 0;for(; i < _PROC_NUM_; i++){pid_list[i] = _DEFAULT_PID_;}if(creat_proc(pid_list, sizeof(pid_list)/sizeof(pid_list[0])) == 0){printf("%s: create all proc successs!\n", __FUNCTION__);}else{printf("%s: not all proc create success!\n", __FUNCTION__);}if(wait_proc(pid_list, sizeof(pid_list)/sizeof(pid_list[0])) == 0){printf("%s: wait all proc success!\n", __FUNCTION__);}else{printf("%s: not all proc wait success!\n", __FUNCTION__);}return 0;}

运行结果:


1 0