修改内存映射文件时通知/发出信号

Posted

技术标签:

【中文标题】修改内存映射文件时通知/发出信号【英文标题】:Notify/Signal when memory mapped file modified 【发布时间】: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 周期重复轮询。 【参考方案1】:

在所有阻塞通信中,读取器获取数据,其他读取器无法读取。

您可以创建一个阅读器链。这很糟糕,因为在您的情况下,进程可能会突然结束 使用多个管道。每次创建阅读器时,它都可以要求作者打开一个管道,然后阅读器可以订阅该管道并读取它。此外,写入者可以向读取者发送当前数据状态的副本,除非读取者可以自行访问它。 使用信号。您可以在每次写入后从写入器向所有读取器发送信号。

虽然是个棘手的问题...这些都是我得到的...

【讨论】:

【参考方案2】:

(贴出实际使用的解决方案以供日后参考)

使用这个添加mmap-ed file support to inotify的补丁,

reader 进程可以使用 inotify 框架 以重要/重要的时间间隔监控 mmap 文件的更改 由 writer 进程在同一个 mmap 文件上调用 sync() 触发。

【讨论】:

以上是关于修改内存映射文件时通知/发出信号的主要内容,如果未能解决你的问题,请参考以下文章

linux虚拟内存附加/分离信号

共享内存之——mmap内存映射

linux 进程间通信——内存共享映射mmap和munmap

JavaNIO的深入研究4内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射

JavaNIO的深入研究4内存映射文件I/O

Linux共享内存