【问题标题】:Multi-reader IPC solution?多读卡器 IPC 解决方案?
【发布时间】:2010-05-29 17:19:39
【问题描述】:

我正在开发一个 C++ 框架(现在只是为了好玩),它允许用户编写使用标准 API 在彼此之间传输数据的插件。将有三种基本的数据传输机制:文件、套接字和某种 IPC 管道系统。系统设置为对于非文件传输,每个流可以有多个阅读器。 IE 一旦设置了服务器套接字,多台计算机就可以连接并流式传输数据。不过,我有点卡在多阅读器 IPC 系统上。

我所有的插件都在线程中运行(尽管我最终可能想使用基于进程的系统)所以它们存在于相同的地址空间中,所以某种共享内存系统可以正常工作,我想我会用写指针编写我自己的循环缓冲区,并在缓冲区周围追逐它的读指针,但我怀疑我能否实现与 linux 管道相同的性能。

我很好奇人们对于这样的多阅读器解决方案会提出什么建议?管道或域套接字的开销是否足够低,以至于我可以打开到每个阅读器的连接并向每个阅读器发出单独的写入?这是为了处理大量数据(数十兆样本/秒),因此性能是必须的。

【问题讨论】:

  • 网络部分是否考虑过使用IP组播?
  • 这绝对是 2.0 版菜单上的内容,但我现在想专注于基本功能

标签: c++ ipc


【解决方案1】:

我开发了一个媒体服务器,我通常将单个阅读器用于同一类的一组所有活动套接字。您可以对每个组使用 select()(在阻塞或非阻塞模式下)函数来读取准备好读取的套接字。当套接字数据准备好或发生新连接时,我只需调用通知回调函数来管理它。

每个读取器(控制一组套接字)可以由一个单独的线程管理,避免您的主线程在等待新连接或套接字数据时阻塞。

【讨论】:

    【解决方案2】:

    如果我正确理解了描述,在我看来,使用您提到的循环队列将是一个很好的 IPC 解决方案。我认为它可以很好地扩展,最终会比每个客户端的单个管道或单个共享内存更好。为多个客户端使用单个队列/缓冲区的一个(几个)问题是同步对缓冲区的访问。客户端需要能够成功读取队列中的条目而服务器不更改它。这是一种可能的实现机制。

    这要求服务器知道有多少活动客户端。我认为,只要客户端在服务器上进行某种注册/登录,这是可能的(如果它们是进程内的,几乎可以肯定,但对于进程外的客户端不一定是真的)。

    • 假设有 N 个客户端。对于此示例,假设有 100 个活动客户端。
    • 为循环队列中的每个条目维护两个计数信号量。如果使用进程外客户端,则需要在进程之间共享这些客户端。调用信号量 SemReady 和 SemDone。
    • 使用 SemReady 指示缓冲区已准备好供客户端读取。服务器写入缓冲区条目,然后将信号量的值设置为客户端数量(在本例中为 100)。稍后再详细介绍。
    • 当客户端想要读取队列中的条目时,它会等待相关的 SemReady 信号量。如果初始值为 100,则所有 100 个客户端都可以成功获取信号量并“并发”读取数据。
    • 当客户端完成读取/使用条目后,它会递增/释放 SemDone 信号量。
    • 当服务器想要写入缓冲区条目时,它需要确保两件事:a) 当前没有客户端正在读取它,b) 一旦服务器写入它,就没有客户端开始读取它。
    • 因此,首先,通过等待 SemReady 信号量直到计数为零(显然,使用零超时)来阻止对缓冲区的任何进一步访问。当它达到零时,服务器知道没有其他客户端将开始读取它。
    • 要知道客户端已完成缓冲区,服务器使用 SemDone 信号量。它检查 SemDone 并等待,直到它的值等于它在 SemReady 上所做的等待次数的 N 减。换句话说,如果 SemReady 为 0,则意味着所有客户端都读取了缓冲区条目,因此,当它们完成时,SemDone 应该为 N (100)。但是,如果服务器在 SemReady 上等待了 10 次,那么当所有客户端都完成时,SemDone 应该是 90 (N-10)。
    • 上述步骤需要对客户端“活跃度”进行某种超时和状态检查,以防客户端在获得 SemReady 之后和释放 SemDone 之前崩溃/退出。此外,它还需要考虑在该步骤期间新客户端注册的可能性,以保持信号量计数值同步。
    • 一旦服务器发现没有更多的客户端正在读取缓冲区,它可以将 SemDone 重置为零,将新数据写入条目,并将 SemReady 设置为 N (100)。
    • 冲洗并重复。

    注意 1 维护循环队列的头/尾还有其他同步问题,以便客户端知道它在哪里。

    注意 2 SemDone 可能是一个用原子增量处理的整数计数器……我认为无论如何都可以。需要考虑一下。

    注意 3 让服务器中的多个线程写入缓冲区条目可能是有意义的。这样,如果服务器必须在开始读取但未完成的崩溃客户端上等待/超时,它不会阻止其他客户端可能已经在等待的后续队列条目。

    【讨论】:

      猜你喜欢
      • 2015-06-14
      • 2013-02-21
      • 2020-07-23
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 1970-01-01
      • 2011-03-24
      相关资源
      最近更新 更多