exec 程序分析
概要:通过一个调用 exec 的示例程序,分析 exec 系统调用的使用方法与流程:exec 用新程序替换当前进程的内存与寄存器,失败时才会返回。
1 程序结构分析
代码如下:
// exec.c: replace a process with an executable file
#include "kernel/types.h"
#include "user/user.h"
int
main()
{
char *argv[] = { "echo", "this", "is", "echo", 0 };
exec("echo", argv);
printf("exec failed!\n");
exit(0);
}
演示
exec()如何用一个新的可执行文件替换当前进程的内存映像。
也就是说:
- 不是创建新进程(那是
fork) - 而是把“当前进程”变成另一个程序
1.1 构造参数数组
char *argv[] = { "echo", "this", "is", "echo", 0 };
这是传给 exec() 的参数数组。
非常重要:
在 UNIX 系统中:
argv[0] = 程序名
argv[1...] = 参数
argv 最后必须是 0 (NULL)
1.2 exec调用
exec("echo", argv);
它的作用是:
用 echo 这个可执行文件替换当前进程
发生了什么?
- 当前进程的代码段被销毁
- 数据段被销毁
- 栈被销毁
- 加载 echo 程序
- 把 argv 传给新程序
- 从 echo 的 main() 开始执行
⚠️ 注意:
- exec 成功时 不会返回
- 只有失败才会继续往下执行
1.3 失败处理
printf("exec failed!\n");
如果看到这句话,说明:
- echo 没找到
- 或加载失败
2 执行流程图
main()
↓
构造 argv
↓
exec("echo", argv)
↓
[内核加载 echo]
↓
当前进程变成 echo
↓
echo main()
↓
打印:
this is echo
3 理解进程替换机制
很多人误以为:
exec 是创建新进程
其实真正流程是:
fork() → 创建子进程
exec() → 子进程变成另一个程序
shell 的运行机制:
父进程(shell)
|
└── fork()
|
└── 子进程
|
└── exec(ls)
留下评论