Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 内存映射IO概念详细信息_C++_Windows_Multithreading_Operating System_Mmap - Fatal编程技术网

C++ 内存映射IO概念详细信息

C++ 内存映射IO概念详细信息,c++,windows,multithreading,operating-system,mmap,C++,Windows,Multithreading,Operating System,Mmap,我试图找出在Windows中编写文件的最佳方法。为此,我一直在运行一些内存映射测试,试图弄清楚发生了什么以及我应该如何组织事情 场景:该文件打算在单个进程、多个线程中使用。您应该将线程视为处理文件存储的辅助线程;其中一些会读,一些会写——在某些情况下,文件会增长。我希望我的状态能够在进程崩溃和操作系统崩溃中幸存下来。文件可以很大,例如:1 TB 在阅读了大量有关MSDN的内容后,我编写了一个小测试用例。我基本上做的是: 使用file\u FLAG\u NO\u BUFFERING\124; fi

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

场景:该文件打算在单个进程、多个线程中使用。您应该将线程视为处理文件存储的辅助线程;其中一些会读,一些会写——在某些情况下,文件会增长。我希望我的状态能够在进程崩溃和操作系统崩溃中幸存下来。文件可以很大,例如:1 TB

在阅读了大量有关MSDN的内容后,我编写了一个小测试用例。我基本上做的是:

  • 使用
    file\u FLAG\u NO\u BUFFERING\124; file\u FLAG\u WRITE\u to
    打开文件(
    CreateFile
  • 使用一些文件增长机制在文件上构建mmap文件句柄(
    CreateFileMapping
  • 使用扇区大小的倍数映射内存区域(
    MapViewOfFile
    )(从
    STORAGE\u PROPERTY\u QUERY
    )。我打算使用的模式是读+写
  • 到目前为止,我还没有弄清楚如何准确地使用这些构造(像
    diskmon
    这样的工具有很好的理由不起作用),所以我决定在这里提问。我基本上想知道的是:我如何在我的场景中最好地使用这些结构

    如果我理解正确,这或多或少是正确的方法;但是,我不确定
    CreateFileMapping
    MapViewOfFile
    的确切作用,以及这是否适用于多个线程(例如,刷新到磁盘时的写入顺序)

  • 我打算按照第(1)条的规定,在每个进程中打开该文件一次
  • 对于每个线程,我打算按照(2)为整个文件创建一个mmap文件句柄。如果需要扩展文件,我将估计需要多少空间,关闭句柄并使用
    CreateFileMapping
    重新打开它
  • 当工人在做自己的事情时,他需要文件的一部分。因此,我打算使用
    MapViewOfFile
    (似乎限制为2GB)对每一块进行处理并再次取消映射
  • 问题:

  • 我是否正确理解这些概念
  • 数据何时物理读取和写入磁盘?所以,当我有一个循环在(3)中写入1MB的数据时,它会在unmap调用之后写入该数据吗?或者它会在我进入另一页的内存时写入数据?(毕竟,磁盘是块设备,因此在某些时候我们必须写入块…)
  • 这在多线程中可以工作吗?这是关于电话本身——我不确定如果你有——比如说——100名工人,他们是否会出错
  • 我知道(写入的)数据可以立即在其他线程中使用(除非是远程文件),这意味着我应该小心读/写并发性。如果我打算写东西,然后更新一个单独的物理块(physical block)头(指示从现在开始读卡器应该使用另一个指针),那么是否保证数据在头之前写入
  • 如果我使用一个文件还是多个文件(当然假设它们在同一个物理设备上),这有关系吗
    内存映射文件通常最适合读取;不写。您面临的问题是,在进行映射之前,必须知道文件的大小

    你说:

    在某些情况下,文件将增长

    这实际上排除了内存映射文件

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


    对于写入,内存映射文件是有问题的。

    当您需要文件标记写入和“在操作系统崩溃后生存”时,使用MMF是完全不合适的。您无法控制将MMF更改刷新到磁盘的确切时间。“别这么做!”汉斯帕桑很有趣。我开始探索内存映射,因为我在一些论文中读到一些数据库将其用于磁盘IO(并且它们保证了ACID的“持久性”)。我还在PostgreSQL bugreports()上读到,他们停止使用
    FlushFileBuffers
    非常糟糕。那么,如果这两种方法都不适用,您在这里有什么建议作为解决方案?使用WriteFile和ReadFile有什么问题?因为你已经关闭了缓冲,所以在我看来,至少就操作系统而言,它们提供了你想要的保证。(如果您也想对电源故障保持健壮性,那么底层硬件可能尊重这些保证,也可能不尊重这些保证,但如果不这样做,您就无能为力。)(顺便说一句,我相信MapViewOfFile将适用于大于2GB的视图,当然前提是您构建的是64位。在这种情况下没有实际意义,因为正如Hans所说,您将无法获得所需的保证。)@HarryJohnston写文件没什么问题,我只是想找出最好的方法。所以,让我直截了当地说:你们基本上告诉我的是,我应该坚持使用它们,再加上无缓冲和写入。(或者,不要使用这些标志,而是显式使用
    FlushFileBuffers
    ——任何性能最好的)。正确吗?