尝试将StreamWriter打开到命名管道时Mono挂起

DWi*_*ams 10 c# linux mono pipe

我正在编写的程序是在linux中使用FIFO管道进行进程间通信.它充其量只是hacky,但无论我遇到什么问题.

        if (!File.Exists(Path.GetTempPath() + "gminput.pipe"))
        {
            ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = "/usr/bin/mkfifo", Arguments = Path.GetTempPath() + "gminput.pipe", };
            Process proc = new Process() { StartInfo = startInfo, };
            proc.Start();
            proc.WaitForExit();
        }
        if (!File.Exists(Path.GetTempPath() + "gmoutput.pipe"))
        {
            ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = "/usr/bin/mkfifo", Arguments = Path.GetTempPath() + "gmoutput.pipe", };
            Process proc = new Process() { StartInfo = startInfo, };
            proc.Start();
            proc.WaitForExit();
        }

        using (StreamWriter outputPipe = new StreamWriter(Path.GetTempPath() + "gmoutput.pipe"))
        using (StreamReader inputPipe = new StreamReader(Path.GetTempPath() + "gminput.pipe"))
        {
            Console.WriteLine("This code is never reached!");
        }
Run Code Online (Sandbox Code Playgroud)

我正在做的就是检查管道是否已经存在,如果没有,请调用mkfifo来创建它.这部分似乎工作正常,命名管道是正确创建的.每当我尝试打开它们时(使用StreamWriter,StreamReader或两者),程序就会挂起.没有错误或任何东西.它也挂在调试器中.

最好的部分是...它曾经工作过.我进行了进程间通信,然后它莫名其妙地停止了.除了你在这里看到的东西,重新启动我的系统,重新创建管道等,我注释掉了所有的东西,但没有用.是什么赋予了?我的代码有问题还是系统上的其他东西干扰了?

ven*_*syv 3

这是设计使然。尝试以下操作:打开 2 个 bash 终端,创建一个管道,然后在其中一个终端中读取它并在另一个终端中写入它。例如

>mkfifo test.fifo
>echo "test" > test.fifo

>cat test.fifo
Run Code Online (Sandbox Code Playgroud)

您将看到,无论顺序如何,每一方都会阻塞等待另一方。

进程 1 的输入管道是进程 2 的输出管道,反之亦然。如果两个进程使用相同的代码访问管道,则进程 1 读取其输入管道并阻塞等待进程 2 写入内容。进程 2 也读取它的输入管道并等待进程 1 写入,但进程 1 正在等待,甚至还没有打开另一个管道。陷入僵局。

解决这个问题的一种方法是在单独的线程中运行读取器或写入器。这样进程 1 和 2 就会打开两个管道,从而解决了僵局。

另一种选择是异步打开管道。我的 C# 很生疏,但是 stackoverflow 上有很多例子:

如何在命名管道(c#)上进行非等待写入?

Mono 中的 NamedPipeServerStream

基本上将 NamedPipeServerStream 传递给读取器/写入器。

我怀疑它以前有效,因为P1打开了Reader,然后是Writer,而P2打开了Writer,然后是Reader,从而解锁了P1。