【问题标题】:Sharing memory mappings under LinuxLinux下共享内存映射
【发布时间】:2012-09-08 11:53:35
【问题描述】:

动机

我想编写一对程序,其中一个程序读取数据并将其转换为内部格式,另一个程序将内部格式转换为其他格式。作为练习,我想在不使用管道的情况下编写这些程序之间的交互。我更喜欢使用信号和共享内存。

我想要什么

我有程序 A 和 B,A 调用 B。我该怎么做

  1. 从程序 A 创建一个内存块
  2. 从程序 A 调用程序 B,为其提供有关在何处找到内存块的信息
  3. 使用两个程序中的内存块。

更具体地说,A 解码自定义视频格式并将单个未压缩帧放入共享缓冲区。 B 从缓冲区中读取数据并将其编码为输出流。解码器每秒解码高达 100 帧,这大约是 500 MiB/s 的内存流量。管道变得很慢,因为必须经常复制数据并且缓冲区不是很大。

我认为可行的方法

我的想法是使用mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0) 创建一段共享内存。问题是,execve(2) 的联机帮助页指出:

不保留内存映射 (mmap(2))。

那么,我怎样才能与其他程序共享该内存?将这两种功能都放在一个程序中并改用fork 是不是更好?

【问题讨论】:

  • 你应该把它作为一个学习练习,但请注意,让事情在共享状态下工作,特别是共享内存,太难了,即使付出高昂的代价也应该避免。无论如何,内存共享可能会更加昂贵。作为一个友好的警告:)
  • @Magnus 你认为应该怎么做?共享状态是未压缩像素数据的两个缓冲区。一个进程解码图像,另一个进程编码。由于 512 字节的缓冲区太小,因此使用管道被证明可以完全消除并行性。
  • 这作为一个练习很好,但共享内存通常是一个非常糟糕的主意。您可能会查看更高级别的 IPC,例如套接字、命名管道或零 MQ。
  • 大数据并不疯狂。例如,SkypeKit 使用共享内存进行视频传输,因为它提供了高吞吐量而没有其他 IPC 机制的开销。
  • @nneonneo 我添加了一段关于数据大小的段落。

标签: c linux memory-mapping execve


【解决方案1】:

*nix 系统有几个共享内存的 API:

  • BSD:使用mmap()。要在不相关的进程之间共享内存,请将其关联到一个文件。您还可以使用MAP_ANONYMOUS 和fork()ing 在相关进程之间共享内存(但请确保使用-1 作为fd 以实现可移植性)。
  • System V:(有些人真的不喜欢这个)使用shmget()创建/获取对共享内存区域的引用,通过shmat()附加到它,通过shmdt()分离, 用shmctl() 标记删除。您可以通过一个键来标识共享内存区域,该键应该是唯一的。
  • POSIX:使用返回的文件描述符中的shm_open() 然后mmap()。

【讨论】:

  • 文件支持 mmap() 用于共享内存不仅适用于 BSD,它也是 POSIX。使用MAP_SHARED 映射,共享对象位于RAM 中,只有在调用msync() 或内存压力很大且映射最近未访问页面时才会将页面刷新到磁盘。就个人而言,我发现文件上的mmap(..,MAP_SHARED,..) 是最佳选择,尤其是在处理大量数据的情况下。
猜你喜欢
  • 1970-01-01
  • 2019-05-08
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2011-01-16
相关资源
最近更新 更多