虚拟内存
全库目录221
本文目录8
申请很大地址区间,不一定立刻占用同样多物理内存。虚拟内存把地址与物理页分开,首次访问可能触发缺页,随机工作集又会增加TLB开销。Reserve、Commit和驻留要分别观测。
虚拟内存、页表与 TLB
每个进程拥有独立的虚拟地址空间,实际映射可以分散,中间保留未映射区间。页表把虚拟页映射到物理页,并记录读写执行权限。不同进程可以把同一物理页映射到不同地址,用于共享库、共享内存和写时复制。
TLB 缓存最近使用的地址翻译。工作集跨越大量页或访问模式随机时,TLB Miss 增加,硬件需要查询多级页表。大页可以减少页表层级和 TLB 压力,但分配、碎片和平台权限更复杂。
访问尚未建立有效映射的页面会触发缺页异常。次缺页可能只需建立已有物理页映射;主缺页可能要从磁盘读取,延迟高得多。首次触碰新提交内存、内存映射文件和换页都可能产生缺页异常。
Reserve 通常只占用地址范围,Commit 才承诺可用存储,实际物理页还可能在首次访问时分配。引擎分配器可以先申请大块虚拟地址,再按页提交和回收,减少频繁进入内核。
栈、堆与内存映射
线程栈保存调用帧、局部变量和返回信息,容量有限,提交与增长方式取决于操作系统和栈类型;例如Windows常规线程栈可以通过保护页逐步提交。深递归、大型局部数组和无限调用链会造成栈溢出。
语言运行库的堆分配器在操作系统提供的大块虚拟内存上管理小对象。new/malloc 不一定每次直接调用系统;分配器会维护尺寸类别、空闲链表、Arena 或线程缓存。多线程高频分配还要处理锁竞争和跨线程释放。
内存映射文件把文件区间映射到虚拟地址。读取由缺页异常按需触发,操作系统页缓存可以与普通文件 IO 共享数据。它适合随机访问大型文件,但仍要处理映射生命周期、文件截断、错误页和显式刷盘语义。
按页提交
平台中立伪代码保留地址区间,再为所需页提交存储;具体OS接口与权限由后端实现。
range = ReserveVirtualAddress(capacity)
CommitPages(range, requiredBytes)
TouchCommittedPagesIfLatencyRequires()
DecommitUnusedPagesAfterReadersFinish()
ReleaseRange()保留、提交与驻留
Windows VirtualAlloc 的MEM_RESERVE保留虚拟地址,MEM_COMMIT为页承诺存储;首次访问仍可能触发物理页建立。先保留1GiB地址再提交其中4MiB,并不意味着工作集立即增加1GiB。Linux的映射与过量承诺策略使用不同接口和保证,不能把Windows术语直接当跨平台契约。
范围操作按页向外取整。若页大小为P,起始偏移为s、长度为n,先检查s+n不溢出,再取开始页 floor(s/P) 与结束页 ceil((s+n)/P)。相邻分配若共享一页,释放其中一个对象不能直接撤销整页,否则会破坏仍在使用的邻居。
例如P=4096,A占[100,3000),B占[3000,5000)。A使用第0页,B同时使用第0、1页。销毁A后,第0页仍有B的1096字节,撤销它会让B的合法地址故障。页级分配器可为每页维护有效子分配数量,只有计数为零并且所有异步读者结束,才撤销提交。页取整解决覆盖范围,引用计数解决共享寿命,两者承担不同条件。
TLB未命中与缺页也有区别:页表中已有有效映射时,硬件页表遍历可以完成地址翻译;只有访问触发页故障条件才进入异常处理。因而随机访问慢并不能单凭耗时归因于磁盘换页,要分别观察TLB、缓存与缺页计数。
验证方法
比较地址保留、提交量与驻留集,冷访问记录缺页,热访问记录TLB与缓存。测试文件截断、映射失效和跨页范围;大页的收益由实际工作集验证。
实现与证据
页范围为推导与平台API语义说明。已核读VirtualAlloc,未在本机执行大块保留、页提交或驻留测量;Linux语义只作为需独立后端的边界。
相关主题
参考资料
- Microsoft VirtualAlloc:MEM_RESERVE与MEM_COMMIT;2026-10-22核读。