Linux 共享内存:shmget() 与 mmap()?

Posted

技术标签:

【中文标题】Linux 共享内存:shmget() 与 mmap()?【英文标题】:Linux shared memory: shmget() vs mmap()? 【发布时间】:2014-02-14 04:08:36 【问题描述】:

在this 线程中,建议OP 使用mmap() 而不是shmget() 在Linux 中获取共享内存。 我访问了this 页面和this 页面以获取一些文档,但第二个给出了一个关于mmap() 的模糊示例。

几乎是新手,需要在两个进程之间共享一些信息(以文本形式),我应该使用shmget() 方法还是mmap()?为什么?

【问题讨论】:

【参考方案1】:

这两种方法都是可行的。 mmap 方法比 shmget 更严格一些,但更易于使用。 shmget 是旧的 System V 共享内存模型,支持最广泛。 mmap/shm_open 是新的 POSIX 共享内存方式,更易于使用。如果您的操作系统允许使用 POSIX 共享内存,那么我建议您使用它。

一些提示:

如果您通过fork 创建您的孩子,那么mmapMAP_ANONYMOUS | MAP_SHARED 是迄今为止最简单的方法 - 只需一个电话。 MAP_ANONYMOUS 是一个 Linux 扩展 not specified by POSIX。 如果您独立启动进程,但可以为它们提供共享内存名称,则 shm_open (+ ftruncate) + mmapMAP_SHARED 是两个/三个调用。在某些操作系统上需要 librt。 如果您的操作系统有/dev/shm/,那么shm_open 相当于在/dev/shm/ 中打开文件。

【讨论】:

感谢您提供的所有有用建议。我暂时不会使用 fork。 但是用mmap修改内存时会自动修改硬盘上的文件?所以你经常写那个文件? /dev/shm 是你的内存盘。如果您使用文件支持的共享内存mmap 一个实际磁盘上的文件,那么将由操作系统来安排更新。通常,在您停止使用映射或分页守护程序决定将您的页面换出后很久,映射文件才会更新。您可以通过调用msync 来强制更新,这是使用您希望写入磁盘的文件支持映射时的推荐做法。 @BowPark 使用 MAP_ANONYMOUS 映射的内存没有文件支持。 在 OSX 上,您希望 mmap 因为 shmget 的最大共享内存在所有进程中只有 4mb。【参考方案2】:

这在很大程度上与历史和未来方向有关。

曾几何时,unix 有两个主要(并且有些竞争)版本 - system V 和 BSD。 SysV 有自己的 IPC 版本,包括大 3 - 共享内存、信号量和消息队列。 POSIX 的出现是为了尝试统一事物。

所以目前我们有两个版本 - posix 共享内存、MQ 和信号量以及 sysV 版本。只是为了让事情更加混乱,sysV 版本也是 posix 的一部分。

所以基本上你的问题是你想使用 Posix 还是 sysV 风格的共享内存?一般来说,大多数人都着眼长远并选择 Posix,因为这似乎是通向未来的道路。但是,实际上,sysV 的东西是如此嵌入在如此多的系统中,你不得不严重怀疑它是否会消失。

所以,消除长期的东西,归根结底是什么对你的项目和你的品味有意义。一般来说,sysV 版本实际上往往更强大,但它们的界面很笨拙,大多数人在第一次接触时会觉得有点困惑。 sysV 信号量和消息队列尤其如此。就共享内存而言,可以说 sysV 和 posix 都很尴尬。 sysV 版本带有笨重的ftok 和关键的东西,而 posix 最终会接受多个调用和一些竞争条件来设置。从外部看,posix 版本的优势在于它们利用文件系统并且可以使用标准命令行函数(如“rm”)进行维护,而不是依赖 sysV 所需的单独实用程序(例如 ipcs)。

那么你应该使用哪个?作为一项规则,posix 版本。但是您应该真正熟悉 sysV 版本。它们具有超出 posix 版本功能的一些功能,您可能希望在特定情况下利用这些功能。

【讨论】:

您能解释一下为什么您认为 System V 版本更强大吗? 强大可能是错误的词。也许是富勒的特色?例如 sysv 信号量范围从正数到负数,可以添加或减去,可以在进程死亡时撤消操作,可以报告对它们进行操作的最后一个进程(如果将其扩展到报告线程会更有用),存在于内核中,因此您不必弄乱共享内存,您可以一次创建一整套它们。 sysv MQ 具有 msgtypes 允许许多进程轻松共享同一个队列并只处理特定类型。 Posix MQs 总是读取最旧的 msg w/i 优先级

以上是关于Linux 共享内存:shmget() 与 mmap()?的主要内容,如果未能解决你的问题,请参考以下文章

Linux C语言进程间通信 共享内存(Shared Memory)shmget()shmat()shmdt()shmctl() ipcs -mipcrm -m

linux 共享内存 shmat,shmget,shmdt,shmctl

Linux进程间通信 -- 共享内存 shmget()shmat()shmdt()shmctl()

linux两个进程间共享内存通信都需要调用shmget函数么

linux下通过shmget创建的共享内存,是属于用户空间还是内核空间?

SystemV标准的Linux进程间通信共享内存