如何在C/C++中使用execvp()函数
在本文中,我们将介绍如何在C/C++中使用execvp()函数。
在UNIX中,如果您想使用我们的C程序运行另一个程序,execvp()函数非常有用。
注意:此功能仅适用于基于UNIX的操作系统。它不能在Windows上运行。
让我们来看一下,使用说明性示例从我们的程序执行UNIX命令!
execvp()的基本语法
这个函数的第一个参数是要运行的UNIX命令的名称。
这个在 头文件中存在,因此我们必须在我们的程序中包含它。
#include <unistd.h>
int execvp(const char* command, char* argv[]);
在这里,我们将“命令”指称为任何作为PATH环境变量的一部分的二进制可执行文件。因此,如果你想运行自定义程序,请确保将其添加到你的PATH变量中!
第二个参数(argv)表示命令的参数列表。它是一个char*字符串数组。
在这里,argv包含了完整的命令以及它的参数。
例如,下面的数组遵循 argv 的格式。
char* argument_list[] = {"ls", "-l", NULL}; // NULL terminated array of char* strings
// Ok! Will execute the command "ls -l"
execvp("ls", argument_list);
这个数组必须以NULL结尾,也就是argv的最后一个元素必须是一个NULL指针。
我们的C程序现在发生了什么?
此功能将控制当前进程(C程序)传递给命令。因此,C程序会立即被实际命令替代。
所以,由于我们的程序被完全接管,execvp()之后的任何内容都不会执行!
然而,如果由于某种原因命令失败,execvp() 将返回 -1。
所以,无论何时使用execvp(),如果你想要保持你的C程序,通常会使用fork()先生成一个新进程,然后在这个新进程上使用execvp()。
这被称为“分叉-执行”模型,是使用C语言运行多个进程的标准做法。
让我们现在看一些例子,以更好地理解这个功能。我们还将与execvp()一起使用fork(),这样我们就可以继续使用我们的C程序!
在C/C++中使用execvp()函数-一些例子
如果你想要看到如果在不使用fork()创建新进程的情况下尝试使用execvp()会发生什么,下面的程序会展示这个情况。
我们将在我们的C程序中执行”ls -l”。
请注意,execvp() 函数后的 printf() 语句不会执行,因为其他进程已经掌控了!
#include <stdio.h>
#include <unistd.h>
int main() {
char* command = "ls";
char* argument_list[] = {"ls", "-l", NULL};
printf("Before calling execvp()\n");
// Calling the execvp() system call
int status_code = execvp(command, argument_list);
if (status_code == -1) {
printf("Process did not terminate correctly\n");
exit(1);
}
printf("This line will not be printed if execvp() runs correctly\n");
return 0;
}
输出
Before calling execvp()
total 3
-rwxrwxrwx 1 user user 22088 May 30 16:37 a.out
-rwxrwxrwx 1 user user 16760 May 30 16:37 sample
-rw-rw-rw- 1 user user 1020 May 30 16:37 sample.c
正如你所见,execvp()后面的部分根本不会执行,因为“ls -l”接管了我们的进程!
我们来重新写同样的例子,但是让我们将execvp()系统调用放在另一个进程中,并使用fork()。
让我们看看现在会发生什么。
#include <stdio.h>
#include <unistd.h>
int main() {
char* command = "ls";
char* argument_list[] = {"ls", "-l", NULL};
printf("Before calling execvp()\n");
printf("Creating another process using fork()...\n");
if (fork() == 0) {
// Newly spawned child Process. This will be taken over by "ls -l"
int status_code = execvp(command, argument_list);
printf("ls -l has taken control of this child process. This won't execute unless it terminates abnormally!\n");
if (status_code == -1) {
printf("Terminated Incorrectly\n");
return 1;
}
}
else {
// Old Parent process. The C program will come here
printf("This line will be printed\n");
}
return 0;
}
输出
Before calling execvp()
Creating another process using fork()...
This line will be printed
user@shell:$ total 3
-rwxrwxrwx 1 user user 22088 May 30 16:37 a.out
-rwxrwxrwx 1 user user 16760 May 30 16:37 sample
-rw-rw-rw- 1 user user 1020 May 30 16:37 sample.c
如果你处于一个Shell环境中,输出可能会看起来很奇怪,但那是因为多个进程并发运行!两个输出都确实被打印出来,所以我们成功解决了问题。
结论
我们学习了在C/C++中使用execvp()函数,从我们的C程序中执行其他程序。但请注意,这将使得其他程序完全控制我们的进程。
由于这个原因,我们需要通过fork()系统调用来把这个过程包含在另一个进程中。希望你能理解,并且能在运行其他程序的同时仍然能控制你的C程序!
参考资料
- Linux manual page on the execvp() function in C