调用fork()之后,子进程从哪里开始?

时间:2018-07-05 01:22:17

标签: c unix fork exec

根据名为“ UNIX环境中的高级编程”的书,在我们调用fork()之后,子进程调用exec()来运行新进程。 exec()将使用新流程来替换旧流程,而新流程将从main()开始。 但是我们都知道,当我们调用fork()时,父进程和子进程都从fork()函数开始。那么,我们如何理解这本书的观点呢?

3 个答案:

答案 0 :(得分:2)

也许他们对这本书的措词有些困惑:

  

•我们调用fork创建一个新进程,它是调用方的副本。   我们说呼叫者是父母,而新创建的   过程是孩子。然后fork返回的非负进程ID   将新的子进程返回给父进程,并向子进程返回0。   因为fork创建了一个新流程,所以我们称它被调用一次-   父级-但在父级和子级中返回两次。

     

•在子级中,我们调用execlp执行已读取的命令   从标准输入。这将子进程替换为新的   程序文件。后面跟exec的fork的组合称为   在某些操作系统上产生新进程。在UNIX系统中,   这两个部分分为各自的功能。我们会说很多   有关这些功能的更多信息,请参见第8章。

在成功的fork()通话中,我们返回两次。一次作为父级过程,再次作为子级

调用exec()将更改进程正在运行的程序。通常在调用fork()之后将其与子进程配对,但这是完全可选的。

为简单起见,fork()创建(重复)流程,而exec()更改我们的流程。

fork(2) man page

exec(3) man page

答案 1 :(得分:0)

我想这也可以解决问题:可能会有一些混乱。 fork()带来了新的过程。 exec()替换正在运行的程序...但不创建或启动新进程。我怀疑过程一词可能会被宽松地使用吗?您也可以参考execve(2)手册页以获得更清晰的术语和说明:

  

execve()执行filename指向的程序。这将导致调用程序当前正在运行的程序被新程序替换,并具有新初始化的堆栈,堆和(初始化和未初始化的)数据段。

答案 2 :(得分:0)

fork()通过复制调用过程来创建子过程。调用fork()的进程是父进程,而新创建的进程是子进程。因此,fork()将一个进程一分为二,并将0返回到子进程,并将子进程的PID返回到父进程,如果返回失败,则返回-1

子进程和父进程在单独的内存空间中运行。在fork()时,两个存储空间的内容相同。

当您从进程中调用exec()时,它将在现有进程的上下文中运行可执行文件,从而替换先前的可执行文件。新程序被加载到相同的进程地址空间中。当前流程只是变成了新流程,因此PID未被更改,这是因为我们不创建新流程,而只是在exec中用另一个流程替换了一个流程

有一个称为写时复制的概念,知道它的知识很好-

  

写时复制是一种优化,其中设置了页表,以便父进程和子进程开始共享所有相同的内存,并且仅在需要时才复制两个进程写入的页面。

如果该进程未修改任何内存,而是立即执行一个新进程,请完全替换地址空间。因此,在派生期间复制进程的所有内存是浪费的,而使用写时复制技术。