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

时间:2016-02-18 18:46:17

标签: fork exec

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

Differences between fork and exec

  

exec调用是一种基本上用新程序替换整个当前进程的方法。它将程序加载到当前进程空间并从入口点运行它。

它真的取代了整个程序吗?它不仅仅是执行子程序/函数调用,恰好体现了所选程序的colour吗? - 在返回自己的背景和操作之前?

所以不是更合适的描述,只是一个体现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

现在很明显我的理解存在缺陷。既然如我所说 以上是正确的,那么所有产生的过程都不应该只是实例 当我看到htop时bash或init?它们不是(它们都有自己的名字,例如ls或htop) 那么exec()实际上是否用一个新的程序替换了调用它的整个程序?所以喜欢调用exec() 隐含地杀死调用它的程序?这是怎么回事?

4 个答案:

答案 0 :(得分:6)

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

将新进程作为“子例程”执行的方法是先fork,然后让子进程执行exec,然后为子进程创建父进程wait终止。这就是在shell上键入命令时会发生的情况。这也是system库函数在幕后的作用。

答案 1 :(得分:3)

您的理解不正确。 exec函数系列完全取代了新进程的调用进程。实际上,如果exec函数返回,则在启动新进程时会发生错误。

新进程保留旧进程的进程ID以及任何打开的文件描述符。其他一切都被取代了。

与“调用”新程序相同。当新程序从main(或调用exit)返回时,该过程结束。它不会“返回”调用它的程序。

答案 2 :(得分:2)

它是否真的取代了整个程序?是的,确实如此。可以用自己替换整个程序,从而从头开始重新启动相同的程序(并部分地给你你想象的概念)。

它不仅仅是执行子程序/函数调用,恰好体现了所选程序的main()吗? - 在返回到自己的上下文和操作之前?否。当exec()函数系列完成它们的工作时,函数永远不会返回。任何返回值都表示失败。

fork()exec系列都是独立的操作,并且有充分理由独立存在。也就是说,它们经常一起使用,其中fork()创建了一个新流程:

  • 现在正在执行(有效地)从fork()语句的返回开始(实际上在内核中的某个地方,这导致两个进程在fork()语句内返回)
  • 其中一个从0返回fork(),而另一个返回新流程的进程ID
  • 其中一个,从fork()返回时键入,调用exec(),因为其目的只是为了在不停止第一个过程/程序的情况下生成新的进程/程序。

答案 3 :(得分:1)

  

它真的取代了整个程序吗?

  

它不仅仅是执行子程序/函数调用,恰好体现了所选程序的main()吗? - 在返回自己的背景和操作之前?

没有

  

所以不是更恰当的描述,只是一个体现main()的子程序? (例如,将选定的流程代码纳入当前的流程中?与完全开启&#34;替换它&#34;?

没有

  

现在很明显我的理解存在缺陷。因为如果我上面说的是正确的,那么当我查看htop时,所有产生的过程都不应该只是bash或init的实例吗?它们不是(它们都有自己的名字,例如ls或htop)

完全。

  

exec()实际上是否用一个新的程序替换了调用它的整个程序?

  

所以调用exec()会隐式杀死调用它的程序吗?

不完全。它用不同的程序替换程序,正是你所读取的程序,然后将程序加载到当前进程空间并从入口点运行它。

这是一个奇怪的问题。您已经准确地描述了所有内容,然后询问它是否真的以一种完全不同的方式表现出来。但你不能解释为什么你认为它以其他方式起作用。

是的,它按照你描述的方式工作,而不是你似乎已经弥补的方式。如果出于某种原因你认为描述不正确并且它实际上是以其他方式工作,那么你还没有告诉我们它是什么。