C/C++ execvp()函数完全指南:用法、实例与常见问题解析

这是文章《如何在C/C++中使用execvp()函数》的第1部分(共3部分)。

在本文中,我们将介绍如何在C/C++中使用execvp()函数。

在UNIX系统中,如果您想通过C程序运行另一个程序,execvp()函数非常有用。

注意:此功能仅适用于基于UNIX的操作系统,不能在Windows上运行。

接下来,让我们通过示例说明如何从程序中执行UNIX命令!


execvp()的基本语法

这个函数的第一个参数是要运行的UNIX命令的名称。

该函数在<unistd.h>头文件中定义,因此我们必须在程序中包含它。

#include <unistd.h>

int execvp(const char* command, char* argv[]);

在这里,”命令”指的是任何作为PATH环境变量一部分的二进制可执行文件。因此,如果要运行自定义程序,请确保将其添加到PATH变量中!

第二个参数(argv)表示命令的参数列表,它是一个char*字符串数组。

argv数组包含了完整的命令及其参数。

例如,下面的数组展示了argv的格式:

char* argument_list[] = {"ls", "-l", NULL}; // 以NULL结尾的char*字符串数组

// 执行命令 "ls -l"
execvp("ls", argument_list);

这个数组必须以NULL结尾,即argv的最后一个元素必须是一个NULL指针。

我们的C程序会发生什么?

此功能会将当前进程(C程序)的控制权传递给命令。因此,C程序会立即被实际命令替代。

所以,由于程序被完全接管,execvp()之后的任何代码都不会执行!

然而,如果命令因某种原因执行失败,execvp()将返回-1。

因此,在使用execvp()时,如果希望保持C程序继续运行,通常会先使用fork()创建一个新进程,然后在新进程中调用execvp()。

这被称为”分叉-执行”模型,是使用C语言运行多个进程的标准做法。

接下来,让我们通过一些示例来更好地理解这个功能。我们将结合使用fork()和execvp(),这样我们的C程序就能继续运行!

在C/C++中使用execvp()函数 – 示例

这是文章《如何在C/C++中使用execvp()函数》的第2部分(共3部分)。

如果您想了解在不使用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()函数》的第3部分(共3部分)。

我们学习了在C/C++中使用execvp()函数,从我们的C程序中执行其他程序。但请注意,这将使得其他程序完全控制我们的进程。

由于这个原因,我们需要通过fork()系统调用来把这个过程包含在另一个进程中。希望你能理解,并且能在运行其他程序的同时仍然能控制你的C程序!

参考资料

  • C语言中execvp()函数的Linux手册页

bannerAds