内存映射IO概念细节

时间:2017-06-22 17:24:37

标签: c++ windows multithreading operating-system mmap

我试图找出在Windows中编写文件的最佳方法。为此,我一直在运行一些带有内存映射的测试,试图弄清楚发生了什么以及我应该如何组织事情......

场景:该文件旨在用于多个线程中的单个进程。你应该看到一个线程作为一个工作于文件存储的工作者;其中一些会读,一些会写 - 在某些情况下文件会增长。我希望我的状态能够在进程和操作系统崩溃中幸存下来。文件可能很大,比如:1 TB。

在MSDN上阅读了很多内容之后,我掀起了一个小测试用例。我基本上做的是以下几点:

  1. 使用CreateFile打开文件(FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH)。
  2. 使用一些文件增长机制在文件上构建mmap文件句柄(CreateFileMapping)。
  3. 使用扇区大小的倍数(来自MapViewOfFile)映射内存区域(STORAGE_PROPERTY_QUERY)。我打算使用的模式是READ + WRITE。
  4. 到目前为止,我一直无法弄清楚如何正确使用这些构造(diskmon之类的工具无法正常工作)所以我决定在这里问一下。我基本上想知道的是:我如何才能最好地将这些结构用于我的场景?

    如果我理解正确,这或多或少是正确的方法;但是,我不确定CreateFileMapping vs MapViewOfFile的确切作用,以及它是否可以在多个线程中工作(例如,在将它们刷新到磁盘时进行写入的方式)。

    1. 我打算按照每个进程打开一次文件(1)。
    2. 每个线程,我打算按照(2)为整个文件创建一个mmap文件句柄。如果我需要增加文件,我将估计需要多少空间,关闭句柄并使用CreateFileMapping重新打开它。
    3. 当工人正在做它的事情时,它需要文件的一部分。因此,我打算为每个部分使用MapViewOfFile(似乎限制为2 GB),处理它并再次取消映射。
    4. 问题:

      1. 我是否理解这些概念?
      2. 什么时候数据物理读写到磁盘?那么,当我有一个在(3)中写入1 MB数据的循环时,它会在 unmap调用之后写入数据吗?或者,当我在另一个页面中记忆时,它会写入数据吗? (毕竟,磁盘是块设备,因此在某些时候我们必须编写一个块...)
      3. 这可以在多个线程中工作吗?这是关于呼叫本身 - 如果你有100名工人,我不确定他们是否会出错。
      4. 我明白(写入)数据可以立即在其他线程中使用(除非它是远程文件),这意味着我应该小心读/写并发。如果我打算写东西,然后更新单个物理块)头(表明读者应该从现在开始使用另一个指针) - 那么它是否保证数据先于写入头?
      5. 如果我使用1个文件或多个文件(假设它们当然在同一个物理设备上)会有用吗?

1 个答案:

答案 0 :(得分:-3)

内存映射文件通常最适合READING;不写作您遇到的问题是在进行映射之前必须知道文件的大小。

你说:

  

在某些情况下文件会增长

这确实排除了内存映射文件。

在Windoze上创建内存映射文件时,您将创建自己的页面文件并将一系列内存映射到该页面文件。这往往是读取二进制数据的最快方法,尤其是在文件是连续的情况下。

对于写入,内存映射文件存在问题。