john_he 发表于 2008-4-5 15:57:45

CRT怎么创建子进程并将其stdin/stdout重定向?

如题……

嘛,用WIN32 API就会怎么搞,CreateProcess的参数里可以指定子进程stdin/stdout的HANDLE,但换CRT就不懂了……

这个MSDN的例子:
// crt_BeepFilter.C
// arguments: crt_beeper.exe

#include <windows.h>
#include <process.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

#define   OUT_BUFF_SIZE 512
#define   READ_FD 0
#define   WRITE_FD 1
#define   BEEP_CHAR 7

char szBuffer;

int Filter(char* szBuff, ULONG nSize, int nChar)
{
   char* szPos = szBuff + nSize -1;
   char* szEnd = szPos;
   int nRet = nSize;

   while (szPos > szBuff)
   {
      if (*szPos == nChar)
         {
            memmove(szPos, szPos+1, szEnd - szPos);
            --nRet;
         }
      --szPos;
   }
   return nRet;
}

int main(int argc, char** argv)
{
   int nExitCode = STILL_ACTIVE;
   if (argc >= 2)
   {
      HANDLE hProcess;
      int fdStdOut;
      int fdStdOutPipe;

      // Create the pipe
      if(_pipe(fdStdOutPipe, 512, O_NOINHERIT) == -1)
         return   1;

      // Duplicate stdout file descriptor (next line will close original)
      fdStdOut = _dup(_fileno(stdout));

      // Duplicate write end of pipe to stdout file descriptor
      if(_dup2(fdStdOutPipe, _fileno(stdout)) != 0)
         return   2;

      // Close original write end of pipe
      close(fdStdOutPipe);

      // Spawn process
      hProcess = (HANDLE)spawnvp(P_NOWAIT, argv,
       (const char* const*)&argv);

      // Duplicate copy of original stdout back into stdout
      if(_dup2(fdStdOut, _fileno(stdout)) != 0)
         return   3;

      // Close duplicate copy of original stdout
      close(fdStdOut);

      if(hProcess)
      {
         int nOutRead;
         while   (nExitCode == STILL_ACTIVE)
         {
            nOutRead = read(fdStdOutPipe,
             szBuffer, OUT_BUFF_SIZE);
            if(nOutRead)
            {
               nOutRead = Filter(szBuffer, nOutRead, BEEP_CHAR);
               fwrite(szBuffer, 1, nOutRead, stdout);
            }

            if(!GetExitCodeProcess(hProcess,(unsigned long*)&nExitCode))
               return 4;
         }
      }
   }
   return nExitCode;
}


不明白他哪里重定向了子进程的HANDLE……

rednaxela 发表于 2008-4-6 10:13:54

n order to use the _pipe function to communicate between a parent and a child process, each process must have only one handle open on the pipe. The handles must be opposites: if the parent has a read handle open, then the child must have a write handle open. The easiest way to do this is to OR (|) the _O_NOINHERIT flag with textmode. Then, use _dup or _dup2 to create an inheritable copy of the pipe handle you wish to pass to the child. Close the original handle, and spawn the child process. Upon returning from the spawn call, close the 'duplicate' handle in the parent process. See Example 2 below for more information.
http://msdn2.microsoft.com/en-us/library/aa298531.aspx

整个main函数都在做重定向的工作。与CreateProcess不一样,并不是在类似STARTUPINFO之类的地方去设置重定向参数,而是直接在父进程里创建管道,子进程会继承带有[可继承]属性的管道。

john_he 发表于 2008-4-6 16:30:10

这篇文章看过了(我用的是3CD版的MSDN Jan.2006)。

创建管道的地方明白,就是不明白哪里指定了子进程stdin/stdout使用的管道。是spawn函数指定的?如果是的话,假设我父进程创建了N个管道,那么子进程怎么知道要继承哪个呢?

rednaxela 发表于 2008-4-6 19:23:53

_O_NOINHERIT的是不继承的,没有这个flag的都会被继承(吧……

john_he 发表于 2008-4-6 23:46:09

但如果有多个可继承的pipe呢?哪个才是子进程的stdin呢?

PS:是想调用别人的程序,所以用参数把pipe handle传进去是不可能了……
页: [1]
查看完整版本: CRT怎么创建子进程并将其stdin/stdout重定向?