迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C语言 >

使用 C 语言中的 waitpid 函数

作者:迹忆客 最近更新:2023/03/28 浏览次数:

本文将演示关于如何使用 C 语言中的 waitpid 函数的多种方法。


在 C 语言中使用 waitpid 函数监控子进程状态

在基于 Unix 的系统中,有一个进程的概念,它只是一个程序的运行实例。该进程可以使用 fork 系统调用创建其他进程,并执行给定的部分代码。需要注意的是,在本专题中,系统调用是以 C 式函数的形式提供给用户的操作系统服务。一般来说,在很多场景下,程序需要监视它创建的称为子进程的进程。wait 函数族就是提供这种功能的,waitpid 就是其中之一。

wait 系统调用有多种限制,为了覆盖更高级的功能,需要利用 waitpid 函数。即,如果一个进程创建了多个子进程,而父进程需要监控某个特定的子进程,只有 waitpid 可以做到这一点。在下面的例子中,我们实现了一个名为 spawnChild 的函数,它可以创建一个新的子进程,并执行不同的程序。为了很好地演示这个例子,我们正在执行一个 top 程序(几乎所有基于 Unix 的系统都有),这个程序一直运行到用户终止它。一旦函数在父进程中返回,我们就存储一个子进程的 ID,并将其传递给 waitpid 函数来监视状态。

waitpid 需要三个参数,其中第一个参数是进程 PID 号(pid)。pid 可以有多个预先指定的值,并有不同的效果,但在本例中,我们只提 -1>0-1 值可以传递给监控任何先改变其状态的子进程,它用来实现 wait 功能。>0 意味着该值应该是由 fork 函数返回的实际进程 ID,而这个 ID 又只用来监视特定的子进程。第二个参数的类型是 int 指针,我们应该声明一个整数变量,将其地址传递给函数。而 waitpid 则会将子进程的状态信息存储在给定的 int 变量中,然后可以使用预定义的宏进行解码。最后一个参数的类型是 int,除了默认的事件外,它还用来指定要监控的某些子进程事件。

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

pid_t spawnChild(const char* program, char** arg_list)
{
    pid_t ch_pid = fork();
    if (ch_pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (ch_pid > 0) {
        printf("spawn child with pid - %d\n", ch_pid);
        return ch_pid;
    } else {
        execvp(program, arg_list);
        perror("execve");
        exit(EXIT_FAILURE);
    }
}

int main(void) {
    const char *args[] = { "top", NULL, NULL };

    pid_t child;
    int wstatus;

    child = spawnChild("top", args);

    if (waitpid(child, &wstatus, WUNTRACED | WCONTINUED) == -1) {
        perror("waitpid");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

在 C 语言中使用宏来显示子进程的等待状态

需要注意的是,当 waitpid 函数被调用时,父进程是被暂停的,直到被监控的子进程改变状态,它才会恢复执行。下一个例子显示了 waitpid 调用时带有 WUNTRACEDWCONTINUED 参数,这意味着父进程通过相应的信号来监控子进程是否被停止或继续。另外,我们还实现了 printWaitStatus 函数,可以调用它来打印检索到的子程序状态。注意,它是使用 <sys/wait.h> 头中定义的 W*类型宏,从 status 整数变量中提取编码信息。

由于不是所有的宏在所有的平台上都可以使用,所以有一些条件性的预处理程序定义,从而保证了函数的可移植性,无论如何都能编译成功。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

pid_t spawnChild(const char* program, char** arg_list)
{
    pid_t ch_pid = fork();
    if (ch_pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (ch_pid > 0) {
        printf("spawn child with pid - %d\n", ch_pid);
        return ch_pid;
    } else {
        execvp(program, arg_list);
        perror("execve");
        exit(EXIT_FAILURE);
    }
}

void printWaitStatus(int status)
{
    if (WIFEXITED(status)) {
        printf("child exited, status=%d\n", WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
        printf("child killed by signal %d (%s)",
               WTERMSIG(status), strsignal(WTERMSIG(status)));
#ifdef WCOREDUMP
        if (WCOREDUMP(status))
            printf(" (core dumped)");
#endif
        printf("\n");
    } else if (WIFSTOPPED(status)) {
        printf("child stopped by signal %d (%s)\n",
               WSTOPSIG(status), strsignal(WSTOPSIG(status)));
#ifdef WIFCONTINUED
    } else if (WIFCONTINUED(status)) {
        printf("child continued\n");
#endif
    } else {
        printf("status=%x\n",
               (unsigned int) status);
    }
}

int main(void) {
    const char *args[] = { "top", NULL, NULL };

    pid_t child;
    int wstatus;

    child = spawnChild("top", args);

    if (waitpid(child, &wstatus, WUNTRACED | WCONTINUED) == -1) {
        perror("waitpid");
        exit(EXIT_FAILURE);
    }

    printWaitStatus(wstatus);

    exit(EXIT_SUCCESS);
}

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 C 语言中使用 typedef enum

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。

C 语言中的静态变量

发布时间:2023/05/07 浏览次数:151 分类:C语言

本文介绍了如何在 C 语言中使用静态变量。在 C 语言中使用 static 变量在函数调用之间保存变量值

C 语言中生成随机数

发布时间:2023/05/07 浏览次数:64 分类:C语言

本文演示了如何在 C 语言中生成随机数。使用 rand 和 srand 函数在 C 语言中生成随机数

C 语言中的 i++ 与++i

发布时间:2023/05/07 浏览次数:83 分类:C语言

本文演示了如何在 C 语言中使用前缀增量与后缀增量运算符。C 语言中++i 和 i++ 记号的主要区别

C 语言中获取当前工作目录

发布时间:2023/05/07 浏览次数:182 分类:C语言

本文演示了如何在 C 语言中获取当前工作目录。使用 getcwd 函数获取当前工作目录的方法

C 语言中的位掩码

发布时间:2023/05/07 浏览次数:126 分类:C语言

本文介绍了如何在 C 语言中使用位掩码。使用 struct 关键字在 C 语言中定义位掩码数据

C 语言中的排序函数

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文演示了如何在 C 语言中使用标准库排序函数。使用 qsort 函数对 C 语言中的整数数组进行排序

C 语言中的 extern 关键字

发布时间:2023/05/07 浏览次数:114 分类:C语言

本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量

C 语言中的 #ifndef

发布时间:2023/05/07 浏览次数:186 分类:C语言

本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便