【发布时间】:2013-06-15 11:24:19
【问题描述】:
我目前正在通过内存映射在多个进程之间共享数据 (mmap同一个文件。
目前,阅读器进程需要不断检查更新。读取器进程不断轮询 mmap-ed 区域以查看是否写入了任何新数据。
典型用法(和现有实现):
“Writer”进程是一个记录器,它以不规则的时间间隔不断地附加新数据(每个都在新行上)。在任何给定时间点,可能有一个或多个“读取器”进程对“写入器”进程生成的任何新数据感兴趣。此外,它不是无限扩展的文件,而是一个循环缓冲区,即在固定数量的行之后,编写器循环返回并开始用新数据从头开始覆盖文件。此文件中的头字段跟踪最新数据的位置,即当前“头”。
简而言之,系统试图模仿 msgsnd() 和 msgrcv() 的语义,但有两个额外的警告:
支持多个“读者”
当“作家”发布单个消息时,应发送多个通知,每个通知 1 活跃的“读者”。
--> 目前实现,每个“reader”不断轮询“head”字段并在新数据发生变化时读取。持久性(文件支持)
如果任何“读取器”/“写入器”进程突然终止,恢复系统应该与重新启动进程一样简单。
--> 目前已实现,因为 IPC 共享数据保存在磁盘上的 mmap-ed 文件中。
什么是
- 快速(低延迟)和
- 轻量级(低 cpu 使用率)替代方案来实现某种事件机制,以在每次 mmap-ed 区域被写入进程修改?
注意:在读取进程中,当写入进程更新 mmap 内存时,在 mmap 文件上添加 inotify 监视不会导致任何事件(即使在打电话给msync())。
【问题讨论】:
-
来自手册页,
For file-backed mappings, the st_atime field for the mapped file may be updated at any time between the mmap() and the corresponding unmapping; the first reference to a mapped page will update the field if it has not been already. The st_ctime and st_mtime field for a file mapped with PROT_WRITE and MAP_SHARED will be updated after a write to the mapped region, and before a subsequent msync(2) with the MS_SYNC or MS_ASYNC flag, if one occurs.- 这有帮助吗? -
您应该使用某种同步原语(信号量/互斥量)。您可以将其放在映射区域中。无论如何,你都应该使用它来避免竞争条件,当一个进程写入而另一个进程同时读取相同的内存时。
-
@VoidPointer 所以在阅读器过程中,我必须不断地在文件上反复调用 stat() 吗?
-
@zch 因为总是有一个“作家”,我相信我们可以不使用任何锁定机制(以实现更快的性能)。因此,除非绝对必要,否则我想避免锁定。我还用当前实现的典型用法和细节更新了 Q。
-
@zch 基本上,我试图避免使用信号量/互斥体,以免由于阻塞(饥饿)而降低性能,如en.wikipedia.org/wiki/Readers-writers_problem 中所述。因为我只需要一个事件,即通知机制来将阅读器代码重构为等待事件而不消耗 cpu 周期重复轮询。