C 语言中的 execvp 函数

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

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

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

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

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.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);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook

相关文章 - C Process