使用命名管道模拟流程替换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用命名管道模拟流程替换相关的知识,希望对你有一定的参考价值。
我正在尝试在.NET中启动子进程并将其输出重定向到命名管道。尝试在子进程中写入stdout应该阻塞,直到客户端实际从命名管道读取为止。
这是我的代码:
using System;
using System.Diagnostics;
using System.IO.Pipes;
namespace psub
{
class Program
{
static void Main(string[] args)
{
var pipeName = "testpipe"; // Guid.NewGuid().ToString();
Console.WriteLine($@"\.pipe{pipeName}");
var psi = new ProcessStartInfo()
{
FileName = "ping",
Arguments = "google.com",
UseShellExecute = false,
RedirectStandardOutput = true
};
using (var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.Out))
using (var process = new Process { StartInfo = psi })
{
pipeServer.WaitForConnection();
process.Start();
process.StandardOutput.BaseStream.CopyTo(pipeServer);
process.WaitForExit();
}
}
}
}
当我启动这个可执行文件时,它按照预期在pipeServer.WaitForConnection();
上阻塞。然后我打开一个cmd.exe
并运行type \.pipe estpipe
,尝试从命名管道中读取[1]。
这会导致以下错误(在cmd会话中):
All pipe instances are busy.
此外,在C#程序中,pipeServer.WaitForConnection
完成,执行进行到...CopyTo(pipeServer)
,它爆炸:
Unhandled Exception: System.IO.IOException: Pipe is broken.
我不明白为什么All pipe instances are busy.
错误正在发生。
根据我的理解,有一个服务器(在C#程序中实例化)将写入命名管道。执行到达CopyTo
后,数据将被传送到程序的单个被阻塞线程上的命名管道服务器。
还有一个命名管道客户端(type \.pipe estpipe
进程),它将减轻服务器尝试写入的数据的命名管道。
那么为什么会出现“所有管道实例都很忙”的错误呢?
我没有成功地将new NamedPipeServerStream(pipeName, PipeDirection.Out)
调整到new NamedPipeServerStream(pipeName, PipeDirection.Out, 2)
,以及其他调整,但没有真正理解问题是什么或如何解决它。有人可以像我五岁那样解释一下吗?
[1]:目标是模拟UNIX shell中可用的process substitution功能,因此我必须能够从\.pipe<some file name>
读取,而不是使用C ++或.NET来实例化管道的客户端。
当你在cmd中使用type <some_file_name>
时 - 它首先为GetFileAttributes
调用<some_file_name>
GetFileAttributes
内部(内核)临时打开文件,用于查询它的属性(真的 - 需要查询文件系统设备,用于发送查询请求 - 需要打开文件)。
对于命名管道文件,这会产生致命的副作用 - 服务器端已连接(在打开文件上)并且只是断开连接(关闭时)。
只有在此命令(再次)打开文件后
但您的管道服务器已经没有监听(断开连接后)。结果cmd通常接收STATUS_PIPE_NOT_AVAILABLE
错误 - 在侦听状态下找不到命名管道的实例。 - 它转换为win32错误ERROR_PIPE_BUSY
- 所有管道实例都很忙
作为单独的注释 - 3种不同的状态错误:
STATUS_INSTANCE_NOT_AVAILABLE
(已达到最大命名管道实例计数。)
STATUS_PIPE_NOT_AVAILABLE
(在侦听状态下找不到命名管道的实例。)
和STATUS_PIPE_BUSY
翻译成相同的单win32错误ERROR_PIPE_BUSY
。但在你的情况下,原始错误恰恰是STATUS_PIPE_NOT_AVAILABLE
结论 - cmd type
命令不设计与管道交互。或者作为替代方案,您需要创建最小2个管道在同一管道名称上的结尾。
对于Windows命名管道,您无法通过命令行界面进行访问。有关更多信息,请参阅http://en.wikipedia.org/wiki/Named_pipe
以上是关于使用命名管道模拟流程替换的主要内容,如果未能解决你的问题,请参考以下文章
dotnet 替换 ASP.NET Core 的底层通讯为命名管道的 IPC 库