C linux内核何时将页面写回内存映射文件?

C linux内核何时将页面写回内存映射文件?,c,linux,mmap,C,Linux,Mmap,我正在考虑一个系统,它可以让我存储映射文件并透明地对它们包含的数据进行类型转换。似乎可以捕获内存访问,方法是:映射第二个内存区域并使其受到保护,然后在访问新页面时捕获SEGFULT。这将使我能够处理所需的读类型转换 然而,为了读/写兼容,我需要一些方法来捕获操作系统何时将部分内存分页回磁盘,以便在写入之前以另一种方式进行类型转换 有没有这样连接寻呼系统的功能?您想要的是不可能的,这反映了对mmap的根本误解。文件备份的映射被写回磁盘的事件与此无关,因为在此之前,任何读取文件的尝试(并且必须,以符

我正在考虑一个系统,它可以让我存储映射文件并透明地对它们包含的数据进行类型转换。似乎可以捕获内存访问,方法是:映射第二个内存区域并使其受到保护,然后在访问新页面时捕获SEGFULT。这将使我能够处理所需的读类型转换

然而,为了读/写兼容,我需要一些方法来捕获操作系统何时将部分内存分页回磁盘,以便在写入之前以另一种方式进行类型转换


有没有这样连接寻呼系统的功能?

您想要的是不可能的,这反映了对
mmap
的根本误解。文件备份的映射被写回磁盘的事件与此无关,因为在此之前,任何读取文件的尝试(并且必须,以符合POSIX)都将从页面的修改内存副本中读取,而不是从磁盘上过时的内容中读取。换句话说,将修改过的页面写回磁盘对应用程序来说是完全透明的,并且假设您从未断电或重新启动,则完全有可能修改过的页面永远不会写回磁盘


你的设计就是不起作用。如果您想要这种行为,您必须做一些不同的事情。

使用内存映射和SIGSEGV处理程序有点问题。首先,不是,这意味着信号处理程序中的
mprotect()
不能保证工作。其次,信号处理程序和多个线程之间必要结构的同步相当复杂(尽管可以使用GCC和/或内置),因为您无法在信号处理程序中使用标准锁定原语——幸运的是,您可以从信号处理程序返回;内核不会跳过有问题的指令,因此随后会立即发出相同的信号

我确实编写了一个小程序来测试匿名私有无保留内存映射,使用
read()
write()
来更新映射。问题在于,当信号处理程序更新映射时,其他线程可能会访问该映射

我认为,如果您为当前活动区域使用临时文件,在记录跨越页面边界时,前后都有一个额外的页面来保存部分记录,这可能会起作用

实际数据文件将由一个私有的匿名的无保留的不可访问的映射表示(
PROT_NONE
map_anonymous | map_private | map_NORESERVE
)。SIGSEGV信号处理程序捕获对该映射的访问。该映射的页面对齐区域将取消映射并从临时文件映射(
map_SHARED | map_FIXED | map_NORESERVE
)。诀窍是临时文件可以另外映射到另一个内存区域(
MAP|SHARED | MAP|NORESERVE
),信号处理程序可以简单地取消映射映射中的临时文件,以阻止其他线程在转换期间访问该区域;数据仍然可用于另一个内存区域中的库函数(使用
read()
write()
读取和写入实际数据文件)
MAP\u SHARED
表示使用完全相同的页面(来自页面缓存),而
MAP\u NORESERVE
表示内核不为它们保留交换或RAM


这种方法在线程和锁定方面应该可以很好地工作,但是它仍然受到
mmap()
munmap()
、和
mremap()
不异步信号安全的影响。但是,如果您确实只以原子方式访问了一个全局变量,从而在应用程序/库代码修改结构和/或映射时导致信号处理程序立即返回,那么这应该是可靠的。

我当然理解,但是如果页面被交换回磁盘,为了实现我想要的工作,我必须截取它,键入convert,然后将该类型转换后的数据写回磁盘。当我保证任何修改过的数据都被写回磁盘时,我会打电话给munmap。不,你不明白
munmap
不保证将数据写回磁盘。它所做的只是从进程的虚拟地址空间中删除映射。POSIX系统上根本不存在“存储在磁盘上”的概念。通过
mmap
-获得的映射进行的任何写入操作都可以立即被任何以任何方式读取文件的进程看到,无论是
read
还是另一个
mmap
。好的,肯定有一个msync()函数可以保证更改被写回,所以我也这么说。你似乎说的和你现在在这里所说的完全相反:对不起,我想也许我没有解释清楚。我希望内存映射文件,但随后创建第二个匿名内存映射区域,以代理对内存映射文件的访问以进行类型转换。我可以通过保护匿名访问并捕获其中的SIGSEGV来处理其中的读取部分,但它是以另一种方式进行的,并实际写入到第二个映射区域,我很好奇我是否能够以某种方式处理该区域。您想要做的事情听起来类似于ENCF,它使用FUSE来提供文件加密。它必须能够在读取时解密,在写入时加密。也许您可以使用encfs作为指导来创建自己的FUSE文件系统。现在有一个想法,我将对此进行研究。这基本上可以归结为同一件事。我只是想用另一种方式转换数据。(编辑)哦,但我只是想,我不想把我的文件存储在一个特殊的地方来获得这种行为,我希望它能适用于任何文件,比如过滤器。不过我还是会检查一下。您的FUSE fs可以在本机fs上作为装载选项提供一个目录名,并将所有内容传递给它,让较低级别的fs像通常那样与块设备通信。堆叠!我想这就是encfs的工作原理。谢谢你的评论。