C 语言中的 execvp 函数

Jinku Hu 2023年1月30日 2021年2月7日
  1. 在 C 语言中使用 execvp 函数替换进程映像
  2. 正确处理 execvp 函数调用错误方案和相应的输出消息
  3. 在 C 语言中使用 execvpfork 函数创建一个子进程并执行不同的程序
C 语言中的 execvp 函数

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

在 C 语言中使用 execvp 函数替换进程映像

在基于 Unix 的系统中,有两个独立的系统调用来创建一个新的进程和将新的程序代码加载到一个正在运行的进程中。后者使用 exec 系列库函数来完成,这些函数只是 execve 系统调用的不同接口。有 6 种不同的函数原型。execlpexecleexecvexecvpexecvpe。这些函数以一个文件名或一个新程序文件的路径名作为第一个参数来加载和执行。execvp 也接受一个程序参数数组作为第二个参数。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(void) {
    const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };

    execvp("vim", args);

    exit(EXIT_SUCCESS);
}

正确处理 execvp 函数调用错误方案和相应的输出消息

需要注意的是,exec 系列函数只有在发生错误时才会返回,所以要实现错误检查例程,并根据需要处理相应的代码路径。
其中 execvp 在失败时返回 -1,而且它还会设置 errno 变量。不过要注意,errno 应该在函数调用前明确设置为 0,只有在给定的调用返回后才检查该值。execvp 函数可以接受没有斜线的文件名,这意味着文件是在 PATH 环境变量指定的目录中搜索的。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(void) {
    const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };

    errno = 0;
    if (execvp("vim", args) == -1) {
        if (errno == EACCES)
            printf("[ERROR] permission is denied for a file\n");
        else
            perror("execvp");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

在 C 语言中使用 execvpfork 函数创建一个子进程并执行不同的程序

另外,假设用户需要创建一个新的进程,并执行给定的程序代码,那么在这种情况下,我们可以利用 fork 函数调用与 execvp 相结合。在这种情况下,我们可以利用 fork 函数调用与 execvp 相结合。fork 复制调用的进程,并创建一个新的进程,称为-子进程。在下面的例子中,我们实现了一个自定义函数包装器来创建一个新的进程并加载/执行给定的程序代码。请注意,一旦创建了子进程,它就会执行不同的代码,而父进程则会等待,直到子进程退出。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.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[] = { "vim", "/home/ben/tmp3.txt", NULL };

    pid_t child;
    int wstatus;

    child = spawnChild("vim", args);

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

    exit(EXIT_SUCCESS);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相关文章 - C Process