一.exev函数族
1.1功能
exec()
函数族的主要功能是在当前进程中运行一个新的程序。使用这些函数可以实现以下功能:
-
程序替换(Program Replacement):调用
exec()
函数后,当前进程的代码和数据会被新程序的代码和数据替换。这可以用于动态加载和替换程序,使得一个进程可以切换到运行不同的程序,实现灵活的程序执行。 -
命令行参数传递:
exec()
函数族提供了不同的方式传递命令行参数给新程序。可以使用列表或数组形式将参数传递给新程序。同时,还可以在某些函数中使用可 参数。 -
环境变量传递:部分
exec()
函数族提供了传递环境变量的功能。可以通过字符串数组形式设置新程序的环境变量。 -
程序搜索和执行:一些
exec()
函数(如execvp()
和execlp()
)会自动搜索可执行文件的路径,无需指定完整路径。它们会根据环境变量PATH
中指定的路径,搜索并执行指定的程序。 -
进程间传递状态信息:通过执行新程序,可以将一些状态信息以特定的方式传递给新程序。这样可以在进程间共享数据和状态,并实现进程间的通信。
需要注意的是,exec()
函数族在成功执行后,不会返回到原来的程序。新程序的代码开始执行,原来的进程被完全替换。因此,通常在exec()
函数调用后紧跟exit()
函数,以确保原来的程序在替换后退出。
1.2函数原型
exec()
函数族的函数原型如下:
-
int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
path
:要执行的可执行文件的路径。arg0
:可执行文件的名称,作为参数传递给新程序。- 可变参数:新程序的命令行参数,以空指针
(char *)0
结尾。
-
int execv(const char *path, char *const argv[]);
path
:要执行的可执行文件的路径。argv
:新程序的命令行参数,以字符串数组形式传递,其中第一个字符串是可执行文件的名称。
-
int execle(const char *path, const char *arg0, ... /*, (char *)0, char *const envp[] */);
path
:要执行的可执行文件的路径。arg0
:可执行文件的名称,作为参数传递给新程序。- 可变参数:新程序的命令行参数,以空指针
(char *)0
结尾。 envp
:新程序的环境变量,以字符串数组形式传递。
-
int execvp(const char *file, char *const argv[]);
file
:要执行的可执行文件的名称,不包含路径。argv
:新程序的命令行参数,以字符串数组形式传递,其中第一个字符串是可执行文件的名称。
-
int execve(const char *file, char *const argv[], char *const envp[]);
file
:要执行的可执行文件的路径。argv
:新程序的命令行参数,以字符串数组形式传递。envp
:新程序的环境变量,以字符串数组形式传递。
这些函数返回值为-1表示执行出错。成功执行exec()
函数后,当前进程的代码和数据将被新程序的代码和数据替换,并开始执行新程序。
1.3后缀含义
exec()
函数族有一些不同的后缀,用于表示不同的功能和参数形式。下面是一些常见的后缀:
-
l
:表示使用列表(list)形式的参数。接收一系列用空格分隔的命令行参数作为参数传递给新程序。 -
v
:表示使用数组(vector)形式的参数。接收一个字符串数组作为参数传递给新程序,其中包含程序名称和命令行参数。 -
p
:表示通过路径(path)搜索程序。会根据环境变量PATH
中指定的路径搜索并执行指定的程序。 -
e
:表示接收环境变量(environment)参数。可以指定新程序运行时的环境变量,以字符串数组形式传递。 -
x
:表示接收完整的参数列表。除了接收程序路径和命令行参数外,还可以指定新程序运行时的环境变量。
这些后缀可以结合使用,来达到所需的功能和参数形式。例如,execlp()
函数接收一个程序名称和一系列的命令行参数,并会在PATH
环境变量指定的路径中搜索该程序进行执行。
需要注意的是,exec()
函数族中并没有具有无后缀的exec()
函数,因为这样的函数原则上无法确定参数列表的长度。所以,我们需要使用带有具体后缀的函数来适应不同的参数形式和需求。
1.4函数案例
execl:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("This is the original program\n");
// 使用execl函数族调用ls命令
execl("/bin/ls", "ls", "-l", NULL);
printf("This line will not be executed\n");
return 0;
}
execlp:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("This is the original program\n");
// 使用execl函数族调用ls命令
execlp("ls", "ls", "-l", NULL);
printf("This line will not be executed\n");
return 0;
}
execv:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("This is the original program\n");
char *buf[]={ "ls", "-l", NULL};
// 使用execl函数族调用ls命令
execv("/bin/ls",buf);
printf("This line will not be executed\n");
return 0;
}
exeve
#include <stdio.h>
#include <unistd.h>
int main() {
char *args[] = { "/path/to/my_executable", "arg1", "arg2", NULL };
char *env[] = { "ENV_VAR1=value1", "ENV_VAR2=value2", NULL };
printf("This is the original program\n");
// 使用execve函数族执行自定义可执行文件,并传递环境变量
execve("/path/to/my_executable", args, env);
printf("This line will not be executed\n");
return 0;
}