假设我们使用的是 32 位 Linux 操作系统,具有 4GB 物理内存。
没有交换分区!
有一个内核,保留了 200MB 的不可分页内存,其他任何人都无法获取(这整个声明只是我的假设,您可以更正该值或声明内核不这样做)。
在时间 t₀,有 3 个进程
p1
、p2
和 p3
消耗 1GB 物理内存。
现在第四个进程开始,其中
mmap(2)
是4GB内存,MAP_PRIVATE
是一个空文件,PROT_WRITE
!此过程启动一个 for
循环,向该 mmap
数组的每个元素写入一些值;像这样:
for(int i=0; i<4GB; i++)
mmap_array[i] = i*i%255;
p4
写入数据达到2.8GB,要求写入下一个字节时,内核是否停止其他3个进程,创建它们的映像,并且由于没有交换,将它们存储回RAM;这又消耗了 1GB 物理内存(因为它们运行时有 1GB RAM,所以图像大小相同)?p4
请求数组的下一个元素时,内核是否会卸载第一个页面,然后加载新页面而不是卸载的页面?MAP_SHARED
怎么办?卸载的页面的值会通过备份文件携带,然后释放物理空间吗?p4
这样的进程这样做时(或者 RAM 达到 100% 的其他情况),为什么系统会挂起?是不是因为需要额外的空间来恢复那些p1
、p2
和p3
的图像?或者那些会在那 1GB 中恢复,但一旦他们要求更多内存,他们就会冻结?MAP_SHARED
不能或者它们充当 #5 吗?继续但很慢(当时只有一页 RAM)?SysRq
仍然有效;这是否意味着每个进程都会挂起,但由于内核保留了内存,所以不会挂起?所有这些问题都集中在一篇文章中的原因是通过理解所有这些,我能够理解实际的问题,也就是我在标题中写的问题!
我只是对我想要得到答案的事情进行了编号,以避免对人们写的答案发表评论。
让我向您介绍“Linux 内存不足 (OOM) 杀手”https://rakeshjain-devops.medium.com/linux-out-of-memory-killer-31e477a45759
基本上Linux内核确实为每个进程维护了一个“可牺牲性”分数,如果遇到无法完成内存分配的情况,它会按照分数的顺序牺牲进程,以腾出空间。
如果push到了紧要关头,尝试进行mmap写入的进程将无法完成,因为无论内核如何努力尝试腾出空间,最终该进程都会引发SIGBUS(总线错误,内存访问错误)信号。