Linux 在书写页上扔掉脏的副本

Linux 在书写页上扔掉脏的副本,linux,mmap,Linux,Mmap,有没有一种方法可以让我通过MAP_PRIVATE创建一个写时拷贝映射,写入一些数据(即,弄脏一些页面),然后放弃我的更改,而不使用munmap和重新映射?目标是为给定的映射维护相同的虚拟地址(如果我取消映射,然后再次映射同一个文件,则不一定会发生这种情况),而是一次放弃所有COW更改 我的理解是,试图通过暗示地址和使用map_FIXED标志重新映射空间可能会产生这种效果;但是,我不确定我对MAP_FIXED docs的解释是否正确,或者这种行为是否有保证 引用mmap(2)文件: 在这种情况下,

有没有一种方法可以让我通过MAP_PRIVATE创建一个写时拷贝映射,写入一些数据(即,弄脏一些页面),然后放弃我的更改,而不使用munmap和重新映射?目标是为给定的映射维护相同的虚拟地址(如果我取消映射,然后再次映射同一个文件,则不一定会发生这种情况),而是一次放弃所有COW更改

我的理解是,试图通过暗示地址和使用map_FIXED标志重新映射空间可能会产生这种效果;但是,我不确定我对MAP_FIXED docs的解释是否正确,或者这种行为是否有保证

引用mmap(2)文件:


在这种情况下,“丢弃”是否意味着任何COW页面都将被丢弃,并且从相应页面进行的新读取将出错并反映磁盘上的更改?

即使在复制之后,虚拟地址仍保持不变。只有物理地址更改(以及相关的内存映射页寄存器)


进程写入页面后,撤消该进程为时已晚。复制发生在首次写入内存区域的过程中。

如果执行与现有映射重叠的
mmap
操作,Linux内核将覆盖现有映射的重叠部分,就像首先对它们执行了
取消映射一样。例如,如果你把一个帧缓冲区映射到一个共享库以前所在的位置,那么这个内存现在与共享库无关;它指向帧缓冲区

移除映射的基础页面对象独立于映射而存在:页面是引用计数对象。当两个地图共享同一页面的视图时,这仅仅是因为同一页面“安装”在不同的视图中。当页面变脏,然后取消映射时,这不会创建一个依赖项,即脏页面必须在新映射之前写出;在清除原始脏页(例如,文件支持的共享映射的一部分)之前,可以将虚拟内存重新分配给新映射(例如一块图形帧缓冲区)

关于扔掉地图:我认为你做不到。也就是说,如果您有一个映射,它应该将脏页刷新到一个底层文件,那么您就无法写入该内存,然后
unmap
将其快速(或
mmap
上的某个内容)取消映射,希望永远不会进行写入。在Linux的
madvise
API中,似乎有相关的
MAP\u REMOVE
操作,但根据手册页面,它似乎只适用于
tmpfs
shmfs
。我认为阻止写操作发生的唯一方法是进行一项由来已久的仪式,即“俯冲到电源开关前”

有一种方法可以映射文件对象,使更改不会传播:即,
map\u PRIVATE
(与
map\u SHARED
相反)<例如,像
gdb
这样的调试器需要code>MAP\u PRIVATE
,它需要能够将断点放入可执行文件或共享库,而无需在每个运行进程(以及磁盘上的副本!)中向该可执行文件或库的每个实例抛出陷阱指令


如果您有一个带有修改部分的
MAP\u PRIVATE
,并且您取消了它(或那些部分)的映射,或者在它们上面映射了一些东西,我相信它们将被丢弃。这些页面本应在书写时进行复制,因此使其变脏的过程应包含唯一的参考。当它们被取消映射时,它们的refcount会下降到零,因为它们是私有页,所以它们会被覆盖。

我知道我会在第一个副本上写入物理RAM,我无法“撤消”它-但问题是,具有重叠地址(或其他机制)的新mmap是否会导致相同的虚拟内存被覆盖“重新初始化“从映射过程的角度来看,以一种抛弃这些变化的方式。非常有趣。因此,如果我1)在文件上创建MAP_私有映射,2)将其读入页面缓存,3)通过在该私有COW映射中写入来脏掉一些页面,4)使用MAP_FIXED标志重新映射,覆盖MAP_私有映射的地址空间,我应该在页面缓存中保留底层文件的“真实”数据,也抛弃了我对母牛“变化”的看法。这是非常方便的行为;我认为文件中的原始数据应该重新出现;如果要
lseek
到这些位置并
读取,您将看到相同的数据。
If the memory region specified by addr and len overlaps pages of any existing
mapping(s), then the overlapped part of the existing mapping(s) will be 
discarded.