(FW: From MSDN)Creating a Child Process with Redirected Input and Output

原创 2011年01月10日 14:35:00
Preface:
When programming with multi-threads and multi-process , we often come to question how to 
transfer data between threads or  proceeds, My answer is :
1. Allocate a critical space for threads under same process , and mutex on it.
2. Use anonymous Pipe for processes , goto MSDN for more info:
   http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx    

MSDN:(Build date: 2/5/2009)

Creating a Child Process with Redirected Input and Output

The example in this topic demonstrates how to create a child process using theCreateProcess 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 theSTARTUPINFO structure, which makes them the standard handles inherited by the child process.

The parent process uses the opposite ends of these two pipes to write to the child process’s input and read from the child process’s output. As specified in the STARTUPINFOstructure, these handles are also inheritable. However, these handles must not be inherited. Therefore, before creating the child process, the parent process uses theSetHandleInformation function to ensure that the write handle for the child process’s standard input and the read handle for the child process’s standard input cannot be inherited. 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.

 
1:  #include  
   2:  #include 
   3:  #include  
   4:  #include 
   5:  
   6:  #define BUFSIZE 4096 
   7:   
   8:  HANDLE g_hChildStd_IN_Rd = NULL;
   9:  HANDLE g_hChildStd_IN_Wr = NULL;
  10:  HANDLE g_hChildStd_OUT_Rd = NULL;
  11:  HANDLE g_hChildStd_OUT_Wr = NULL;
  12:  
  13:  HANDLE g_hInputFile = NULL;
  14:   
  15:  void CreateChildProcess(void); 
  16:  void WriteToPipe(void); 
  17:  void ReadFromPipe(void); 
  18:  void ErrorExit(PTSTR); 
  19:   
  20:  int _tmain(int argc, TCHAR *argv[]) 
  21:  { 
  22:     SECURITY_ATTRIBUTES saAttr; 
  23:   
  24:     printf("n->Start of parent execution.n");
  25:  
  26:  // Set the bInheritHandle flag so pipe handles are inherited. 
  27:   
  28:     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
  29:     saAttr.bInheritHandle = TRUE; 
  30:     saAttr.lpSecurityDescriptor = NULL; 
  31:  
  32:  // Create a pipe for the child process's STDOUT. 
  33:   
  34:     if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) 
  35:        ErrorExit(TEXT("StdoutRd CreatePipe")); 
  36:  
  37:  // Ensure the read handle to the pipe for STDOUT is not inherited.
  38:  
  39:     if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
  40:        ErrorExit(TEXT("Stdout SetHandleInformation")); 
  41:  
  42:  // Create a pipe for the child process's STDIN. 
  43:   
  44:     if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
  45:        ErrorExit(TEXT("Stdin CreatePipe")); 
  46:  
  47:  // Ensure the write handle to the pipe for STDIN is not inherited. 
  48:   
  49:     if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
  50:        ErrorExit(TEXT("Stdin SetHandleInformation")); 
  51:   
  52:  // Create the child process. 
  53:     
  54:     CreateChildProcess();
  55:  
  56:  // Get a handle to an input file for the parent. 
  57:  // This example assumes a plain text file and uses string output to verify data flow. 
  58:   
  59:     if (argc == 1) 
  60:        ErrorExit(TEXT("Please specify an input file.n")); 
  61:  
  62:     g_hInputFile = CreateFile(
  63:         argv[1], 
  64:         GENERIC_READ, 
  65:         0, 
  66:         NULL, 
  67:         OPEN_EXISTING, 
  68:         FILE_ATTRIBUTE_READONLY, 
  69:         NULL); 
  70:  
  71:     if ( g_hInputFile == INVALID_HANDLE_VALUE ) 
  72:        ErrorExit(TEXT("CreateFile")); 
  73:   
  74:  // Write to the pipe that is the standard input for a child process. 
  75:  // Data is written to the pipe's buffers, so it is not necessary to wait
  76:  // until the child process is running before writing data.
  77:   
  78:     WriteToPipe(); 
  79:     printf( "n->Contents of %s written to child STDIN pipe.n", argv[1]);
  80:   
  81:  // Read from pipe that is the standard output for child process. 
  82:   
  83:     printf( "n->Contents of child process STDOUT:nn", argv[1]);
  84:     ReadFromPipe(); 
  85:  
  86:     printf("n->End of parent execution.n");
  87:  
  88:  // The remaining open handles are cleaned up when this process terminates. 
  89:  // To avoid resource leaks in a larger application, close handles explicitly. 
  90:  
  91:     return 0; 
  92:  } 
  93:   
  94:  void CreateChildProcess()
  95:  // Create a child process that uses the previously created pipes for STDIN and STDOUT.
  96:  { 
  97:     TCHAR szCmdline[]=TEXT("child");
  98:     PROCESS_INFORMATION piProcInfo; 
  99:     STARTUPINFO siStartInfo;
 100:     BOOL bSuccess = FALSE; 
 101:   
 102:  // Set up members of the PROCESS_INFORMATION structure. 
 103:   
 104:     ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
 105:   
 106:  // Set up members of the STARTUPINFO structure. 
 107:  // This structure specifies the STDIN and STDOUT handles for redirection.
 108:   
 109:     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
 110:     siStartInfo.cb = sizeof(STARTUPINFO); 
 111:     siStartInfo.hStdError = g_hChildStd_OUT_Wr;
 112:     siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
 113:     siStartInfo.hStdInput = g_hChildStd_IN_Rd;
 114:     siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
 115:   
 116:  // Create the child process. 
 117:      
 118:     bSuccess = CreateProcess(NULL, 
 119:        szCmdline,     // command line 
 120:        NULL,          // process security attributes 
 121:        NULL,          // primary thread security attributes 
 122:        TRUE,          // handles are inherited 
 123:        0,             // creation flags 
 124:        NULL,          // use parent's environment 
 125:        NULL,          // use parent's current directory 
 126:        &siStartInfo,  // STARTUPINFO pointer 
 127:        &piProcInfo);  // receives PROCESS_INFORMATION 
 128:     
 129:     // If an error occurs, exit the application. 
 130:     if ( ! bSuccess ) 
 131:        ErrorExit(TEXT("CreateProcess"));
 132:     else 
 133:     {
 134:        // Close handles to the child process and its primary thread.
 135:        // Some applications might keep these handles to monitor the status
 136:        // of the child process, for example. 
 137:  
 138:        CloseHandle(piProcInfo.hProcess);
 139:        CloseHandle(piProcInfo.hThread);
 140:     }
 141:  }
 142:   
 143:  void WriteToPipe(void) 
 144:  
 145:  // Read from a file and write its contents to the pipe for the child's STDIN.
 146:  // Stop when there is no more data. 
 147:  { 
 148:     DWORD dwRead, dwWritten; 
 149:     CHAR chBuf[BUFSIZE];
 150:     BOOL bSuccess = FALSE;
 151:   
 152:     for (;;) 
 153:     { 
 154:        bSuccess = ReadFile(g_hInputFile, chBuf, BUFSIZE, &dwRead, NULL);
 155:        if ( ! bSuccess || dwRead == 0 ) break; 
 156:        
 157:        bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
 158:        if ( ! bSuccess ) break; 
 159:     } 
 160:   
 161:  // Close the pipe handle so the child process stops reading. 
 162:   
 163:     if ( ! CloseHandle(g_hChildStd_IN_Wr) ) 
 164:        ErrorExit(TEXT("StdInWr CloseHandle")); 
 165:  } 
 166:   
 167:  void ReadFromPipe(void) 
 168:  
 169:  // Read output from the child process's pipe for STDOUT
 170:  // and write to the parent process's pipe for STDOUT. 
 171:  // Stop when there is no more data. 
 172:  { 
 173:     DWORD dwRead, dwWritten; 
 174:     CHAR chBuf[BUFSIZE]; 
 175:     BOOL bSuccess = FALSE;
 176:     HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
 177:  
 178:  // Close the write end of the pipe before reading from the 
 179:  // read end of the pipe, to control child process execution.
 180:  // The pipe is assumed to have enough buffer space to hold the
 181:  // data the child process has already written to it.
 182:   
 183:     if (!CloseHandle(g_hChildStd_OUT_Wr)) 
 184:        ErrorExit(TEXT("StdOutWr CloseHandle")); 
 185:   
 186:     for (;;) 
 187:     { 
 188:        bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
 189:        if( ! bSuccess || dwRead == 0 ) break; 
 190:  
 191:        bSuccess = WriteFile(hParentStdOut, chBuf, 
 192:                             dwRead, &dwWritten, NULL);
 193:        if (! bSuccess ) break; 
 194:     } 
 195:  } 
 196:   
 197:  void ErrorExit(PTSTR lpszFunction) 
 198:  
 199:  // Format a readable error message, display a message box, 
 200:  // and exit from the application.
 201:  { 
 202:      LPVOID lpMsgBuf;
 203:      LPVOID lpDisplayBuf;
 204:      DWORD dw = GetLastError(); 
 205:  
 206:      FormatMessage(
 207:          FORMAT_MESSAGE_ALLOCATE_BUFFER | 
 208:          FORMAT_MESSAGE_FROM_SYSTEM |
 209:          FORMAT_MESSAGE_IGNORE_INSERTS,
 210:          NULL,
 211:          dw,
 212:          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 213:          (LPTSTR) &lpMsgBuf,
 214:          0, NULL );
 215:  
 216:      lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
 217:          (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); 
 218:      StringCchPrintf((LPTSTR)lpDisplayBuf, 
 219:          LocalSize(lpDisplayBuf) / sizeof(TCHAR),
 220:          TEXT("%s failed with error %d: %s"), 
 221:          lpszFunction, dw, lpMsgBuf); 
 222:      MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 
 223:  
 224:      LocalFree(lpMsgBuf);
 225:      LocalFree(lpDisplayBuf);
 226:      ExitProcess(1);
 227:  }

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 
#include 

#define BUFSIZE 4096 

int main(void)
{
   CHAR chBuf[BUFSIZE];
   DWORD dwRead, dwWritten;
   HANDLE hStdin, hStdout;
   BOOL bSuccess; 

   hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
   hStdin = GetStdHandle(STD_INPUT_HANDLE);
   if (
       (hStdout == INVALID_HANDLE_VALUE) ||
       (hStdin == INVALID_HANDLE_VALUE)
      )
      ExitProcess(1); 

   // Send something to this process's stdout using printf.
   printf("n ** This is a message from the child process. ** n");

   // This simple algorithm uses the existence of the pipes to control execution.
   // It relies on the pipe buffers to ensure that no data is lost.
   // Larger applications would use more advanced process control.

   for (;;)
   {
   // Read from standard input and stop on error or no data.
      bSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL); 

      if (! bSuccess || dwRead == 0)
         break; 

   // Write to standard output and stop on error.
      bSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL); 

      if (! bSuccess)
         break;
   }
   return 0;
}

相关文章推荐

获取MySQL加密密码并验证用户输入(登录界面),retrieve hashpwd from mysql and compare with input password on login

获取MySQL加密密码并验证用户输入(登录界面),retrieve hashpwd from mysql and compare with input password on login...

mongodb启动不了:child process failed, exited with error number 100

原文链接mongodb启动不了:child process failed, exited with error number 100 http://f.dataguru.cn/thread-1073...

mongodb启动时报错ERROR: child process failed, exited with error number 1

转 http://www.cnblogs.com/zlslch/p/6932368.html     不多说,直接上干货!         root@zhouls-virtual-machine...

MongoDB错误2_启动mongodb时遇到child process failed,existed with error number 100错误

今天在启动mongodb的时候,发现起不来,报错:child process failed, exited with error number 100然后先去/var/log/mongo/mongo...

oracle 11gR2 ORA-31626: job does not exist 和ORA-31687: error creating worker process with worker id 1 解决方法

  Oracle 11gR2 imdp 报错如下:  Import: Release 11.2.0.1.0 - Production on Mon May 3 16:25:17 2010Copyrig...

mongodb启动不了:child process failed, exited with error number 100

今天在启动mongodb的时候,发现起不来,报错:child process failed, exited with error number 100;发现—–> 然后去官方文档一查看,嗯??是的 ...

MongoDB错误1_启动mongodb时遇到child process failed,existed with error number 1错误

在进行安装配置mongodb实验时,按照以下的步骤进行:   启动mongodb: cd /usr/local/mongodb/mongodb/bin 进入每个mongodb节点的bin目录下 ./m...

【Linux运维入门】MongoDb启动报错:ERROR: child process failed, exited with error number xx

解决启动报错问题今天启动服务器的MongoDb服务时报错 出现这种错误的原因:大部分是因为mongodb 服务的不正常关闭,导致mongod 被锁,想想可能是上次服务器断电维护时,没有手动关闭Mong...

c++教程(二十五:Input/output with files)

C++提供了以下到/从文件的类执行输出和输入字符: ofstream:写文件的类; ifstream:读取文件类 fstream:读/写文件的类。 这些类都是直接或间接来自类istream和ostre...
  • on2way
  • on2way
  • 2017年02月13日 16:40
  • 740
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:(FW: From MSDN)Creating a Child Process with Redirected Input and Output
举报原因:
原因补充:

(最多只允许输入30个字)