当尝试打开一个命名管道的 StreamWriter 时,Mono 卡住了。

10

我正在编写的程序在Linux中使用FIFO管道进行进程间通信。这种方法可能不太正常,但无论如何我仍然遇到了一些问题。

        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!");
        }

我所做的只是检查管道是否已经存在,如果不存在则调用mkfifo来创建它。这部分似乎运行良好,命名管道被正确创建。但每当我尝试打开它们(使用StreamWriter、StreamReader或两者同时),程序就会挂起。没有错误或任何提示。在调试器中也是如此。

最好的部分是...它曾经可以工作。我曾经让进程间通信工作了,然后它就突然停止了。我注释掉了除了你在这里看到的之外的所有内容,重新启动了系统,重新创建了管道等等,但无济于事。怎么回事?我的代码有问题还是系统上其他东西在干扰?


6
我不知道这是否能对您有所帮助,但我曾经遇到过将路径拼接在一起的问题。有一天它可以用,而另一天却不行!对我来说解决方案是使用 Path.Combine(...) 方法连接路径,这样就可以避免不一致的行为。 - jason.kaisersmith
1个回答

3

这是有意设计的。请尝试以下操作:打开两个bash终端,创建一个管道,在其中一个终端中读取它,在另一个终端中写入它。例如:

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

>cat test.fifo

你会发现,无论顺序如何,每一方都会阻塞等待另一方。

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

解决这个问题的一种方法是将读取器或写入器运行在单独的线程中。这样,进程1和2都打开两个管道,死锁问题就得以解决。

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

如何在命名管道(C#)上进行非等待写操作?

在Mono中使用NamedPipeServerStream

基本上把NamedPipeServerStream传递给读取器/写入器即可。

我怀疑之前它能够工作是因为P1先打开了Reader,然后打开了Writer,而P2则是先打开了Writer,再打开了Reader,从而解除了P1的阻塞。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接