Linux fork函数与Windows的CreateProcess相比 - 什么被复制?

时间:2014-02-12 15:42:53

标签: c++ c linux fork

我正在将Windows应用程序移植到Linux。我在Windows上使用CreateProcess来运行子进程并重定向所有标准流(in,out,error)。流重定向很关键,主进程将数据发送给子进程并接收他们的输出和错误消息。主进程非常大,具有大量内存和线程,子进程是小进程。在Linux上,我看到fork函数在Windows上具有与CreateProcess类似的功能。但是,手动说fork“创建父进程副本”,包括代码,数据和堆栈。这是否意味着如果我创建一个使用1 GB内存的巨大进程的副本只是为了运行一个使用1 MB内存的非常简单的命令行工具,我将需要与{{1}重复1 GB的内存,然后用1 MB进程替换此1 GB?那么,如果我有100个线程,它将需要100 GB的内存来运行100个需要100 MB内存才能运行的进程?另外,父进程中其他线程“不知道”关于fork执行,他们会做什么? fork函数的作用是什么?“它是从巨大的父母创建大量小子进程的真正有效方法吗?

5 个答案:

答案 0 :(得分:8)

当您致电fork()时,最初只会复制您的VM,并且所有页面都会被标记为copy-on write。您的新子进程将具有父进程VM的逻辑副本,但在您实际开始写入之前它不会消耗任何额外的RAM。

对于线程,fork在子进程中只创建一个类似于调用线程副本的新线程。

此外,只要您调用任何exec系列调用(我假设您想要),您的整个过程映像就会被替换为新映像,并且只保留文件描述符。

如果您的父进程有很多打开的文件描述符,那么我建议您浏览/proc/self/fd并关闭您不需要的子进程中的所有文件描述符。

答案 1 :(得分:3)

fork基本上将您的进程拆分为两个,父进程和子进程在fork函数调用之后继续执行指令。但是,子进程中的返回值为0,而在父进程中,它是子进程的进程ID。

子进程的创建非常快,因为它使用与父进程相同的页面。页面标记为写入时复制(COW),因此,如果任一进程更改页面,则另一个不会受到影响。一旦子进程存在,它通常会调用其中一个exec函数来替换自己的图像。 Windows与fork没有等效,而CreateProcess调用只允许您启动新流程。

fork有一个名为clone的替代方案,可以让您更好地控制新流程启动时会发生什么。例如,您可以指定要在新流程中调用的函数。

答案 2 :(得分:2)

副本是“copy-on-write”,因此如果您的子进程不修改数据,它将不会使用除父进程之外的任何内存。通常,在fork()之后,子进程使exec()用另一个进程替换此进程的程序,然后无论如何都会丢弃所有内存。

答案 3 :(得分:1)

我没有使用CreateProcess,但fork()并不是该过程的精确副本。它创建了一个子进程,但是子进程在父进程名为fork相同指令处开始执行,并从那里继续执行。

我建议您查看Chapter 5操作系统手册的Three Easy Pieces。这可能会让你开始,你可能会找到你正在寻找的孩子产卵电话。

答案 4 :(得分:1)

分叉的子进程已经几乎复制了所有父工具:内存,描述符,文本等。唯一的例外是父代的线程,它们不会被复制。