现在的位置: 首页 > 综合 > 正文

wait和waitpid函数

2013年10月20日 ⁄ 综合 ⁄ 共 3627字 ⁄ 字号 评论关闭
 

(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工具与编程》

抱歉!评论已关闭.