写入文件和映射内存有什么区别?

时间:2011-09-02 08:21:20

标签: c linux file mmap

我有以下与处理文件和映射文件相关的问题(mmap):

  1. 我们知道,如果我们创建一个文件,并写入该文件,那么我们写入内存的方式。那么为什么要使用mmap将该文件映射到内存然后写?
  2. 如果是因为我们使用mmap - PROT_NONEPROT_READPROT_WRITE实现了保护,那么使用文件也可以实现相同级别的保护。 O_RDONLYO_RDWR等等。那么为什么mmap
  3. 我们将文件映射到内存然后使用它有什么特别的优势吗?而不仅仅是创建一个文件并写入文件?
  4. 最后,假设我们mmap一个文件到内存,如果我们写入mmap返回的内存位置,它是否也同时写入该文件?
  5. 请帮我回复所有问题。

    提前多多感谢。

    *编辑:在线程之间共享文件*

    据我所知,如果我们在两个线程(非进程)之间共享一个文件,那么建议mmap将它放入内存然后使用它,而不是直接使用该文件。

    但是我们知道使用文件意味着它肯定在主内存中,那为什么线程需要再次进行mmaped?

4 个答案:

答案 0 :(得分:16)

内存映射文件实际上部分或全部映射到内存(RAM)中,而您写入的文件将写入内存然后刷新到磁盘。内存映射文件从磁盘中获取并显式放入内存中以供读取和/或写入。它会保留在那里直到你取消映射它。

对磁盘的访问速度较慢,因此当您写入文件时,它将被刷新到磁盘而不再驻留在RAM中,这意味着,下次需要该文件时,您可能会获得它从磁盘(慢),而在内存映射文件中,你知道该文件在RAM中,你可以更快地访问它,然后它在磁盘上。

此外,mememory映射文件通常用作IPC机制,因此两个或多个进程可以轻松共享同一个文件并对其进行读/写。 (使用必要的sycnh机制)

当你需要经常读取文件时,这个文件非常大,将它映射到内存中是有利的,这样你就可以更快地访问它,然后每次都要打开它并从磁盘上获取它。

修改

取决于你的需求,当你有一个需要被不同线程频繁访问的文件时,那么我不确定内存映射文件一定是个好主意,从以下观点来看,如果您希望在不同线程的相同位置写入,则需要同步访问此mmap的文件。如果这种情况经常发生,它可能是资源争用的一个地方。

只是从文件中读取,这可能是一个很好的解决方案,因为如果你只是 从多个线程读取它,你就不需要同步访问。在你开始写作的那一刻,你必须使用同步机制。

我建议,你有每个线程以线程本地方式自己进行文件访问,如果你必须写入文件,就像你对任何其他文件一样。通过这种方式,它减少了线程同步的需要,并且很难找到和调试错误。

答案 1 :(得分:2)

1)你误解了write(2)系统调用。 write()不写,它只是将缓冲区内容复制到OS缓冲区链并将其标记为脏。其中一个操作系统线程(bdflush IIRC)将获取这些缓冲区,将它们写入磁盘并摆弄一些标志。后来。 使用mmap,您可以直接访问OS缓冲区(但是如果您更改它的内容,它也会被标记为脏)

2)这不是关于保护,而是关于在页面表条目中设置标志。

3)你避免双重缓冲。你也可以用字符而不是块来处理文件,这有时候更实用

4)这是你一直在使用的系统缓冲区(挂在地址空间中)。系统可能会也可能没有将其部分写入磁盘。

5)如果线程属于同一个进程并共享pagetables和地址空间,那么就是。

答案 2 :(得分:1)

  1. 一个原因可能是你有(传统)代码被设置为写入数据缓冲区,然后这个缓冲区最后一次写入文件。在这种情况下,使用mmap将保存至少一个数据副本,因为操作系统可以直接将缓冲区写入磁盘。 只要它只是关于文件写入,我就不能(想象)想象你为什么要使用mmap

  2. 不,这里的保护与我无关。

  3. 它可能会保存一个或两个数据副本,例如: app缓冲区到libc缓冲区到OS缓冲区,请参见第1点。这可能会在写入大量数据时产生性能差异。

  4. 没有。据我所知,只要数据在调用该内存区域的msyncmunmap后写入磁盘,操作系统就可以随时自行编写数据。 (并且对于大多数文件,由于执行原因,它可能不会在大多数时间之间写入任何内容:将整个块写入磁盘,因为一个字节更改相当昂贵,特别是如果预期会有更多修改块将在不久的将来发生。)

答案 3 :(得分:0)

在大多数情况下,您应该将内存映射文件视为您使用的内存。您应该只关心与光盘同步等特殊情况。它与存储器的存储方式相同,但可以根据需要从文件初始化并存储到文件中。