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
创建您的孩子,那么mmap
和MAP_ANONYMOUS | MAP_SHARED
是迄今为止最简单的方法 - 只需一个电话。 MAP_ANONYMOUS
是一个 Linux 扩展 not specified by POSIX。
如果您独立启动进程,但可以为它们提供共享内存名称,则 shm_open
(+ ftruncate
) + mmap
和 MAP_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函数么