You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

mmap()与虚拟内存结合时的内存拆分机制解析

前提条件

  • 运行在32位Linux操作系统,拥有4GB物理内存
  • 无交换分区
  • 内核预留200MB不可分页内存,无法被普通进程占用(注:实际Linux内核会预留部分内存供自身紧急使用,具体数值因配置而异)
  • 时间点t₀时,存在p1、p2、p3三个进程,共占用1GB物理内存
  • 启动进程p4:通过mmap(2)以MAP_PRIVATE方式映射一个空文件的4GB内存,设置PROT_WRITE权限;随后启动循环向映射数组的每个元素写入数据:
for(int i=0; i<4GB; i++)
    mmap_array[i] = i*i%255;

问题与解答

  1. 当p4已写入2.8GB数据,请求写入下一字节时,内核是否会暂停其他3个进程,生成它们的镜像,且因无交换分区而将镜像存回RAM?这又会占用1GB物理内存(因为它们运行时占用1GB RAM,镜像大小相同)?
    不会。内核的内存管理是以页为单位的,根本不会生成所谓的"进程镜像"。当内存不足时,内核会触发页回收机制,优先挑选可回收的页面(比如很久未访问的文件缓存页)释放空间;但因为没有交换分区,进程的匿名页(堆、栈、MAP_PRIVATE已修改页)无法被换出,此时内核要么继续回收可释放的页面,要么直接触发OOM Killer(内存不足杀手)终止某个进程来释放内存——把进程镜像存回RAM完全违背内存管理逻辑,只会进一步加剧内存占用。

  2. 若上述问题答案为是,是否意味着当进程请求更多被其他进程占用的内存时,会发生上下文切换?
    上题答案为否,此问题前提不成立。但正常来说,内存不足时内核处理页错误、页回收、OOM Killer的过程中必然会发生上下文切换,不过和"生成进程镜像"无关。

  3. 关于页错误的工作机制,此后由于这1GB内存无法释放,可用RAM仍为2.8GB,当p4请求数组下一个元素时,内核是否会卸载首个页面,再加载新页面替代?
    首先计算可用内存:总物理内存4GB(4096MB)减去内核预留200MB、p1/p2/p3占用的1GB(1024MB)、p4已占用的2.8GB(2867MB),剩余内存不足10MB,已经处于耗尽状态。p4的这些页面是已修改的匿名页(MAP_PRIVATE映射空文件,写入后无后备存储),内核无法卸载这类页面(卸载意味着数据丢失),所以不会出现"卸载旧页加载新页"的情况,此时内核会直接触发OOM Killer,选择合适的进程杀死以释放内存。

  4. 若第三个问题答案为是(我对此存疑),内核如何保存即将被新页面占用物理内存的已卸载页面的数据?(无交换分区,是否会强制使用磁盘交换空间?)
    上题答案为否,此场景不成立。如果是有后备存储的页面(比如MAP_SHARED映射的文件页、可回收的文件缓存),内核会把数据写回对应的后备文件再释放物理页;但匿名页无后备存储,无交换分区时无法保存,因此这类页面不能被回收,只能通过杀进程释放内存。

  5. 若使用MAP_SHARED方式会怎样?已卸载页面的数据是否会写入后备文件,然后释放物理空间?
    是的。如果p4用MAP_SHARED映射空文件,写入后的页面后备存储就是该空文件。当内存不足时,内核可以把已修改的页面写回对应的文件,然后释放物理内存;后续需要访问这些页面时,再从文件中读回物理页。这种情况下系统不会立刻触发OOM,而是会产生大量磁盘IO,导致运行变慢,但不会直接挂起或杀死进程。

  6. 当p4这类进程导致RAM被占满时,系统为何会挂起?是因为需要额外空间恢复p1、p2、p3的镜像?还是这些进程会在那1GB内存中恢复,但一旦请求更多内存就会冻结?
    系统挂起的核心原因是内存耗尽后,内核陷入频繁的页错误和OOM Killer的死循环,或所有用户进程因等待内存分配被阻塞:

  • p4占用几乎所有可用内存后,p1/p2/p3需要内存时,内核无法分配,会将这些进程置为睡眠状态等待内存;
  • 内核尝试回收内存,但无交换分区时匿名页无法回收,只能触发OOM Killer杀进程,若OOM Killer未选择p4,杀其他进程释放的内存会很快被p4再次占满,导致OOM Killer反复运行;
  • 系统CPU时间几乎全部被内核用于处理内存不足的逻辑,用户进程得不到运行时间,看起来就像挂起了。不存在"恢复进程镜像"的说法,进程的内存本来就在RAM中,只是被阻塞无法运行。
  1. 若第6个问题答案为是,且那3个进程使用MAP_SHARED,它们是否会像第5个问题描述的那样继续运行但变慢(每次仅占用一个RAM页面)?
    是的。如果p1/p2/p3的内存是MAP_SHARED映射的文件页,内存不足时内核可以把它们的已修改页面写回后备文件,释放物理内存;当这些进程需要访问这些页面时,会触发页错误,内核从文件读回页面,这个过程会产生磁盘IO,导致进程运行变慢(需等待磁盘操作完成),但不会被直接杀死,也不会完全挂起,只是响应性极差。

  2. SysRq仍能工作,是否意味着所有进程都会挂起,但由于内核预留了内存,自身不会挂起?
    是的。SysRq是内核直接处理的功能,不需要用户态进程参与,而且内核预留了紧急内存,即使系统内存耗尽,内核仍有足够内存处理SysRq请求(比如触发OOM Killer、重启系统、杀死指定进程等)。此时用户态进程可能都因等待内存分配而处于阻塞状态,看起来像是挂起,但内核本身仍能正常运行关键功能。


内容的提问来源于stack exchange,提问作者Shahaboddin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:44:54