Contents

Exec函数家族

1. 概述

在本文中,我们将讨论 *exec ()*系列函数、它们的作用以及它们之间的区别。

这些函数用于执行文件,一旦被调用,它们就会用新的过程映像替换当前的过程映像。尽管它们非常相似,但它们之间存在差异,并且它们中的每一个都接收不同的信息作为论据。

2. execl()

execl()接收可执行文件的位置作为其第一个参数。当文件执行时,下一个参数将可用于文件。最后一个参数必须是NULL

int execl(const char *pathname, const char *arg, ..., NULL)

让我们看一个例子。我们需要确保包含unistd.h

#include <unistd.h>
int main(void) {
    char *file = "/usr/bin/echo";
    char *arg1 = "Hello world!";
	
    execl(file, file, arg1, NULL);
    return 0;
}

我们正在运行的命令是 echo,它位于*/usr/bin/echo*。按照惯例,程序可用的第一个参数必须是程序本身。

现在我们可以编译并运行代码:

$ gcc execl.c -o execl
$ ./execl
Hello world!

echo已成功在屏幕上打印输出。

3. execlp()

*execlp()execl()*非常相似。但是,*execlp()*使用 PATH 环境变量来查找文件。因此,不需要可执行文件的路径:

int execlp(const char *file, const char *arg, ..., NULL)

让我们看一个例子:

#include <unistd.h>
int main(void) {
    char *file = "echo";
    char *arg1 = "Hello world!";
    execlp(file, file, arg1, NULL);
    return 0;
}

现在我们可以编译并运行它:

$ gcc execlp.c -o execlp
$ ./execlp
Hello world!

由于echo已经位于 PATH 环境变量中,我们不必指定它的位置。

4. execle()

如果我们使用 execle(),我们可以将环境变量传递给函数,它会使用它们:

int execle(const char *pathname, const char *arg, ..., NULL, char *const envp[])

例如:

#include <unistd.h>
int main(void) {
    char *file = "/usr/bin/bash";
    char *arg1 = "-c";
    char *arg2 = "echo $ENV1 $ENV2!";
    char *const env[] = {"ENV1=Hello", "ENV2=World", NULL};
	
    execle(file, file, arg1, arg2, NULL, env);
    return 0;
}

现在我们可以编译并运行它:

$ gcc execle.c -o execle
$ ./execle
Hello World!

bash成功接收到环境变量并将它们打印在屏幕上。

5. execv()

*execv()execl()*不同,它接收可执行文件可用的参数向量。此外,向量的最后一个元素必须为 NULL:

int execv(const char *pathname, char *const argv[])

让我们看一个例子:

#include <unistd.h>
int main(void) {
    char *file = "/usr/bin/echo";
    char *const args[] = {"/usr/bin/echo", "Hello world!", NULL};
	
    execv(file, args);
    return 0;
}

现在我们可以编译并运行它:

$ gcc execv.c -o execv
$ ./execv
Hello world!

6. execvp()

就像 *execlp()*一样,*execvp()*在 PATH 环境变量中查找程序:

int execvp(const char *file, char *const argv[])

例如:

#include <unistd.h>
int main(void) {
    char *file = "echo";
    char *const args[] = {"/usr/bin/echo", "Hello world!", NULL};
	
    execvp(file, args);
    return 0;
}

现在我们可以编译并运行它:

$ gcc execvp.c -o execvp
$ ./execvp
Hello world!

这次我们不需要指定程序的确切位置。

7. execve()

我们可以将环境变量传递给 execve()。此外,参数需要在以 NULL 结尾的向量内:

int execve(const char *pathname, char *const argv[], char *const envp[])

例如:

#include <unistd.h>
int main(void) {
    char *file = "/usr/bin/bash";
    char *const args[] = {"/usr/bin/bash", "-c", "echo Hello $ENV!", NULL};
    char *const env[] = {"ENV=World", NULL};
	
    execve(file, args, env);
    return 0;
}

让我们编译并运行:

$ gcc execve.c -o execve
$ ./execve
Hello World!

我们成功地将环境变量和参数传递给bash并将它们打印在屏幕上。