【问题标题】:What is the most efficient way to exchange high volume data between 2 process?在两个进程之间交换大量数据的最有效方法是什么?
【发布时间】:2012-05-20 08:38:20
【问题描述】:

最近我正在为DVR 构建软件。

它将安装在插入了 2 个或更多 PCIE x4 视频编码卡的 x86 pc 服务器上。

我们有两个独立的过程,一个必须从这些编码器卡中获取编码的视频数据,另一个必须将这些数据保存到硬盘驱动器。为什么我们有2个过程?一些历史问题。

那么,我们应该使用什么样的 IPC?套接字、管道还是共享内存?

目前我们正在使用套接字。

【问题讨论】:

  • 我会投票支持共享内存,因为它的开销最小。您将不得不实现某种循环缓冲区(我认为 boost 有一个)。

标签: linux


【解决方案1】:

使用 Linux 上的管道,您可以使用 splice 功能将数据从一个进程零拷贝移动到另一个进程。例如,发送进程使用vmsplice()SPICE_F_GIFT 将数据赠送到管道中,然后接收进程使用splice()SPLICE_F_MOVE 将数据直接从管道移动到磁盘文件中而不接触它。请注意,这自然有一些对齐和长度限制。

根据您的编码器卡驱动程序的工作方式,您可能可以安排从驱动程序到磁盘的整个过程中的零复制 - 编码器卡 DMA 进入内存,磁盘 DMA 将其返回,而无需CPU 需要查看它(在这种情况下,您将 splice() 将编码器卡中的数据输入管道,然后 splice() 将其从管道返回到磁盘文件)。

【讨论】:

  • 我没有考虑 DMA,因为我知道驱动程序不支持它。
  • 尽管如此,磁盘几乎可以肯定,所以它仍然是一个胜利。复制越少越好。
  • @caf:我不明白如何使用vmsplice 实现零拷贝移动。我在 stackoverflow 上问了这个特殊的问题,但到目前为止没有得到任何有用的答案:stackoverflow.com/q/10639559/1305501
  • @nosid:在这个特定问题的上下文中,接收过程会将复制的数据写入磁盘文件。所以我的建议是发送进程使用vmsplice(SPLICE_F_GIFT)将数据拼接到管道中,接收进程使用splice(SPLICE_F_MOVE)将天赋页面直接移动到磁盘文件。您是对的,如果您希望接收进程的地址空间中的数据当前涉及副本(它仍然比普通的read()/write() 管道案例更好,因为它是一个副本而不是两个副本)。
【解决方案2】:

使用 IPC:

  • 一个共享内存区域:两个进程之间的低开销共享缓冲区(请参阅 shmat())。
  • 一个信号量:它的计数器将是可用的帧数(请参阅 semop())。从摄像头抽取视频数据的过程会将一个帧放入共享内存区域,然后将 put() 放在信号量上。将帧记录到磁盘的进程将在信号量上获取(),并且帧将在共享内存中。

这有点像用信号量作为计数器来实现队列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多