如何避免并行命名管道的死锁?

Posted

技术标签:

【中文标题】如何避免并行命名管道的死锁?【英文标题】:how to avoid deadlock with parallel named pipes? 【发布时间】:2015-02-04 02:00:53 【问题描述】:

我正在处理a flow-based programming system called net2sh。它目前基于通过命名管道连接的 shell 工具。多个进程协同工作以完成工作,通过命名管道进行通信,这与工厂中的生产线不同。

总的来说,它运行良好,但存在一个主要问题。在进程通过两个或多个命名管道进行通信的情况下,“发送”进程和“接收”进程必须以相同的顺序打开管道。这是因为当一个进程打开一个命名管道时,它会阻塞直到另一端也被打开。

我想要一种方法来避免这种情况,无需为每个管道生成额外的“帮助”进程,无需破解现有组件,也无需为了避免此问题而弄乱程序网络。

理想情况下,我正在寻找一些“非阻塞 fifo”选项,其中 fifo 上的“open”总是立即成功,但如果管道缓冲区已满(或为空,用于读取),后续操作可能会阻塞......我' d 甚至考虑使用内核补丁来达到这种效果。根据 fifo(7) O_NONBLOCK 在打开 fifos 时确实做了一些不同的事情,而不是我想要的,为了使用它,我必须重写所有现有的 shell 工具,例如 cat。

这是一个死锁的最小示例:

mkfifo a b
(> a; > b; ) &
(< b; < a; ) &
wait

如果你能帮助我明智地解决这个问题,我将非常感激!

【问题讨论】:

【参考方案1】:

这里有一个很好的描述使用 O_NONBLOCK 和命名管道:How do I perform a non-blocking fopen on a named pipe (mkfifo)?

听起来您希望它在您的整个环境中工作而无需更改任何 C 代码。因此,一种方法是将LD_PRELOAD 设置为某个共享库,该库包含open(2) 的包装器,只要pathname 引用命名管道,就会将O_NONBLOCK 添加到flags

使用LD_PRELOAD 覆盖库函数的简明示例如下:https://www.technovelty.org/c/using-ld_preload-to-override-a-function.html

这是否真的在实践中有效而不会破坏其他任何东西,您必须自己找出答案(请告诉我们!)。

【讨论】:

谢谢,这是个好主意。我想我将不得不做一些额外的hackery,而不仅仅是添加 O_NONBLOCK 来打开,但它可能是可行的。非常感激。 LD_PRELOAD 虽然有点邪恶,但比修补内核更安全、更简单!

以上是关于如何避免并行命名管道的死锁?的主要内容,如果未能解决你的问题,请参考以下文章

带有命名管道的 WCF:如何允许并行调用?

命名管道中的 C# 死锁

如何避免命名管道中的多个作者?

linux管道(pipeline)

如何避免回显关闭 FIFO 命名管道? - Unix FIFO 的有趣行为

命名管道服务器,如何中断或超时等待客户端连接和传入数据