exec()混乱,更像是替换或子程序?

Ala*_*ACK 0 fork exec

在以下链接中,以及许多其他类似链接,exec通常被描述为:

fork和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()隐式杀死调用它的程序?这里发生了什么?

Bri*_*ian 6

exec 确实用新的程序替换当前的程序.该过程被完全覆盖.没有任何州可以返回.但是说exec"隐含地杀死 "调用它的过程也是不准确的.该过程继续执行; 它只是在运行一个不同的程序.它保留了旧的进程ID.

将新进程作为"子例程"执行的方法首先是fork,然后让子进程执行exec,然后让wait子进程终止父进程.这就是在shell上键入命令时会发生的情况.这也是system图书馆功能在幕后的作用.