管道技术

来源:互联网 发布:淘宝代充王者荣耀流程 编辑:程序博客网 时间:2024/04/28 07:36

CreatePipe()


近来做事接触到管道技术,精湛而精妙,让人一见三叹。所谓管道可以轻松实现不同程序进程间的数据通信。让人不得不佩
服微软的强大与卧虎藏龙,深不可测。他们可以敏锐地从现实世界发现一些本质的东西,并在技术上进行模拟从而推进技术的进步。譬如现实生活中,铁路可以说是不同城市之间的管道。有一种观点,黑洞是不同宇宙间的通道,其实也就是管道。心灵之间也有通道,是叫做“灵犀”的东西,这个李商隐同学可以作证,他说“心有灵犀一点通”。可惜他没坚持到我们来到就逃学离开了,不能进一步请教,恨哉恨哉。

 

Platform SDK: DLLs, Processes, and Threads
Creating a Child Process with Redirected Input and Output

The example in this topic demonstrates how to create a child process using the CreateProcess function from a console process. It also demonstrates a technique for using anonymous pipes to redirect the child process's standard input and output handles. Note that named pipes can also be used to redirect process I/O.


The CreatePipe function uses the SECURITY_ATTRIBUTES structure to create inheritable handles to the read and write ends of two pipes. The read end of one pipe serves as standard input for the child process, and the write end of the other pipe is the standard output for the child process. These pipe handles are specified in the STARTUPINFO structure, which makes them the standard handles inherited by the child process.

The parent process uses the other ends of the pipes to write to the child process's input and read the child process's output. The handles to these ends of the pipe are also inheritable. However, the handle must not be inherited. Before creating the child process, the parent process must use DuplicateHandle to create a duplicate of the application-defined hChildStdinWr global variable that cannot be inherited. It then uses CloseHandle to close the inheritable handle. For more information, see Pipes.


The following is the code for the parent process. It takes a single command-line argument: the name of a text file.


#include <stdio.h>
#include <windows.h>
 
#define BUFSIZE 4096
 
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
   hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
   hInputFile, hStdout;
 
BOOL CreateChildProcess(VOID);
VOID WriteToPipe(VOID);
VOID ReadFromPipe(VOID);
VOID ErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);
 
DWORD main(int argc, char *argv[])
{
   SECURITY_ATTRIBUTES saAttr;
   BOOL fSuccess;
 
// Set the bInheritHandle flag so pipe handles are inherited.
 
   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
   saAttr.bInheritHandle = TRUE;
   saAttr.lpSecurityDescriptor = NULL;
 
// Get the handle to the current STDOUT.
 
   hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 
// Create a pipe for the child process's STDOUT.
 
   if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
      ErrorExit("Stdout pipe creation failed/n");
 
// Create noninheritable read handle and close the inheritable read
// handle.

    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
        GetCurrentProcess(), &hChildStdoutRdDup , 0,
        FALSE,
        DUPLICATE_SAME_ACCESS);
    if( !fSuccess )
        ErrorExit("DuplicateHandle failed");
    CloseHandle(hChildStdoutRd);

// Create a pipe for the child process's STDIN.
 
   if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
      ErrorExit("Stdin pipe creation failed/n");
 
// Duplicate the write handle to the pipe so it is not inherited.
 
   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
      GetCurrentProcess(), &hChildStdinWrDup, 0,
      FALSE,                  // not inherited
      DUPLICATE_SAME_ACCESS);
   if (! fSuccess)
      ErrorExit("DuplicateHandle failed");
 
   CloseHandle(hChildStdinWr);
 
// Now create the child process.
  
   fSuccess = CreateChildProcess();
   if (! fSuccess)
      ErrorExit("Create process failed");

// Get a handle to the parent's input file.
 
   if (argc == 1)
      ErrorExit("Please specify an input file");

   hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,
      OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
 
   if (hInputFile == INVALID_HANDLE_VALUE)
      ErrorExit("CreateFile failed/n");
 
// Write to pipe that is the standard input for a child process.
 
   WriteToPipe();
 
// Read from pipe that is the standard output for child process.
 
   ReadFromPipe();
 
   return 0;
}
 
BOOL CreateChildProcess()
{
   PROCESS_INFORMATION piProcInfo;
   STARTUPINFO siStartInfo;
   BOOL bFuncRetn = FALSE;
 
// Set up members of the PROCESS_INFORMATION structure.
 
   ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
 
// Set up members of the STARTUPINFO structure.
 
   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
   siStartInfo.cb = sizeof(STARTUPINFO);
   siStartInfo.hStdError = hChildStdoutWr;
   siStartInfo.hStdOutput = hChildStdoutWr;
   siStartInfo.hStdInput = hChildStdinRd;
   siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
 
// Create the child process.
   
   bFuncRetn = CreateProcess(NULL,
      "child",       // command line
      NULL,          // process security attributes
      NULL,          // primary thread security attributes
      TRUE,          // handles are inherited
      0,             // creation flags
      NULL,          // use parent's environment
      NULL,          // use parent's current directory
      &siStartInfo,  // STARTUPINFO pointer
      &piProcInfo);  // receives PROCESS_INFORMATION
  
   if (bFuncRetn == 0)
      ErrorExit("CreateProcess failed");
   else
   {
      CloseHandle(piProcInfo.hProcess);
      CloseHandle(piProcInfo.hThread);
      return bFuncRetn;
   }
}
 
VOID WriteToPipe(VOID)
{
   DWORD dwRead, dwWritten;
   CHAR chBuf[BUFSIZE];
 
// Read from a file and write its contents to a pipe.
 
   for (;;)
   {
      if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
         dwRead == 0) break;
      if (! WriteFile(hChildStdinWrDup, chBuf, dwRead,
         &dwWritten, NULL)) break;
   }
 
// Close the pipe handle so the child process stops reading.
 
   if (! CloseHandle(hChildStdinWrDup))
      ErrorExit("Close pipe failed");
}
 
VOID ReadFromPipe(VOID)
{
   DWORD dwRead, dwWritten;
   CHAR chBuf[BUFSIZE];

// Close the write end of the pipe before reading from the
// read end of the pipe.
 
   if (!CloseHandle(hChildStdoutWr))
      ErrorExit("CloseHandle failed");
 
// Read output from the child process, and write to parent's STDOUT.
 
   for (;;)
   {
      if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead,
         NULL) || dwRead == 0) break;
      if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))
         break;
   }
}
 
VOID ErrorExit (LPTSTR lpszMessage)
{
   fprintf(stderr, "%s/n", lpszMessage);
   ExitProcess(0);
}

The following is the code for the child process. It uses the inherited handles for STDIN and STDOUT to access the pipe created by the parent. The parent process reads from its input file and writes the information to a pipe. The child receives text through the pipe using STDIN and writes to the pipe using STDOUT. The parent reads from the read end of the pipe and displays the information to its STDOUT.


#include <windows.h>
#define BUFSIZE 4096
 
VOID main(VOID)
{
   CHAR chBuf[BUFSIZE];
   DWORD dwRead, dwWritten;
   HANDLE hStdin, hStdout;
   BOOL fSuccess;
 
   hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
   hStdin = GetStdHandle(STD_INPUT_HANDLE);
   if ((hStdout == INVALID_HANDLE_VALUE) ||
      (hStdin == INVALID_HANDLE_VALUE))
      ExitProcess(1);
 
   for (;;)
   {
   // Read from standard input.
      fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
      if (! fSuccess || dwRead == 0)
         break;
 
   // Write to standard output.
      fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
      if (! fSuccess)
         break;
   }
}

 
原创粉丝点击