先共享,后处理写入

Linux 的 fork 创建具有独立虚拟地址空间的子进程,但不必马上逐页复制父进程全部内容。父子可以先共享物理页,私有写入发生时,再按需要建立相应的私有存储。

这保留了父子普通私有内存修改互不影响的语义。共享的是起初的物理表示,而不是把所有后续写入变成另一个进程都能看到的共享变量。

参考:[1]

以页为单位的延迟成本

页表和访问保护让内核能够发现需要处理的写入。页错误并不都代表程序故障;内核文档把写时复制列为能够合法触发页错误的内存管理路径之一。

fork 仍需要创建子任务并处理页表等元数据。以后写入很多页时,实际复制和额外内存也会增加;因此收益取决于共享期间读写的范围,不能只看创建进程那一刻的速度。

参考:[1] [3]

私有文件映射的含义

mmap 的 MAP_PRIVATE 建立私有写时复制映射,对映射的修改不会写回原文件,也不会作为这些修改共享给映射同一文件的其他进程。它与用于传播共享修改的 MAP_SHARED 不同。

这不是自动的持久化快照。映射建立以后原文件被别处改变,其变化是否在私有映射中可见有规范边界;程序仍须明确选择一致性、保存及同步策略。

参考:[2]