进程分叉时会复制其虚拟内存或常驻内存吗?


12

在Linux中制作新进程的标准方法是复制父进程的内存占用空间,并成为子进程的环境,直到execv被调用为止。

我们在谈论什么内存占用量,虚拟的(所需的过程)还是常驻的(实际使用的)?

动机:我的设备的交换空间有限,而应用程序在虚拟内存和驻留内存之间的差异却很大。由于内存不足,该应用程序无法派生,并希望查看尝试减小虚拟足迹大小是否有帮助。

Answers:


12

在现代系统中,仅因为使用了fork系统调用而实际上没有复制任何内存。页面表中所有标记为只读,以便在首次尝试将陷阱写入内核代码时发生。只有在第一次尝试写入时,复制才会发生。

这称为写时复制。

但是,也可能需要跟踪已提交的地址空间。如果内核必须复制页面时没有可用的内存或交换空间,则它必须终止某些进程以释放内存。这并非总是可取的,因此可以跟踪内核已承诺的内存量。

如果内核承诺的内存量超过可用内存+交换量,则在尝试调用fork时会给出错误代码。如果有足够的可用空间,则在分叉之后,内核将为两个进程承诺父进程的完整虚拟大小。


1
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.是的,谢谢。这意味着在内存(RAM和交换空间)有限的环境中减少进程的虚拟足迹可以解决无法分叉的问题。
TheMeaningfulEngineer

1
@Alan是的。如果fork失败,则显示一条错误消息,指示内存不足。然后,在分叉之前减少进程的虚拟内存使用量可能会有所帮助。
kasperd

5

不用担心,它会生成一个懒惰的副本(写时复制)。最初,两个进程的虚拟内存地址都指向相同的页面,但是当分叉的进程试图对其进行修改时,它实际上是对页面进行物理复制(此后,该页面位于RAM中的两个位置)。

当心,没有报告的内存占用实际告诉您该进程正在使用多少RAM。由于虚拟内存的交换,内存共享和其他问题,无法确定。内存空间的某些部分是共享库(在何处进行计数?),某些部分指的是非RAM存储器(其他硬件设备),一些当前已换出,某些尚未复制(写时复制),以及以此类推。读这个:

https://lwn.net/Articles/642202/


5

有内核设置

/ proc / sys / vm / overcommit_memory

优秀文章的引文:

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

这适用于派生以及常规malloc。即,如果将其设置为0,则会在写入时复制fork。写时复制意味着一旦应用程序分支,它的两个副本将共享使用子级或原始版本开始更改内存的内存页面。

在大多数发行版中,我知道过量使用为0。但是,如果将其设置为2,则所有内存页面将完全由实际内存支持,在某些情况下,在高内存压力下会更稳定,但是有些程序(我面对gitk)依赖过量使用将失败。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.