父进程和子进程有相同的堆栈

时间:2011-08-17 18:04:56

标签: unix fork

http://www.steve.org.uk/Reference/Unix/faq_2.html

根据上面的链接,子进程从父进程获取堆栈,内存等的副本。那是对的吗?

3 个答案:

答案 0 :(得分:4)

您的链接是对的。内存不是由进程共享的,只是由同一进程中的线程共享(即使这样,线程也有自己的堆栈)。

但是,在现代Unices中,所涉及的内存页通常是copy-on-write:只有在此进程(或其父进程)修改其中一个页面时,才会在子进程的地址空间中创建副本。

因此,即使父母占用大量空间,儿童进程的实际内存占用量仍然很低。

答案 1 :(得分:2)

在程序调用fork()之后,新创建的子进程是相同的(堆,堆栈甚至文件句柄)。这是Unix工作原理的基本部分;这是shell启动的程序如何写入与shell相同的终端。该程序不知道它在哪个xterm中运行;它只是从其父进程继承其stdin和stdout文件句柄。

对于内存,这看起来有点浪费,因为fork()通常后跟exec()来运行一个新程序(再次,如在shell中)。但是,如果子程序无法访问fork()之前的数据,那么子程序如何知道exec()的哪个程序?

此外,fork()早于线程,甚至比select()更多基本形式的多处理。在过去的日子里(如果你有足够的内存),编写一个程序来分叉()编写几个孩子来执行I / O繁重的任务是一种常见的设计。如果一个子进程暂时挂起做I / O,其他进程仍然可以继续运行。 Apache Web服务器在版本1.x中的工作方式与此类似。

就“复制”的机制如何工作而言,这取决于系统。一些(较旧的)系统实现这是一个完整的副本,但大多数(较新的)系统实现它作为写时复制。也就是说,在fork()时,父和子共享完全相同的内存页。当父或子更改内存的内容时,更改的任何人都会获得更改的内存的私有副本(更改不会被共享);另一个过程为自己保留“旧”副本。如果只读取它们,则不使用额外的内存。

写时复制机制对程序完全透明。虚拟内存子系统完成了幕后的所有工作;甚至内存地址也不会改变。

答案 2 :(得分:0)

从您链接的文章:

  

这样做的帮助就是知道孩子遗传的是什么和不遗传。 [...]请注意,孩子会获得副本这些内容,不是真实的

     
      
  • [...]
  •   
  •   
  • [...]
  •   

我对它有点模糊,但我认为进程得到了自己的记忆内容;这就是它们与共享所有内容的线程的不同之处。

来自the Wikipedia article on Threads

  

多个线程可以存在于同一个进程中并共享内存等资源,而不同的进程不共享这些资源。