当进程派生时,它的虚拟内存或常驻内存是否被复制?

The*_*eer 12 linux memory fork linux-kernel

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

我们在谈论什么内存占用,虚拟的(进程请求的)还是常驻的(实际使用的)?

动机:我有一个交换空间有限的设备和一个虚拟内存占用和常驻内存占用差异很大的应用程序。由于内存不足,应用程序无法分叉,并想看看尝试减少虚拟占用空间是否会有所帮助。

kas*_*erd 12

在现代系统中,实际上没有任何内存会因为使用了 fork 系统调用而被复制。它在页表中都被标记为只读,这样在第一次尝试将陷阱写入内核代码时就会发生。只有在第一个进程尝试写入时才会发生复制。

这称为写时复制。

然而,也可能需要跟踪已提交的地址空间。如果在内核必须复制页面时没有可用的内存或交换,它必须杀死一些进程以释放内存。这并不总是可取的,因此可以跟踪内核已提交多少内存。

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


ori*_*ion 5

别担心,它会生成一个懒惰的副本(写时复制)。两个进程的虚拟内存地址最初都指向相同的页面,但是当分叉进程尝试修改它时,它实际上制作了页面的物理副本(从那时起,该页面驻留在您的 RAM 中的两个位置)。

请注意,报告的内存占用量实际上都没有告诉您进程使用了​​多少 RAM。由于虚拟内存的交换、内存共享和其他问题,无法确定。内存空间的某些部分是共享库(在哪里计算?),有些是指非 RAM 内存(其他硬件设备),有些是当前换出的,有些尚未复制(写时复制)和很快。读这个:

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


gen*_*a2x 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.)
Run Code Online (Sandbox Code Playgroud)

这适用于 fork 以及常规 malloc。即如果您将其设置为 0,fork 将在写入时复制。写入时复制意味着一旦应用程序分叉,它的两个副本将共享内存页面 util child 或 original 开始更改内存。

在我知道的大多数发行版中,overcommit 是 0。但是如果你将它设置为 2,所有内存页面都将完全由真实内存支持,并且在某些情况下在高内存压力下会更稳定,但是一些依赖于过度使用将失败。