← 返回首页
Linux高级程序设计(三十)
发表时间:2021-11-17 23:03:28
wait函数

父进程可以通过 wait() 或 waitpid() 函数等待子进程结束,获取子进程结束时的状态,同时回收他们的资源。

wait() 和 waitpid() 函数的功能一样,区别在于,wait() 函数会阻塞,waitpid() 可以设置不阻塞,waitpid() 还可以指定等待哪个子进程结束。

1.wait()

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);

等待任意一个子进程结束,如果任意一个子进程结束了,此函数会回收该子进程的资源。在每个进程退出的时候,内核释放该进程所有的资源、包括打开的文件、占用的内存等。但是仍然为其保留一定的信息,这些信息主要主要指进程控制块的信息(包括进程号、退出状态、运行时间等)。调用 wait() 函数的进程会挂起(阻塞),直到它的一个子进程退出或收到一个不能被忽视的信号时才被唤醒(相当于继续往下执行)。若调用进程没有子进程,该函数立即返回;若它的子进程已经结束,该函数同样会立即返回,并且会回收那个早已结束进程的资源。

所以,wait()函数的主要功能为回收已经结束子进程的资源。

以下两个宏定义用来取出子进程的退出信息。 |宏定义|说明| |-|-| |WIFEXITED(status)|如果子进程是正常终止的,取出的字段值非零。| |WEXITSTATUS(status)|返回子进程的退出状态,退出状态保存在 status 变量的 8~16 位。在用此宏前应先用宏 WIFEXITED 判断子进程是否正常退出,正常退出才可以使用此宏。|

实例:

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

int main(int argc, char *argv[])
{
    pid_t pid;

    pid = fork(); // 创建进程
    if (pid < 0)
    { // 出错
        perror("fail to create process:");
        exit(0);
    }

    if (pid == 0)
    { // 子进程
        int i = 0;
        for (i = 0; i < 5; i++)
        {
            printf("this is son process\n");
            sleep(1);
        }

        _exit(2); // 子进程退出,数字 2 为子进程退出的状态
    }
    else if (pid > 0)
    { // 父进程

        int status = 0;

        // 等待子进程结束,回收子进程的资源
        // 此函数会阻塞
        // status 某个字段保存子进程调用 _exit(2) 的 2,需要用宏定义取出
        wait(&status);

        if (WIFEXITED(status) != 0)
        { // 子进程是否正常终止
            printf("son process return %d\n", WEXITSTATUS(status));
        }

        printf("this is father process\n");
    }

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
this is son process
this is son process
this is son process
this is son process
this is son process
son process return 2
this is father process

2.waitpid()

#include <sys/types.h>
#include <sys/wait.h>
//等待子进程终止,如果子进程终止了,此函数会回收子进程的资源。
pid_t waitpid(pid_tpid, int *status, int options);

pid: 参数 pid 的值有以下几种类型:

参数 含义
pid>0 等待进程ID等于pid的子进程。
pid=0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid 不会等待它。
pid=-1 等待任一子进程,此时waitpid和wait作用一样。
pid<-1 等待指定进程组中的任何子进程,这个进程组的 ID 等于 pid 的绝对值。

status: 进程退出时的状态信息。和 wait() 用法一样。

options: options 提供了一些额外的选项来控制 waitpid()。

实例:

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

int main(int argc, char *argv[])
{
    pid_t pid;

    pid = fork(); // 创建进程
    if (pid < 0)
    { // 出错
        perror("fail to create process:");
        exit(0);
    }

    if (pid == 0)
    { // 子进程
        int i = 0;
        for (i = 0; i < 5; i++)
        {
            printf("this is son process\n");
            sleep(1);
        }
        _exit(2); // 子进程退出,数字 2 为子进程退出的状态
    }
    else if (pid > 0)
    { // 父进程
        int status = 0;
        // waitpid(-1, &status, 0); // 和 wait() 没区别,0:阻塞
    // waitpid(pid, &status, 0); // 指定等待进程号为 pid 的子进程, 0 阻塞
    waitpid(pid, &status, WNOHANG); // WNOHANG:不阻塞
        if (WIFEXITED(status) != 0)
        { // 子进程是否正常终止
            printf("son process return %d\n", WEXITSTATUS(status));
        }
        printf("this is father process\n");
    }
    return 0;
}

测试运行:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
son process return 0
this is father process
this is son process
[root@iz2zefozq9h39txdb8s7npz shelldemo]# this is son process
this is son process
this is son process
this is son process