如何确保内存映射文件保持内存页面可访问?

Posted

技术标签:

【中文标题】如何确保内存映射文件保持内存页面可访问?【英文标题】:How can I ensure that a memory-mapped file keeps the memory pages accessible? 【发布时间】:2013-03-28 10:36:51 【问题描述】:

我正在使用 Qt 将文件映射到一块内存页面

QFile::map (qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions)

本质上,这应该是一个mmap 系统函数调用。我想知道如何保证我可以访问返回的内存,即使磁盘上的文件被截断。我似乎需要这个,因为我从磁盘文件中读取并希望优雅地处理错误

if (offset > m_file.size()) 
  // throw an error...
if (m_mappedFile != NULL) return m_mappedFile + offset;

显然,这包含一个竞争条件,因为文件大小可能会在检查和访问映射之间发生变化。如何避免这种情况?

【问题讨论】:

当有一些打开的描述符引用它时,文件不会停止存在 - open()ed 或 mmap()ed。即使另一个进程发出remove(),或者如果您从shell 发出rm @xtofpernaud 是的,你是对的。但是如果我截断它,那将修改与文件描述符关联的文件。 来自 man mmap:SIGBUS Attempted access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file, including the case where another process has truncated the file)。如果这可能发生在您的代码中,您可能必须处理 SIGBUS.. @xtofpernaud 如果我创建文件,打开它,然后在使用期间使其只读?我可以使用以前打开的文件描述符截断并写入它吗? XXX:如果我只是从文件中读取,这将不起作用。我可能没有写权限,但其他人可能有。 @FrankOsterfeld 我只想在文件突然从外部更改(用户删除或截断它)的情况下尽可能稳定。我知道没有 100% 的安全。 【参考方案1】:

来自man mmap

SIGBUS Attempted  access to a portion of the buffer that does not correspond to the file
       (for example, beyond the end of  the  file,  including  the  case  where  another
       process has truncated the file).

所以你必须为 SIGBUS 安装一个信号处理程序(默认是崩溃程序)

【讨论】:

以上是关于如何确保内存映射文件保持内存页面可访问?的主要内容,如果未能解决你的问题,请参考以下文章

1-4_基本概念_进程间通信及同步

文件映射原理及实现

内存映射文件到 WPF 网格

共享内存实现原理

c# 通过内存映射实现文件共享内存

将几个大文件映射到内存中