幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 5176|回复: 4

[通用编程] CRT怎么创建子进程并将其stdin/stdout重定向?

[复制链接]

23

主题

218

帖子

2470

积分

⑥精研

积分
2470
发表于 2008-4-5 15:57:45 | 显示全部楼层 |阅读模式
如题……

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

这个MSDN的例子:
  1. // crt_BeepFilter.C
  2. // arguments: crt_beeper.exe
  3. #include <windows.h>
  4. #include <process.h>
  5. #include <memory.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <fcntl.h>
  9. #include <io.h>
  10. #define   OUT_BUFF_SIZE 512
  11. #define   READ_FD 0
  12. #define   WRITE_FD 1
  13. #define   BEEP_CHAR 7
  14. char szBuffer[OUT_BUFF_SIZE];
  15. int Filter(char* szBuff, ULONG nSize, int nChar)
  16. {
  17.    char* szPos = szBuff + nSize -1;
  18.    char* szEnd = szPos;
  19.    int nRet = nSize;
  20.    while (szPos > szBuff)
  21.    {
  22.       if (*szPos == nChar)
  23.          {
  24.             memmove(szPos, szPos+1, szEnd - szPos);
  25.             --nRet;
  26.          }
  27.       --szPos;
  28.    }
  29.    return nRet;
  30. }
  31. int main(int argc, char** argv)
  32. {
  33.    int nExitCode = STILL_ACTIVE;
  34.    if (argc >= 2)
  35.    {
  36.       HANDLE hProcess;
  37.       int fdStdOut;
  38.       int fdStdOutPipe[2];
  39.       // Create the pipe
  40.       if(_pipe(fdStdOutPipe, 512, O_NOINHERIT) == -1)
  41.          return   1;
  42.       // Duplicate stdout file descriptor (next line will close original)
  43.       fdStdOut = _dup(_fileno(stdout));
  44.       // Duplicate write end of pipe to stdout file descriptor
  45.       if(_dup2(fdStdOutPipe[WRITE_FD], _fileno(stdout)) != 0)
  46.          return   2;
  47.       // Close original write end of pipe
  48.       close(fdStdOutPipe[WRITE_FD]);
  49.       // Spawn process
  50.       hProcess = (HANDLE)spawnvp(P_NOWAIT, argv[1],
  51.        (const char* const*)&argv[1]);
  52.       // Duplicate copy of original stdout back into stdout
  53.       if(_dup2(fdStdOut, _fileno(stdout)) != 0)
  54.          return   3;
  55.       // Close duplicate copy of original stdout
  56.       close(fdStdOut);
  57.       if(hProcess)
  58.       {
  59.          int nOutRead;
  60.          while   (nExitCode == STILL_ACTIVE)
  61.          {
  62.             nOutRead = read(fdStdOutPipe[READ_FD],
  63.              szBuffer, OUT_BUFF_SIZE);
  64.             if(nOutRead)
  65.             {
  66.                nOutRead = Filter(szBuffer, nOutRead, BEEP_CHAR);
  67.                fwrite(szBuffer, 1, nOutRead, stdout);
  68.             }
  69.             if(!GetExitCodeProcess(hProcess,(unsigned long*)&nExitCode))
  70.                return 4;
  71.          }
  72.       }
  73.    }
  74.    return nExitCode;
  75. }
复制代码

不明白他哪里重定向了子进程的HANDLE……
ONScripter for PSP/Windows中文版 http://blog.163.com/john_he_
回复

使用道具 举报

8

主题

215

帖子

2223

积分

⑥精研

积分
2223
发表于 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之类的地方去设置重定向参数,而是直接在父进程里创建管道,子进程会继承带有[可继承]属性的管道。
回复 支持 反对

使用道具 举报

23

主题

218

帖子

2470

积分

⑥精研

积分
2470
 楼主| 发表于 2008-4-6 16:30:10 | 显示全部楼层
这篇文章看过了(我用的是3CD版的MSDN Jan.2006)。

创建管道的地方明白,就是不明白哪里指定了子进程stdin/stdout使用的管道。是spawn函数指定的?如果是的话,假设我父进程创建了N个管道,那么子进程怎么知道要继承哪个呢?
ONScripter for PSP/Windows中文版 http://blog.163.com/john_he_
回复 支持 反对

使用道具 举报

8

主题

215

帖子

2223

积分

⑥精研

积分
2223
发表于 2008-4-6 19:23:53 | 显示全部楼层
_O_NOINHERIT的是不继承的,没有这个flag的都会被继承(吧……
回复 支持 反对

使用道具 举报

23

主题

218

帖子

2470

积分

⑥精研

积分
2470
 楼主| 发表于 2008-4-6 23:46:09 | 显示全部楼层
但如果有多个可继承的pipe呢?哪个才是子进程的stdin呢?

PS:是想调用别人的程序,所以用参数把pipe handle传进去是不可能了……
ONScripter for PSP/Windows中文版 http://blog.163.com/john_he_
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2024-4-30 06:22 , Processed in 0.026658 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表