exec
系列函数用于替换当前进程的用户空间代码和数据,从而执行一个新的程序。调用 exec
系列函数不会创建新的进程,但会用新程序的代码和数据替换当前进程,因此调用 exec
后,进程的 ID 保持不变,但进程的行为变为执行新的程序
exec
系列函数有六个,分别是:
execl
int execl(const char *path, const char *arg, ...);
功能:使用指定的路径名执行新程序,参数一个一个列出,最后一个参数必须为 NULL
以标记结束。
execv
int execv(const char *path, char *const argv[]);
功能:使用指定的路径名执行新程序,参数以数组的形式传递。
execle
int execle(const char *path, const char *arg, ..., char *const envp[]);
功能:与 execl
类似,但可以传递环境变量数组 envp
。
execve
int execve(const char *path, char *const argv[], char *const envp[]);
功能:与 execv
类似,但可以传递环境变量数组 envp
。execve
是真正的系统调用。
execlp
int execlp(const char *file, const char *arg, ...);
功能:与 execl
类似,但使用文件名 file
作为参数,当文件名中不含 /
时,会根据 PATH
环境变量寻找可执行文件。
execvp
int execvp(const char *file, char *const argv[]);
功能:与 execv
类似,但使用文件名 file
作为参数,当文件名中不含 /
时,会根据 PATH
环境变量寻找可执行文件。
函数参数解析
路径名 vs. 文件名
使用路径名的函数(如 execl
, execv
, execle
, execve
)需要明确指定可执行文件的完整路径。
使用文件名的函数(如 execlp
, execvp
)会根据 PATH
环境变量查找可执行文件。
参数表传递
l
表示 list:参数需要一个一个列出。
v
表示 vector:参数以数组形式传递。
环境变量
e
结尾的函数(如 execle
, execve
)可以传递一个环境变量数组。
没有 e
结尾的函数则继承父进程的环境变量。
代码示例
char *const ps_argv[] = {"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
// 使用不同的 exec 函数执行 ps 命令
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execv("/bin/ps", ps_argv);
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
execve("/bin/ps", ps_argv, ps_envp);
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execvp("ps", ps_argv);
ps_argv[]
:
这是一个参数数组,传递给 ps
命令,用于指定显示进程信息的格式。
"ps"
是命令名。
"-o"
是选项,用于指定自定义输出格式。
"pid,ppid,pgrp,session,tpgid,comm"
指定了输出的字段(进程ID、父进程ID、进程组ID、会话ID、控制终端的进程组ID、命令名)。
NULL
是数组的结束标志。
ps_envp[]
:
这是一个环境变量数组,传递给 ps
命令。
"PATH=/bin:/usr/bin"
指定了查找可执行文件的路径。
"TERM=console"
设置终端类型为 console
。
NULL
是数组的结束标志
execl
- 使用绝对路径
/bin/ps
执行ps
命令。 - 参数依次为
"ps"
,"-o"
,"pid,ppid,pgrp,session,tpgid,comm"
,最后NULL
结束。 - 适用于知道完整路径并手动列出所有参数的情况。
execv
- 使用绝对路径
/bin/ps
执行ps
命令。 - 参数通过数组
ps_argv[]
传递。 - 适用于需要动态构建参数列表的情况。
execle
- 与
execl
类似,但额外传递了环境变量数组ps_envp[]
。 - 适用于需要在新程序中设置特定环境变量的情况。
execve
- 与
execv
类似,但额外传递了环境变量数组ps_envp[]
。 - 这是底层的系统调用函数,通常其他
exec
函数也是调用它实现的。
execlp
- 与
execl
类似,但只提供文件名"ps"
而非路径。 - 系统会根据
PATH
环境变量来查找ps
的可执行文件位置。 - 适用于不想指定绝对路径、依赖系统自动查找的情况。
execvp
- 与
execv
类似,但只提供文件名"ps"
而非路径。 - 系统会根据
PATH
环境变量来查找ps
的可执行文件位置。
代码执行效果
在每种
exec
函数调用成功后,当前进程的用户空间代码和数据将被新的ps
程序替换,进程会从ps
程序的启动例程开始执行。如果
exec
调用失败,函数会返回-1
并设置errno
以指示错误原因。因为
exec
系列函数不会创建新进程,所以进程 ID 不会变化。