gpt4 book ai didi

c - 处理进程间大文件的 mmap 和 fread

转载 作者:IT王子 更新时间:2023-10-29 01:21:06 27 4
gpt4 key购买 nike

我有两个进程:进程 A 正在将大文件(~170 GB - 内容不断变化)映射到内存中以使用标志 MAP_NONBLOCKMAP_SHARED 进行写入:

MyDataType *myDataType; = (MyDataType*)mmap(NULL, sizeof(MyDataType), PROT_WRITE, MAP_NONBLOCK | MAP_SHARED , fileDescriptor, 0);

每一秒我都会调用 msync:

msync((void *)myDataType, sizeof(MyDataType), MS_ASYNC); 

这部分工作正常。

当进程 B 试图从进程 A 映射到的同一个文件中读取时,进程 A 在大约 20 秒内没有响应。进程 B 尝试使用 fread()fseek() 小块(每次约 4 个字节)从文件中读取大约 1000 次。该进程正在阅读的大部分内容彼此接近。

这个问题的原因是什么?它与页面分配有关吗?我该如何解决?

顺便说一句,当我在进程 B 中使用 mmap() 而不是简单的 fread() 时,也会出现同样的问题。

最佳答案

msync() 可能是问题所在。它强制系统写入磁盘,在写入狂潮中阻塞内核。通常在 Linux 上(顺便说一句,在 Solaris 上也是如此),过于频繁地使用 msync() 并不是一个好主意。内存映射和read()/write() I/O操作之间的数据同步不需要调用msync(),这是一种误解来自过时的 HOWTO。实际上,mmap() 只使进程的文件系统缓存“可见”。这意味着进程更改的内存块仍在内核控制之下。即使您的进程崩溃,更改最终也会落在磁盘上。其他进程也仍将由同一缓冲区提供服务。

这里是关于这个主题的另一个答案 mmap, msync and linux process termination有趣的部分是关于 realworldtech 的讨论链接,其中 Linus Torvalds 自己解释了缓冲区缓存和内存映射的工作原理。

PS:fseek()/fread() 对也可能更好地替换为 pread()。 1 次系统调用总是比 2 次好。此外,fseek()/fread() 始终读取 4K 并在缓冲区中复制,因此如果您有多个小读取而不使用 fseek(),它将从其本地缓冲区读取并可能错过进程 A 中的更新。

关于c - 处理进程间大文件的 mmap 和 fread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34336107/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com