多读卡器IPC解决方案?

时间:2010-05-29 17:19:39

标签: c++ ipc

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

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

我很好奇人们会建议这样的多读者解决方案?管道或域套接字的开销是否足够低,以至于我只能打开与每个读取器的连接并向每个读取器发出单独的写入?这是大量的数据(数十兆样本/秒),所以性能是必须的。

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

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

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

注1 还有其他同步问题需要维护循环队列的头/尾,以便客户知道它的位置。

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

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