wait()和waitpid()函数

分享到:
           

    1)wait()和waitpid()函数说明

    wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()就会立即返回。

    waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能,也能支持作业控制。实际上,wait()函数只是waitpid()函数的一个特例,在Linux内部实现wait()函数时直接调用的就是waitpid()函数。

    2)wait()和waitpid()函数格式说明

    表1列出了wait()函数的语法要点。

表1 wait()函数语法要点

所需头文件 #include <sys/types.h>
#include <sys/wait.h>
函数原型 pid_t wait(int *status)
函数传入值 这里的status是一个整型指针,是该子进程退出时的状态。若status不为空,则通过它可以获得子进程的结束状态。另外,子进程的结束状态可由Linux中一些特定的宏来测定
函数返回值 成功:已结束运行的子进程的进程号
失败:-1

    表2列出了waitpid()函数的语法要点。

表2 waitpid()函数语法要点

所需头文件 #include <sys/types.h>
#include <sys/wait.h>
函数原型 pid_t waitpid(pid_t pid, int *status, int options)
函数传入值 pid pid > 0:只等待进程ID等于pid的子进程,不管是否已经有其他子进程运行结束退出,只要指定的子进程还没有结束,waitpid()就会一直等下去
pid = -1:等待任何一个子进程退出,此时和wait()作用一样
pid = 0:等待其组ID等于调用进程的组ID的任一子进程
pid < -1:等待其组ID等于pid的绝对值的任一子进程
status 同wait()
options WNOHANG:若由pid指定的子进程没有结束,则waitpid()不阻塞而立即返回,此时返回值为0
WUNTRACED:为了实现某种操作,由pid指定的任一子进程已被暂停,且其状态自暂停以来还未报告过,则返回其状态
0:同wait(),阻塞父进程,等待子进程退出
函数返回值 正常:已经结束运行的子进程的进程号
使用选项WNOHANG且没有子进程退出:0
调用出错:-1

    3)waitpid()使用实例

    由于wait()函数的使用较为简单,在此仅以waitpid()为例进行讲解。本例中首先使用fork()创建一个子进程,然后让其子进程暂停5s(使用了sleep()函数)。接下来对原有的父进程使用waitpid()函数,并使用参数WNOHANG使该父进程不会阻塞。若有子进程退出,则waitpid()返回子进程号;若没有子进程退出,则waitpid()返回0,并且父进程每隔1s循环判断一次。该程序的流程图如图1所示。


图1 waitpid()函数程序流程图

    该程序源代码如下:

    /* waitpid.c */
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {
        pid_t pc, pr;

        pc = fork();
        if (pc < 0)
        {
            printf("Error fork\n");
        }
        else if (pc == 0) /* 子进程 */
        {
            /* 子进程暂停5s */
            sleep(5);
            /* 子进程正常退出 */
            exit(0);
        }
        else /* 父进程 */
        {
            /* 循环测试子进程是否退出 */
            do
            {
                /* 调用waitpid(),且父进程不阻塞 */
                pr = waitpid(pc, NULL, WNOHANG);

                /* 若子进程还未退出,则父进程暂停1s */
                if (pr == 0)
                {
                    printf("The child process has not exited\n");
                    sleep(1);
                }
            } while (pr == 0);

            /* 若发现子进程退出,打印出相应情况 */
            if (pr == pc)
            {
                printf("Get child exit code: %d\n",pr);
            }
            else
            {
                printf("Some error occured.\n");
            }
        }
    }

    将该程序交叉编译,下载到目标板后的运行结果如下:

    $ ./waitpid
    The child process has not exited
    The child process has not exited
    The child process has not exited
    The child process has not exited
    The child process has not exited
    Get child exit code: 75

    可见,该程序在经过5次循环后,捕获到了子进程的退出信号,具体的子进程号在不同的系统上会有所区别。

    读者还可以尝试把“pr = waitpid(pc, NULL, WNOHANG);”改为“pr = waitpid(pc, NULL, 0);”或者“pr = wait(NULL);”,运行的结果为:

    $ ./waitpid
    Get child exit code: 76

    可见,在上述两种情况下,父进程在调用waitpid()或wait()之后就将自己阻塞,直到有子进程退出为止。

    本文选自华清远见嵌入式培训教材《从实践中学嵌入式Linux应用程序开发》

   热点链接:

   1、exit()和_exit()函数
   2、Linux下多进程编程之exec函数语法及使用实例
   3、Linux下多进程编程之fork()函数语法
   4、Linux下多进程编程之fork()函数说明
   5、Linux下多任务系统之线程介绍

更多新闻>>