(1)wait函数说明
当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件,这种信号也是内核向父进程发的异步通知。父进程可以忽略该信号,或者提供一个该信号发生时即被调用执行的函数(信号处理程序)。
父进程同步等待子进程退出时则调用wait函数,此时父进程可能会有如下三种情形:
① 阻塞(如果其所有子进程都还在运行)。
② 带回子进程的终止状态立即返回(如果已有一个子进程终止,正等待父进程取其终止状态)。
③ 出错立即返回(如果它没有任何子进程)。
(2)wait与waitpid函数原型
wait(等待子进程的中断和结束)
所需头文件 | #include <sys/types.h> #include <sys/wait.h> | |
函数说明 | wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则status可以设成NULL | |
函数原型 | pid_t wait (int *status) | |
函数传入值 | status | 这里的status 是一个整型指针,是该子进程退出时的状态: status 若为空,则代表不记录子进程结束状态 status 若不为空,则由status记录子进程的结束状态值 另外,子进程的结束状态可由 Linux中一些特定的宏来测定 |
函数返回值 | 成功 | 返回子进程识别码(PID) |
出错 | -1,失败原因存于errno中 |
waitpid(等待子进程的中断和结束)
所需头文件 | #include <sys/types.h> #include <sys/wait.h> | |
函数说明 | waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status可以设成NULL。参数pid为欲等待的子进程识别码 | |
函数原型 | pid_t waitpid(pid_t pid,int * status,int options) | |
函数传入值
| pid | <-1:等待进程组识别码为pid绝对值的任何子进程 |
-1: 等待任何子进程,相当于wait() | ||
0:等待进程组识别码与目前进程相同的任何子进程 | ||
>0:等待任何子进程识别码为pid的子进程 | ||
options | 参数options可以为0 或下面的OR 组合 | |
WNOHANG:如果没有任何已经结束的子进程则马上返回,不予以等待。此时返回值为0 | ||
WUNTRACED:如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会 | ||
函数传出值 | status | 同wait函数 |
函数返回值 | 成功 | 返回子进程识别码(PID) |
使用选项WNOHANG且没有子进程退出返回0 | ||
出错 | -1,失败原因存于errno中 |
对status状态判断的宏
说明 | 子进程的结束状态返回后存于status |
宏 | 宏意义说明 |
WIFEXITED(status) | 如果子进程正常结束返回的值。取exit或_exit的低8位 |
WEXITSTATUS(status) | 取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏 |
WIFSIGNALED(status) | 如果子进程是因为信号而结束则此宏值为真 |
WTERMSIG(status) | 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏 |
WIFSTOPPED(status) | 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况 |
WSTOPSIG(status) | 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED来判断后才使用此宏 |
子进程的终止信息存放在一个int变量中,其中包含了多个字段位。用宏定义可以取出其中的每个字段位:如果子进程是正常终止的,WIFEXITED取出的字段值非零,WEXITSTATUS取出的字段值就是子进程的退出状态。如果子进程是收到信号而异常终止的,WIFSIGNALED取出的字段值非零,WTERMSIG取出的字段值就是信号的编号。
(3)wait和waitpid两函数的说明
如果父进程的所有子进程都还在运行,调用wait将使父进程阻塞,而调用waitpid时,如果在options参数中指定WNOHANG可以使父进程不阻塞而立即返回0。
wait等待第一个终止的子进程,而waitpid可以通过pid参数指定等待哪一个子进程。
当pid=-1、option=0时,waitpid函数等同于wait,可以把wait看作waitpid实现的特例。
可见,调用wait和waitpid不仅可以获得子进程的终止信息,还可以使父进程阻塞等待子进程终止,起到进程间同步的作用。如果参数status不是空指针,则子进程的终止信息通过这个参数传出,如果只是为了同步而不关心子进程的终止信息,可以将status参数指定为NULL。
waitpid函数提供了wait函数没有提供的三个功能:
① waitpid等待一个特定的进程,而wait则返回任一终止子进程的状态 。
② waitpid提供了一个 wait的非阻塞版本,有时希望取得一个子进程的状态, 但不想进程阻塞。
③ waitpid支持作业控制。
(3)wait函数使用实例
wait.c源代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int status,i;
if(fork()==0){
printf("This is the child process pid =%d\n",getpid());
exit(5);
}else{
sleep(1);
printf("This is the parent process,wait for child...\n");
pid=wait(&status);
i=WEXITSTATUS(status);
printf("child pid =%d, exit status=%d\n",pid,i);
}
return 0 ;
}
编译 gcc wait.c –o wait。
执行 ./wait,执行结果如下:
This is the child process pid =6904
This is the parent process ,wait for child...
child pid =6904, exit status=5
(4)waitpid函数使用实例
waitpid.c源代码如下:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
if (pid == 0) { //子进程
int i;
for (i = 3; i > 0; i--) {
printf("This is the child\n");
sleep(1);
}
exit(3);
} else { //父进程
int stat_val;
waitpid(pid, &stat_val, 0); /*阻塞等待子进程*/
if (WIFEXITED(stat_val))
printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
else if (WIFSIGNALED(stat_val))
printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
}
return 0;
}
编译 gcc waitpid.c –o waitpid。
执行 ./waitpid,执行结果如下:
This is the child
This is the child
This is the child
Child exited with code 3
摘录自《深入浅出Linux工具与编程》