根据名为“ UNIX环境中的高级编程”的书,在我们调用fork()
之后,子进程调用exec()
来运行新进程。 exec()
将使用新流程来替换旧流程,而新流程将从main()
开始。
但是我们都知道,当我们调用fork()
时,父进程和子进程都从fork()
函数开始。那么,我们如何理解这本书的观点呢?
答案 0 :(得分:2)
也许他们对这本书的措词有些困惑:
•我们调用fork创建一个新进程,它是调用方的副本。 我们说呼叫者是父母,而新创建的 过程是孩子。然后fork返回的非负进程ID 将新的子进程返回给父进程,并向子进程返回0。 因为fork创建了一个新流程,所以我们称它被调用一次- 父级-但在父级和子级中返回两次。
•在子级中,我们调用execlp执行已读取的命令 从标准输入。这将子进程替换为新的 程序文件。后面跟exec的fork的组合称为 在某些操作系统上产生新进程。在UNIX系统中, 这两个部分分为各自的功能。我们会说很多 有关这些功能的更多信息,请参见第8章。
在成功的fork()
通话中,我们返回两次。一次作为父级过程,再次作为子级。
调用exec()
将更改进程正在运行的程序。通常在调用fork()
之后将其与子进程配对,但这是完全可选的。
为简单起见,fork()
创建(重复)流程,而exec()
更改我们的流程。
答案 1 :(得分:0)
我想这也可以解决问题:可能会有一些混乱。 fork()带来了新的过程。 exec()替换正在运行的程序...但不创建或启动新进程。我怀疑过程一词可能会被宽松地使用吗?您也可以参考execve(2)
手册页以获得更清晰的术语和说明:
execve()
执行filename
指向的程序。这将导致调用程序当前正在运行的程序被新程序替换,并具有新初始化的堆栈,堆和(初始化和未初始化的)数据段。
答案 2 :(得分:0)
fork()
通过复制调用过程来创建子过程。调用fork()
的进程是父进程,而新创建的进程是子进程。因此,fork()
将一个进程一分为二,并将0
返回到子进程,并将子进程的PID
返回到父进程,如果返回失败,则返回-1
子进程和父进程在单独的内存空间中运行。在fork()
时,两个存储空间的内容相同。
当您从进程中调用exec()
时,它将在现有进程的上下文中运行可执行文件,从而替换先前的可执行文件。新程序被加载到相同的进程地址空间中。当前流程只是变成了新流程,因此PID
未被更改,这是因为我们不创建新流程,而只是在exec中用另一个流程替换了一个流程
有一个称为写时复制的概念,知道它的知识很好-
写时复制是一种优化,其中设置了页表,以便父进程和子进程开始共享所有相同的内存,并且仅在需要时才复制两个进程写入的页面。
如果该进程未修改任何内存,而是立即执行一个新进程,请完全替换地址空间。因此,在派生期间复制进程的所有内存是浪费的,而使用写时复制技术。