C 语言中的 execvp 函数
Jinku Hu
2023年10月12日
本文将演示如何在 C 语言中使用 execvp
函数的多种方法。
在 C 语言中使用 execvp
函数替换进程映像
在基于 Unix 的系统中,有两个独立的系统调用来创建一个新的进程和将新的程序代码加载到一个正在运行的进程中。后者使用 exec
系列库函数来完成,这些函数只是 execve
系统调用的不同接口。有 6 种不同的函数原型。execlp
、execle
、execv
、execvp
和 execvpe
。这些函数以一个文件名或一个新程序文件的路径名作为第一个参数来加载和执行。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 语言中使用 execvp
与 fork
函数创建一个子进程并执行不同的程序
另外,假设用户需要创建一个新的进程,并执行给定的程序代码,那么在这种情况下,我们可以利用 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