2012-01-16 160 views
1

我想使用除stdin,stdout和stderr之外的管道与子进程进行通信。我正在尝试为此使用Mono.Unix.UnixPipes.CreatePipes。但是,我找不到任何示例,我对如何使用它的最佳猜测不起作用。看来我用Process.Start创建的子进程无法写入继承的文件句柄。我想知道它是否实际上没有继承柄。这是我的(减少)代码:如何正确使用Mono.Unix.UnixPipes.CreatePipes?

using System; 
using System.Diagnostics; 
using System.IO; 
using System.IO.Pipes; 
using System.Threading; 
using System.Collections.Generic; 
using Mono.Unix; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     if (args.Length==0) 
     { 
      InvokeChildProcess(args); 
     } 
     else 
     { 
      RunAsChildProcess(args); 
     } 
    } 
    static int InvokeChildProcess(string[] aArgs) 
    { 
     var childToParentPipe = Mono.Unix.UnixPipes.CreatePipes(); 
     var childToParentStream = childToParentPipe.Reading; 
     string childHandle = childToParentPipe.Writing.Handle.ToString(); 
     var startInfo = new ProcessStartInfo(
      System.Reflection.Assembly.GetExecutingAssembly().Location, 
      childHandle) 
      { 
       UseShellExecute = false, 
      }; 
     Process childProcess = Process.Start(startInfo); 
     childToParentPipe.Writing.Close(); 
     using (var reader = new StreamReader(childToParentStream)) 
     { 
      Console.WriteLine("[PARENT] Waiting for child output..."); 
      string output = reader.ReadToEnd(); 
      Console.Write("[PARENT] Received output ({0} chars): ", output.Length); 
      Console.WriteLine(output); 
      Console.WriteLine("[PARENT] Waiting for child to exit..."); 
      childProcess.WaitForExit(); 
      Console.WriteLine("[PARENT] Saw child exit with code {0}.", childProcess.ExitCode); 
      return childProcess.ExitCode; 
     } 
    } 
    static void RunAsChildProcess(string[] args) 
    { 
     int handle=int.Parse(args[0]); 
     Console.WriteLine("[CHILD] Writing to file handle {0}.", handle); 
     var pipeToParent = new Mono.Unix.UnixStream(handle); 
     Thread.Sleep(2000); 
     using (var writer = new StreamWriter(pipeToParent)) 
     { 
      writer.WriteLine("Message from child."); 
      writer.Flush(); 
      Environment.Exit(123); 
     } 
    } 
} 

下面是输出在运行时:

[email protected]:~/dev$ mono MinimalPipeTest.exe 
[PARENT] Waiting for child output... 
[PARENT] Received output (0 chars): 
[PARENT] Waiting for child to exit... 
[CHILD] Writing to file handle 4. 

Unhandled Exception: System.ArgumentException: Can not write to stream 
    at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0 
    at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0 
    at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream) 
    at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0 
    at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Can not write to stream 
    at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0 
    at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0 
    at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream) 
    at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0 
    at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[PARENT] Saw child exit with code 1. 
[email protected]:~/dev$ 

这个例子是编译和单2.10运行分布式在Ubuntu解梦。

我在做什么错?我如何确保子进程能够写入管道?


编辑 - 它看起来像的Process.Start确实关闭所有的文件描述符,在子进程除0,1和2在这里看到的CreateProcess:

https://github.com/mono/mono/blob/master/mono/io-layer/processes.c#L988

for (i = getdtablesize() - 1; i > 2; i--) { 
    close (i); 
} 

我想这意味着我不能使用UnixPipes和Process.Start。有另一种方法吗?

+0

这取决于你想达到什么。 Process.Start并不能保证新创建的进程是子进程,即使子进程的概念完全存在 - 毕竟它必须是跨平台的。您可以创建线程并使用未命名的管道进行通信,但这是您需要的吗? – 2012-01-16 16:21:17

回答

0

据我所知,你不能在这里双向使用管道。换句话说,你不能用同一个管道读写。你需要两个。

+0

我不相信我在这里双向使用管道。 CreatePipes创建两个文件描述符,一个称为Reading,一个称为Writing。父进程从Reading读取,子进程写入Writing。 – Weeble 2012-01-16 14:32:29