Skip to content

模型Model

文件映射与私有修改

Memory-mapped file · MAP_SHARED and MAP_PRIVATE

把文件偏移映为虚地址,区分共享映射写回、私有COW写和映射生命周期,并检查close、截断与掉电边界。

形式陈述 ​

文件映射为虚拟区域指定文件backing。映射记录为(base,length,file,offset,protection,mode);对区域内虚地址v,其对应文件字节偏移为

q=offset+(v−base).

这里file是已解析的文件对象,不是每次访问都重新查找的路径字符串。OS-16把base、offset按256B页对齐,长度为正;映射建立先记录区域,实际页可在第一次访问时取得。

shared表示对映射的写修改文件的内存缓存副本,并可被映射同一文件区域的其他参与者观察;写回和持久化仍是后续协议。private表示本映射的写不改底层文件,也不发布给其他私有映射;实现可用COW在首次写时分离页。两种模式都还受读写权限约束。

OS-16为教学轨迹额外假定文件大小和外部内容在私有映射建立后不变。真实Linux mmap的MAP_PRIVATE并不承诺冻结快照:映射之后外部对文件的修改是否出现在私有映射中未指定。欲获得稳定快照,必须另有文件版本或同步协议。

直觉

普通read把字节复制到用户缓冲后由程序访问缓冲,mmap把“这个虚地址应该对应哪个文件字节”记录给内核,随后load/store也能触发文件页取得。接口看似没有read调用,不表示没有缺页、磁盘读取或错误。

一个私有映射像在必要时为自己留下修改稿;共享映射则修改共同的内存工作副本。两者都不是“CPU存储指令一完成,磁盘即已保存”。

例子与边界

地址、文件偏移与实际副本 ​

文件I从偏移0开始为abcdefgh,其余至255字节为零。P把文件页映到base=0x2000、offset=0,Q映到0x3000,均shared。P读0x2002对应q=2,返回c;P写0x2002为X后,Q读0x3002得到X,内存文件页为abXdefgh。稳定设备上的文件仍可为abcdefgh,所以共享观察不能充当掉电证据。

另开一次独立实验,先把文件及其内存缓存重置为abcdefgh,再建立两个private映射,并冻结外部文件修改。初始都可只读共享同一backing页。P写时复制该页,P见abXdefgh,Q仍见abcdefgh,底层文件仍未改变。此处分离条件来自私有文件映射,物理页复制与COW fork同用写故障机制,但没有要求P、Q具有父子关系。

关闭描述符不是解除映射 ​

Linux man-pages 6.19明确允许mmap成功后立即关闭原fd而映射继续有效。映射持有自己的文件关联;munmap才解除指定地址范围。此后对解除范围访问无效,即使原fd仍然开着也不会自动恢复映射。

文件被截短又是不同问题。Linux访问映射中超出文件结束的整页可触发SIGBUS,不能把原来的映射长度当成底层文件永久不变的承诺。最后一个不足整页的尾部、超文件末尾的修改如何处理也需遵守实际系统接口,本页练习使用完整一页以避开这些特殊字节。

推论与应用

映射取消需要删除或调整区域、撤销PTE、完成翻译失效,再释放页面及文件引用。若只删除区域元数据而TLB仍能访问旧页,已经释放的页框可能被旧虚地址继续改写;映射生命周期仍受内存隔离协议约束。

共享文件页通常通过页缓存合并普通文件I/O与映射访问。OS-16明确采用同一缓存对象;真实系统的具体一致性、直接I/O混用和跨机器文件系统行为,应另查其契约。

Linux的msync(MS_SYNC)用于等待指定映射范围的更新写回;文件和名称的恢复承诺还要结合文件/目录持久化。映射private页不因msync变成“提交修改到文件”;若想把私有结果写回,应用必须选择明确的写入协议。

参考资料
  • Linux man-pages 6.19,mmap(2)与msync(2),MAP_PRIVATE可见性、fd关闭、SIGBUS与同步范围,2026-10-08核查。
  • Cox、Kaashoek、Morris,xv6教材 rev5,§5.5,memory-mapped files作为真实系统扩展。
关系图谱4 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组