Linux 进程替换详解:从 fork 到 exec 的完整链路
什么是进程替换?
简单来说,进程替换就是一个正在运行的进程,用一个全新的可执行程序,完全替换掉自己当前的代码、数据和堆栈,但进程的 PID 保持不变。
就像你正在用记事本,然后直接把它变成了一个浏览器 —— 窗口(PID)没变,但里面的程序已经完全换了。我们先看一个简单的演示,直观感受一下效果。
#include <iostream>
#include <unistd.h>
using namespace std;
int main() {
cout << "before: I am process, Mypid: " << getpid()
<< " Myppid: " << getppid() << endl;
// 调用 execl 执行 ls -l -a
execl("/usr/bin/ls", "ls", "-l", "-a", NULL);
// 如果 execl 执行成功,下面的代码永远不会执行
cout << "after: I am process, Mypid: " << getpid()
<< " Myppid: " << getppid() << endl;
return 0;
}
运行结果会显示 ls 的输出,而 cout << "after..." 那行永远不会打印。这就是进程替换的核心特征:一旦成功,原进程流终止。
核心原理
1. 会发生写时拷贝(COW)吗?
很多人容易混淆 fork 和 exec 对内存的影响。
- COW 的触发前提:只有
fork()创建子进程后,父子进程共享内存页,且某一方对共享页执行写入操作时,才会触发 COW。 - exec 的本质:它会直接丢弃当前进程的代码段、数据段等所有用户空间内容,重新加载新程序。这相当于销毁了原有的地址空间映射,不再与任何进程共享内存页。
- 结论:
exec替换不会触发写时拷贝。无论是子进程还是父进程直接调用,都不会因为exec本身产生 COW 行为。


