我有以下与处理文件和映射文件相关的问题(mmap
):
mmap
将该文件映射到内存然后写?mmap
- PROT_NONE
,PROT_READ
,PROT_WRITE
实现了保护,那么使用文件也可以实现相同级别的保护。 O_RDONLY
,O_RDWR
等等。那么为什么mmap
?mmap
一个文件到内存,如果我们写入mmap返回的内存位置,它是否也同时写入该文件?请帮我回复所有问题。
提前多多感谢。
*编辑:在线程之间共享文件*
据我所知,如果我们在两个线程(非进程)之间共享一个文件,那么建议mmap
将它放入内存然后使用它,而不是直接使用该文件。
但是我们知道使用文件意味着它肯定在主内存中,那为什么线程需要再次进行mmaped?
答案 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)
一个原因可能是你有(传统)代码被设置为写入数据缓冲区,然后这个缓冲区最后一次写入文件。在这种情况下,使用mmap
将保存至少一个数据副本,因为操作系统可以直接将缓冲区写入磁盘。
只要它只是关于文件写入,我就不能(想象)想象你为什么要使用mmap
。
不,这里的保护与我无关。
它可能会保存一个或两个数据副本,例如: app缓冲区到libc缓冲区到OS缓冲区,请参见第1点。这可能会在写入大量数据时产生性能差异。
没有。据我所知,只要数据在调用该内存区域的msync
或munmap
后写入磁盘,操作系统就可以随时自行编写数据。
(并且对于大多数文件,由于执行原因,它可能不会在大多数时间之间写入任何内容:将整个块写入磁盘,因为一个字节更改相当昂贵,特别是如果预期会有更多修改块将在不久的将来发生。)
答案 3 :(得分:0)
在大多数情况下,您应该将内存映射文件视为您使用的内存。您应该只关心与光盘同步等特殊情况。它与存储器的存储方式相同,但可以根据需要从文件初始化并存储到文件中。