进程间通信之管道通信

管道是进程通信用的共享内存的一部分,有两种用于双向通信的管道:匿名管道和命名管道。前者使得有亲属关系的进程能传递信息,一般常用来重定向子进程的标准输入或输出,这样子进程就可以与其父进程交换数据。为了能双向通信,必须创建两个匿名管道。父进程使用管道的写句柄写入数据到第一个管道,而子进程使用管道的读句柄从第一个管道中读出数据。类似地,子进程写入数据到第二个管道,而父进程从第二个管道读取数据。匿名管道不能在网络中使用,也不能在彼此无关的进程间使用。

命名管道用来在彼此间无关的进程和不同计算机上的进程之间传输数据。一般地,命名管道服务器进程使用一个众所周知的名称或能通知给各个客户端的名称来创建一个命名管道。命名管道客户进程只要知道服务器创建的管道的名称就可以打开这个管道的另一端。当服务器和客户都连接到管道上后,他们就可以通过对管道的读写来交换数据。

CreatePipe函数创建一个匿名管道,返回两个句柄:管道读句柄和管道写句柄。读句柄对管道只有只读权限,写句柄对管道只有只写权限。为了使用管道通信,管道服务器必须传递管道句柄给另一个进程,一般这通过继承来实现。这就是说,进程允许句柄能被子进程继承。进程也可以使用DuplicateHandle函数复制一个管道句柄并使用一些进程间通信方法,比如DDE或共享内存,将管道句柄传递给一个无关的进程。

管道服务器既可以传送读句柄或写句柄给管道客户,这取决于客户使用匿名管道发送还是接收信息。为了从管道读数据,客户在ReadFile函数中使用管道的读句柄。若有另一个进程在往管道中写数据时,ReadFile函数立马返回。若管道的所有的写句柄已经被关闭或读操作完成前发生错误,ReadFile函数也立马返回。

为了往管道中写数据,在WriteFile函数中使用管道的写句柄。直到指定数量的字节被写入管道中前或错误发生时,WriteFile函数才返回。若管道缓冲区满了而还有数据要待写入,WriteFile就会等另一个进程从管道中读取出数据后,从而空出更多的缓冲区空间时才返回。管道服务器在调用CreatePipe函数时指定管道的缓冲区大小。

匿名管道不支持异步读写操作(overlapped)。这意味着你不能在匿名管道上使用ReadFileEx和WriteFileEx。此外,当使用匿名管道时,ReadFile和WriteFile的lpOverlapped参数会被忽略。

当所有的管道句柄(读句柄和写句柄)都被关闭后,匿名管道才不存在。进程可以使用CloseHandle函数来关闭管道句柄。当进程终止时,所有的管道句柄也被关闭。

匿名管道使用一个拥有唯一名字的命名管道实现,因此,对于那些需要一个命名管道句柄的函数来说,你可以传递匿名管道的句柄给它们。

管道服务器通过如下方式控制它的句柄能否被继承:

1,  CreatePipe函数接受一个SECURITY_ATTRIBUTES结构体,若管道服务器将bInheritHandle设置为TRUE,则创建的句柄可以被继承。

2,使用DuplicateHandle函数来改变一个管道句柄的继承性。

3,CreateProcess函数允许管道服务器指明子进程是否继承或不继承它所有的可继承的句柄。

当子进程继承了一个管道句柄,系统允许进程访问管道。然而,父进程必须将句柄值交流给子进程。这点父进程一般通过重定向标准输出到子进程来实现,步骤如下:

1,  调用GetStdHandle函数获取当前的标准输出句柄,保存这个句柄以便在子进程创建完后可以恢复原来的标准输出句柄。

2,  调用SetStdHandle函数设置标准输出句柄为管道的写句柄,现在父进程可以创建子进程了。

3,  调用CloseHandle函数关闭管道的写句柄,当子进程继承写句柄后,父进程就不需要它的拷贝了。

4,  调用SetStdHandle恢复原来的标准输出句柄。

子进程使用GetStdHandle函数来得到它的标准输出句柄,而现在它是管道的写端的句柄。子进程使用WriteFile函数将它的数据写到管道中,当子进程使用完管道后,它应该调用CloseHandle来关闭管道句柄或直接终止进程,后者会自动关闭句柄的。

      父进程使用ReadFile函数来从管道中接收数据。数据是以字节流的形式写入匿名句柄中的,这就意味着从管道中读数据的父进程可以在几次写数据操作中无法分辨开来,除非父子进程使用一个协议来指明写操作何时完成。当管道所有的写句柄关闭后,ReadFile函数返回0.对于父进程来说,重要的一点是,在调用ReadFile前,应该关闭管道的写端的所有句柄。若这个不做的话,ReadFile操作就无法返回0,因为父进程还有到管道写端的打开句柄。

      重定向标准输入句柄类似于重定向输出句柄,管道的读句柄作为子进程的标准输入句柄使用。这时,父进程必须确保子进程没有继承管道的写句柄。若不然,子进程的ReadFile操作无法返回0,因为子进程有到管道的写端的打开句柄。

 

以下是VB版和VC版示例代码:

'新建工程,添加两个文本框txtMessage与txtCommand.
'前者的MultLine=True,用于显示命令行程序的回显;
'后者用于输入命令.
Option Explicit

Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As Any, ByVal nSize As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Private Declare Function SetHandleInformation Lib "kernel32" (ByVal hObject As Long, ByVal dwMask As Long, ByVal dwFlags As Long) As Long
Private Declare Function SetNamedPipeHandleState Lib "kernel32" (ByVal hNamedPipe As Long, lpMode As Long, lpMaxCollectionCount As Long, lpCollectDataTimeout As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadId As Long
End Type

Private Const STARTF_USESTDHANDLES = &H100
Private Const HANDLE_FLAG_INHERIT = 1
Private Const DETACHED_PROCESS = &H8
Private Const PIPE_NOWAIT = &H1

Dim hReadPipe As Long
Dim hWritePipe As Long
Dim hChildReadPipe As Long
Dim hChildWritePipe As Long

 

'上面是公共部分.

Private Sub Form_Load()
    txtCommand.Text = ""
    txtMessage.Text = ""
    txtMessage.Locked = True
   
    ' 创建管道
    CreatePipe hReadPipe, hWritePipe, ByVal 0, ByVal 0
    CreatePipe hChildReadPipe, hChildWritePipe, ByVal 0, ByVal 0
    SetHandleInformation hWritePipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT
    SetHandleInformation hChildReadPipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT
    Dim dwMode As Long
    dwMode = PIPE_NOWAIT
    SetNamedPipeHandleState hReadPipe, dwMode, ByVal 0, ByVal 0
   
    ' 创建CMD进程
    Dim stProcessInfo As PROCESS_INFORMATION
    Dim stStartInfo As STARTUPINFO
    stStartInfo.cb = LenB(stStartInfo)
    stStartInfo.dwFlags = STARTF_USESTDHANDLES
    stStartInfo.hStdError = hWritePipe
    stStartInfo.hStdOutput = hWritePipe
    stStartInfo.hStdInput = hChildReadPipe
   
    Dim strExe As String
    strExe = "cmd"
    If False = CreateProcess(ByVal vbNullString, ByVal strExe, ByVal 0, ByVal 0, ByVal True, ByVal DETACHED_PROCESS, ByVal 0, ByVal vbNullString, stStartInfo, stProcessInfo) Then
        MsgBox "启动进程失败!"
        Exit Sub
    Else
        CloseHandle stProcessInfo.hThread
        CloseHandle stProcessInfo.hProcess
    End If
    ReadFromChildPipe
End Sub

Private Sub Form_Unload(Cancel As Integer)
    CloseHandle hReadPipe
    CloseHandle hWritePipe
    CloseHandle hChildReadPipe
    CloseHandle hChildWritePipe
End Sub

Private Sub txtCommand_KeyPress(KeyAscii As Integer)
    If KeyAscii = vbKeyReturn Then
        Dim nWrite As Long
        Dim strBuffer As String
        strBuffer = txtCommand.Text & vbCrLf
        Dim bResult As Boolean
        bResult = WriteFile(ByVal hChildWritePipe, ByVal strBuffer, ByVal Len(strBuffer), nWrite, ByVal 0)
        If bResult = True Then
            ReadFromChildPipe
        Else
            MsgBox "写入失败."
        End If
        txtCommand.Text = ""
    End If
End Sub

Private Sub ReadFromChildPipe()
    Dim nRead As Long
    Dim strBuffer As String
    Dim nBufferLen As Long
    nRead = -1
    Do While nRead <> 0
        nBufferLen = 65536
        strBuffer = String(nBufferLen, Chr(0))
        Sleep 10
        ReadFile hReadPipe, ByVal strBuffer, ByVal nBufferLen, nRead, ByVal 0
        Sleep 10
        If nRead <> 0 Then
            strBuffer = Left(strBuffer, nRead)
            txtMessage.Text = txtMessage.Text & strBuffer
            txtMessage.SelStart = Len(txtMessage.Text)
        End If
    Loop
End Sub

 

==================================C版===========================

 

父进程:

转 进程间通信之管道通信 - destiny6 - destiny6的博客#include <windows.h> 

转 进程间通信之管道通信 - destiny6 - destiny6的博客#include <tchar.h>

转 进程间通信之管道通信 - destiny6 - destiny6的博客#include <stdio.h> 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客#define BUFSIZE 4096 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客HANDLE hChildStdinRd, hChildStdinWr,  

转 进程间通信之管道通信 - destiny6 - destiny6的博客   hChildStdoutRd, hChildStdoutWr, 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   hInputFile, hStdout;

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客BOOL CreateChildProcess(VOID); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID WriteToPipe(VOID); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID ReadFromPipe(VOID); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID ErrorExit(LPSTR); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客int _tmain(int argc, TCHAR *argv[]) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   SECURITY_ATTRIBUTES saAttr; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   BOOL fSuccess; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Set the bInheritHandle flag so pipe handles are inherited. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   saAttr.bInheritHandle = TRUE; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   saAttr.lpSecurityDescriptor = NULL; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Get the handle to the current STDOUT. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Create a pipe for the child process's STDOUT. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("Stdout pipe creation failed/n"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Ensure the read handle to the pipe for STDOUT is not inherited.

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Create a pipe for the child process's STDIN. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("Stdin pipe creation failed/n"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Ensure the write handle to the pipe for STDIN is not inherited. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0);

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Now create the child process. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   

转 进程间通信之管道通信 - destiny6 - destiny6的博客   fSuccess = CreateChildProcess();

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (! fSuccess) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("Create process failed with"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Get a handle to the parent's input file. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (argc == 1) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("Please specify an input file"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   printf( "/nContents of %s:/n/n", argv[1]);

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (hInputFile == INVALID_HANDLE_VALUE) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("CreateFile failed"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Write to pipe that is the standard input for a child process. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   WriteToPipe(); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Read from pipe that is the standard output for child process. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   ReadFromPipe(); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   return 0; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客BOOL CreateChildProcess() 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   TCHAR szCmdline[]=TEXT("child");

转 进程间通信之管道通信 - destiny6 - destiny6的博客   PROCESS_INFORMATION piProcInfo; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   STARTUPINFO siStartInfo;

转 进程间通信之管道通信 - destiny6 - destiny6的博客   BOOL bFuncRetn = FALSE; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Set up members of the PROCESS_INFORMATION structure. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Set up members of the STARTUPINFO structure. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );

转 进程间通信之管道通信 - destiny6 - destiny6的博客   siStartInfo.cb = sizeof(STARTUPINFO); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   siStartInfo.hStdError = hChildStdoutWr;

转 进程间通信之管道通信 - destiny6 - destiny6的博客   siStartInfo.hStdOutput = hChildStdoutWr;

转 进程间通信之管道通信 - destiny6 - destiny6的博客   siStartInfo.hStdInput = hChildStdinRd;

转 进程间通信之管道通信 - destiny6 - destiny6的博客   siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Create the child process. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客    

转 进程间通信之管道通信 - destiny6 - destiny6的博客   bFuncRetn = CreateProcess(NULL, 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      szCmdline,     // command line 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      NULL,          // process security attributes 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      NULL,          // primary thread security attributes 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      TRUE,          // handles are inherited 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      0,             // creation flags 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      NULL,          // use parent's environment 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      NULL,          // use parent's current directory 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      &siStartInfo,  // STARTUPINFO pointer 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      &piProcInfo);  // receives PROCESS_INFORMATION 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (bFuncRetn == 0) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("CreateProcess failed/n");

转 进程间通信之管道通信 - destiny6 - destiny6的博客   else 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客   转 进程间通信之管道通信 - destiny6 - destiny6的博客{

转 进程间通信之管道通信 - destiny6 - destiny6的博客      CloseHandle(piProcInfo.hProcess);

转 进程间通信之管道通信 - destiny6 - destiny6的博客      CloseHandle(piProcInfo.hThread);

转 进程间通信之管道通信 - destiny6 - destiny6的博客      return bFuncRetn;

转 进程间通信之管道通信 - destiny6 - destiny6的博客   }

转 进程间通信之管道通信 - destiny6 - destiny6的博客}

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID WriteToPipe(VOID) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   DWORD dwRead, dwWritten; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   CHAR chBuf[BUFSIZE]; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Read from a file and write its contents to a pipe. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   for (;;) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客   转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客      if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) || 

转 进程间通信之管道通信 - destiny6 - destiny6的博客         dwRead == 0) break; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      if (! WriteFile(hChildStdinWr, chBuf, dwRead, 

转 进程间通信之管道通信 - destiny6 - destiny6的博客         &dwWritten, NULL)) break; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   } 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Close the pipe handle so the child process stops reading. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (! CloseHandle(hChildStdinWr)) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("Close pipe failed/n"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID ReadFromPipe(VOID) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   DWORD dwRead, dwWritten; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   CHAR chBuf[BUFSIZE]; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Close the write end of the pipe before reading from the 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// read end of the pipe. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if (!CloseHandle(hChildStdoutWr)) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ErrorExit("Closing handle failed"); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客// Read output from the child process, and write to parent's STDOUT. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   for (;;) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客   转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客      if( !ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead, 

转 进程间通信之管道通信 - destiny6 - destiny6的博客         NULL) || dwRead == 0) break; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL)) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客         break; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   } 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID ErrorExit (LPSTR lpszMessage) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   fprintf(stderr, "%s/n", lpszMessage); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   ExitProcess(0); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客}

转 进程间通信之管道通信 - destiny6 - destiny6的博客

子进程:

转 进程间通信之管道通信 - destiny6 - destiny6的博客#include <windows.h> 

转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客#define BUFSIZE 4096 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客VOID main(VOID) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   CHAR chBuf[BUFSIZE]; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   DWORD dwRead, dwWritten; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   HANDLE hStdin, hStdout; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   BOOL fSuccess; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   hStdin = GetStdHandle(STD_INPUT_HANDLE); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   if ((hStdout == INVALID_HANDLE_VALUE) || 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      (hStdin == INVALID_HANDLE_VALUE)) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      ExitProcess(1); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   for (;;) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客转 进程间通信之管道通信 - destiny6 - destiny6的博客   转 进程间通信之管道通信 - destiny6 - destiny6的博客

转 进程间通信之管道通信 - destiny6 - destiny6的博客   // Read from standard input. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      if (! fSuccess || dwRead == 0) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客         break; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   // Write to standard output. 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL); 

转 进程间通信之管道通信 - destiny6 - destiny6的博客      if (! fSuccess) 

转 进程间通信之管道通信 - destiny6 - destiny6的博客         break; 

转 进程间通信之管道通信 - destiny6 - destiny6的博客   } 

转 进程间通信之管道通信 - destiny6 - destiny6的博客}

 

 

更多说明在这里:http://support.microsoft.com/default.aspx/kb/190351

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值