在以下链接中,以及许多其他类似链接,exec通常被描述为:
exec调用是一种基本上用新程序替换整个当前进程的方法.它将程序加载到当前进程空间并从入口点运行它.
它真的取代了整个程序吗?它不仅仅是执行一个恰好体现main()所选程序的子程序/函数调用吗? - 在返回自己的背景和操作之前?
所以不是更恰当的描述,只是一个体现的子程序main()?(例如,将所选择的流程代码纳入当前的流程中?与完全"替换它"相反?
# original taken from the provided link
+--------+
| pid=7 |
| ppid=4 |
| bash |
+--------+
|
| calls fork
V
+--------+ +--------+
| pid=7 | forks | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash | | bash |
+--------+ +--------+
| |
| waits for pid 22 | calls exec to run ls
| V
| +--------+
| | pid=22 |
| | ppid=7 |
| | ls |
V +--------+
+--------+ |
| pid=7 | | exits
| ppid=4 | <---------------+
| bash |
+--------+
|
| continues
V
Run Code Online (Sandbox Code Playgroud)
# wouldnt this technically be more accurate?
# or am I misunderstanding something with exec()?
+--------+
| pid=7 |
| ppid=4 |
| bash |
+--------+
|
| calls fork
V
+--------+ +--------+
| pid=7 | forks | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash | | bash |
+--------+ +--------+
| |
| waits for pid 22 | calls exec to run ls
| V
| +--------+
| | pid=22 |
| | ppid=7 |
| | bash |
| | ls() |
| +--------+
| |
| | ls completes
| | and the program context returns to bash's
| |
| +--------+
| | pid=22 |
| | ppid=7 |
| | bash |
| +--------+
| |
V |
+--------+ | the child branch of bash calls exit/return
| pid=7 | | that follows the exec statement in the
| ppid=4 | <---------------+ "if (fork() == 0) {...}" code branch
| bash |
+--------+
|
| continues
V
Run Code Online (Sandbox Code Playgroud)
现在显然我的理解存在缺陷.因为如果我上面说的是正确的,那么当我查看htop时,所有产生的过程都不应该只是bash或init的实例吗?它们不是(它们都有自己的名字,例如ls或htop)所以exec()实际上是用一个新的程序替换调用它的整个程序吗?所以像调用exec()隐式杀死调用它的程序?这里发生了什么?
exec 确实用新的程序替换当前的程序.该过程被完全覆盖.没有任何州可以返回.但是说exec"隐含地杀死 "调用它的过程也是不准确的.该过程继续执行; 它只是在运行一个不同的程序.它保留了旧的进程ID.
将新进程作为"子例程"执行的方法首先是fork,然后让子进程执行exec,然后让wait子进程终止父进程.这就是在shell上键入命令时会发生的情况.这也是system图书馆功能在幕后的作用.