3

我有一个应用程序,生产者和消费者(“客户”)想要相互发送广播消息,即n:m关系。所有这些都可能是不同的程序,因此它们是不同的进程而不是线程。

为了减少n:m到更易于维护的东西,我正在考虑一个设置,比如引入一个小的中央服务器。该服务器将提供一个套接字,每个客户端都可以连接到该套接字。
每个客户端都会通过该套接字向服务器发送一条新消息 - 导致1:n.

服务器还将提供对客户端只读的共享内存。它将被组织为一个环形缓冲区,新消息将由服务器添加并覆盖旧消息。 这会给客户一些时间来处理消息 - 但如果它太慢,那就是运气不好,无论如何它都不再相关了......

我看到这种方法的优点是我避免了同步以及不必要的数据复制和缓冲区层次结构,中央一个应该就足够了,不是吗?

到目前为止,这就是架构 - 我希望它有意义......

现在到了实现它的更有趣的方面:
​​环形缓冲区中最新元素的索引是共享内存中的一个变量,客户端只需等待它发生变化。而不是愚蠢的while( central_index == my_last_processed_index ) { /* do nothing */ }我想释放 CPU 资源,例如通过使用pthread_cond_wait().

但这需要一个我认为我不需要的互斥锁——另一方面,为什么 pthreads 的条件变量函数需要一个互斥锁?给我的印象是我最好问问我的架构是否有意义并且可以这样实现......

如果所有这些都有意义并且可行,你能给我一个提示吗?

(旁注:客户端程序也可以用 Perl 和 Python 等通用脚本语言编写。因此与服务器的通信必须在那里重新创建,因此不应该太复杂甚至专有)

4

3 回答 3

3

如果内存服务,互斥锁伴随条件变量的原因是在 POSIX 下,向条件变量发出信号会导致内核唤醒条件变量上的所有等待者。在这些情况下,消费者线程需要做的第一件事就是检查是否有东西要消费——通过访问生产者和消费者线程之间共享的变量。互斥锁防止并发访问用于此目的的变量。这当然意味着如果有很多消费者,其中 n-1 个是不必要的唤醒。

已经精确地实现了上述安排,要使用的 IPC 对象的选择并不明显。我们在不同进程中的高优先级实时线程之间缓冲音频,并且不想阻塞消费者。由于音频是实时制作和消费的,我们已经在两端定期安排,如果没有消费(或制作空间),我们就会丢弃数据,因为我们已经错过了最后期限。

在您描述的安排中,您将需要一个互斥锁来防止消费者同时消费排队的项目(相信我,在轻负载的 SMP 系统上,他们会)。但是,您也不需要让制作人对此进行争论。

我不明白您对消费者对共享内存具有只读访问权限的评论。在经典的无锁环形缓冲区实现中,生产者写入队列尾部指针,消费者写入头部 - 而所有各方都需要能够读取两者。您当然可以将队列头和尾安排在与队列数据本身不同的共享内存区域中。

另请注意,在实现诸如此类的环形缓冲区时,SMP 系统存在理论上的数据一致性风险 - 即相对于头或尾指针的队列内容回写到内存可能会发生乱序(它们在缓存 - 通常是每个 CPU 内核)。这个主题还有其他变体与 CPU 之间的缓存同步有关。为了防止这些,你需要一个内存、加载和存储屏障来强制排序。请参阅Wikipedia 上的内存屏障。您可以通过使用互斥锁和条件变量等内核同步原语来显式避免这种危险。

C11 原子操作可以帮助解决这个问题。

于 2012-08-03T23:05:01.973 回答
2

据我所知,您确实需要 pthread_cond_wait() 上的互斥锁。原因是 pthread_cond_wait() 不是原子的。条件变量在调用过程中可能会发生变化,除非它受到互斥锁的保护。

您可以忽略这种情况 - 客户端可能会在消息 1 之后休眠,但是当发送后续消息时,客户端将醒来并找到两条要处理的消息。如果这是不可接受的,则使用互斥锁。

于 2012-08-04T03:30:46.347 回答
2

sem_t如果您的系统有它们,您可能可以通过使用它们来进行一些不同的设计;一些 POSIX 系统仍然停留在 2001 版本的 POSIX 上。

您可能并不强制需要互斥锁/条件对。这就是很久以前为 POSIX 设计的方式。

现代 C、C11 和 C++、C++11 现在为您带来(或将为您带来)原子操作,这是在所有现代处理器中实现的功能,但缺乏大多数高级语言的支持。原子操作是解决您想要实现的环形缓冲区竞争条件的答案的一部分。但它们还不够,因为使用它们你只能通过轮询进行主动等待,这可能不是你想要的。

作为 POSIX 的扩展,Linux 的futex解决了这两个问题:通过使用原子操作避免更新竞争以及通过系统调用使服务员进入睡眠状态。Futex 通常被认为对于日常编程来说太低级了,但我认为使用它们实际上并不太难。我在这里写了一些东西。

于 2012-08-03T22:07:07.380 回答