Answers:
在现代系统中,仅因为使用了fork系统调用而实际上没有复制任何内存。页面表中所有标记为只读,以便在首次尝试将陷阱写入内核代码时发生。只有在第一次尝试写入时,复制才会发生。
这称为写时复制。
但是,也可能需要跟踪已提交的地址空间。如果内核必须复制页面时没有可用的内存或交换空间,则它必须终止某些进程以释放内存。这并非总是可取的,因此可以跟踪内核已承诺的内存量。
如果内核承诺的内存量超过可用内存+交换量,则在尝试调用fork时会给出错误代码。如果有足够的可用空间,则在分叉之后,内核将为两个进程承诺父进程的完整虚拟大小。
fork
失败,则显示一条错误消息,指示内存不足。然后,在分叉之前减少进程的虚拟内存使用量可能会有所帮助。
不用担心,它会生成一个懒惰的副本(写时复制)。最初,两个进程的虚拟内存地址都指向相同的页面,但是当分叉的进程试图对其进行修改时,它实际上是对页面进行物理复制(此后,该页面位于RAM中的两个位置)。
当心,没有报告的内存占用实际告诉您该进程正在使用多少RAM。由于虚拟内存的交换,内存共享和其他问题,无法确定。内存空间的某些部分是共享库(在何处进行计数?),某些部分指的是非RAM存储器(其他硬件设备),一些当前已换出,某些尚未复制(写时复制),以及以此类推。读这个:
有内核设置
/ 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)依赖过量使用将失败。
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.
是的,谢谢。这意味着在内存(RAM和交换空间)有限的环境中减少进程的虚拟足迹可以解决无法分叉的问题。