目录
1. 引言
2. 替换原理
3. exec 函数族概览
4. 函数命名规律
5. 函数示例
6. 返回值特性
7. exec 与 fork 的经典配合
8. 补充:exec 与文件描述符
9. 总结
1. 引言
fork创建的子进程通常需要执行一个新程序,而不是继续父进程的逻辑。程序替换通过exec函数族实现:将新程序加载到当前进程的地址空间,并从头执行。本文将详解六大exec函数的使用与区别。
2. 替换原理
调用
exec后,当前进程的用户空间代码和数据被新程序完全替换;从新程序的
_start或main开始执行;不创建新进程,进程PID保持不变。
3.exec函数族概览
c
#include <unistd.h> int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char *const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execve(const char *path, char *const argv[], char *const envp[]);
4. 函数命名规律
| 后缀 | 含义 | 说明 |
|---|---|---|
l | list | 参数以列表形式传递,如execl("/bin/ls", "ls", "-l", NULL) |
v | vector | 参数以指针数组传递 |
p | path | 自动搜索环境变量PATH,无需写全路径 |
e | env | 可自定义环境变量数组,不继承当前环境 |
execve是真正的系统调用,其他函数都是对其的封装(位于man 3节)。
5. 函数示例
c
// 需要使用全路径 execl("/bin/ls", "ls", "-l", NULL); // 自动搜索 PATH execlp("ls", "ls", "-l", NULL); // 自定义环境变量 char *envp[] = {"PATH=/bin", "HOME=/root", NULL}; execle("/bin/ls", "ls", "-l", NULL, envp); // 使用参数数组 char *argv[] = {"ls", "-l", NULL}; execv("/bin/ls", argv); execvp("ls", argv); execve("/bin/ls", argv, envp);6. 返回值特性
成功:不返回;
失败:返回 -1;
因此通常写法为
execl(...); perror("exec"); exit(1);。
7.exec与fork的经典配合
c
pid_t pid = fork(); if (pid == 0) { // 子进程 execlp("ls", "ls", "-l", NULL); exit(1); // 只有 exec 失败才会执行 } else { wait(NULL); }8. 补充:exec与文件描述符
默认情况下,exec会保留当前进程打开的文件描述符(除非设置了FD_CLOEXEC标志)。这使得父子进程间的文件重定向(如Shell的>和>>)成为可能。
9. 总结
掌握
l/v、p/ 非p、e/ 非e的区别;只有
execve是系统调用,其他是库函数;与
fork配合是Linux下运行新程序的标准模式。