如何避免并行命名管道的死锁?
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 虽然有点邪恶,但比修补内核更安全、更简单!以上是关于如何避免并行命名管道的死锁?的主要内容,如果未能解决你的问题,请参考以下文章