exec 进程替换
核心概念:exec 进程替换
本质:用新程序把当前进程的代码段、数据段、堆栈完全替换掉,执行新逻辑。
关键特性
进程号 PID 不变
父子关系不变
替换后原进程代码不再执行(exec 之后的代码不会运行)
作用:让子进程执行完全不同的程序,是实现shell 命令执行的底层机制。
exec 函数族(6 个)
统一头文件:#include <unistd.h>
| 函数名 | 特点 | 说明 |
|---|---|---|
| execl | 路径 + 列表 | 需写完整路径,参数列表结尾必须(char*)NULL |
| execlp | 文件名 + 列表 | 自动搜索 PATH,最常用 |
| execle | 路径 + 列表 + 环境变量 | 自定义环境变量 |
| execv | 路径 + 数组 | 参数用数组传递 |
| execvp | 文件名 + 数组 | 自动搜 PATH,参数用数组 |
| execvpe | 文件名 + 数组 + 环境变量 | 带自定义环境变量 |
记忆规则:
l:list 参数以列表形式给出
v:vector 参数以数组形式给出
p:path 自动按系统 PATH 查找程序
e:env 自定义环境变量
典型示例
execlp(最常用)
// 执行 ps -f -e printf("pid=%d\n", getpid()); execlp("ps", "ps", "-f", "-e", (char*)NULL); // 下面这行永远不会执行 printf("aaa\n");execv(数组传参)
char *arg[] = {"ps", "-f", "-e", NULL}; execv("/usr/bin/ps", arg);经典用法:fork + exec + wait
父进程(模拟 bash)循环等待输入
输入命令后fork 创建子进程
子进程用exec 替换执行命令
父进程wait 等待子进程结束,再继续循环
流程:
父进程循环 → 输入命令 → fork → 子进程exec → 父进程wait → 回到循环
配套常用函数
fflush(stdout)
立即刷新输出缓冲区,确保内容先打印到屏幕。
strtok
字符串分割,用于拆分命令与参数。
wait(NULL)
父进程阻塞,等待子进程退出,避免僵尸进程。
核心要点
exec 只替换进程内容,不创建新进程。
exec 成功后,原进程代码不再执行。
命令行终端的所有命令,底层都是
fork + exec + wait。
Mybash 实现(exec 综合应用)
核心思路
父进程不退出,循环接收命令 →fork()创建子进程 → 子进程exec替换执行命令 → 父进程wait()等待子进程退出。
常用系统函数
getpwuid():通过 UID 获取用户信息结构体
pw_name:用户名pw_uid:用户 IDpw_dir:家目录
getcwd(buf, size):获取当前工作目录gethostname(name, size):获取主机名chdir(路径):切换目录fflush(stdout):强制刷新输出缓冲区strtok():字符串分割(拆分命令与参数)