如何正确启动进程并转发 stdin/stdout/stderr
How do I correctly launch a process and forward stdin/stdout/stderr?
我正在使用CreateProcess
来启动交互式脚本解释器,并希望透明地将stdin/stdout/stderr转发到解释器。
我的第一次尝试是设置传递给CreateProcess
的STARTUPINFO
结构,例如
STARTUPINFOA si = { sizeof( si ) };
si.hStdError = ::GetStdHandle( STD_ERROR_HANDLE );
si.hStdOutput = ::GetStdHandle( STD_OUTPUT_HANDLE );
si.hStdInput = ::GetStdHandle( STD_INPUT_HANDLE );
si.dwFlags |= STARTF_USESTDHANDLES;
即我试图使脚本解释器进程使用与我的启动器进程相同的句柄进行读取/写入。不过这似乎不起作用(我什至不确定这些标准句柄是否可以继承)。
基于使用重定向输入和输出创建子进程示例的第二个想法是设置三个管道以转发写入任何管道的所有数据。由于我不知道如何等待数据写入多个文件(WaitForMultipleObjects
无法在管道上同步),因此我正在考虑使用三个线程,每个线程都在管道上执行阻塞ReadFile
调用。
我怀疑这可能是矫枉过正,所以我想知道:有没有更简单的方法可以做到这一点?我根本不需要对从/传递到脚本解释器的数据进行任何类型的处理。
作为旁注,在 Linux 上,我使用 execvp
仅将当前进程替换为脚本解释器进程,但在 Windows 上,我需要在主线程处于挂起状态的情况下启动脚本解释器(以便我可以做一些字节码修补) - 所以即使_execvp似乎在 Windows 上可用, 我不得不使用CreateProcess。
为了等待多个文件或管道上的 I/O,您可以在其中每个文件上发出异步 I/O 请求,然后等待所述请求的完成。类似这些内容(未经测试):
HANDLE file1, file2; // initialized somehow
HANDLE events[2];
events[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
events[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
OVERLAPPED overlapped1 = {0};
overlapped1.hEvent = events[0];
OVERLAPPED overlapped2 = {0};
overlapped2.hEvent = events[1];
ReadFile(file1, buffer1, size1, NULL, &overlapped1);
ReadFile(file2, buffer2, size2, NULL, &overlapped2);
WaitForMultipleObjects(2, events, FALSE, INFINITE);
ReadFile
和 WaitForMultipleObjects
需要在循环中调用。检查 WaitForMultipleObjects
的返回值以了解哪个操作已完成,使用 GetOverlappedResult
发现该操作的结果(是否成功,如果是,则检索了多少字节),处理数据,如果要从中读取更多内容,请再次调用该句柄的 ReadFile
,然后返回等待。这有点类似于 Linux 中由 select
驱动的非阻塞 I/O 循环。
更高级的技术是 I/O 完成端口。这允许人们有一个线程池处理大量的异步 I/O.通常用于 Web 服务器等,对于您的情况来说可能矫枉过正。
确保不在 CreateProcess
的dwFlags
参数中传递 CREATE_NO_WINDOW
参数,则按 OP 所示弹出STARTUPINFO
可以正常工作。
- 当使用带有stdin和stdout重定向的双进程管道时,如何避免stdin上的重复输入
- stdin,stdout,stderr是如何关闭的
- 通过stdin/stdout和qdatastream与Qprocess进行通信
- QT控制台:记录所有stdin和stdout要文件
- 将Stdout重定向到另一个程序的Stdin
- 为什么 read() 在管道连接到使用 boost::asio for STDIN/STDOUT 的程序时,使用 EAG
- 从C/C++调用Objective C stdin/stdout管道时,它是如何工作的
- stdout and stdin relationships
- 在c++中重定向bash stdin和stdout
- C++Eclipse:stdin位于与stdout不同的控制台中
- C++启动一个脚本(bash,python..)并使用stdin/stdout进行datatransfare [linu
- 测试使用 tty stdin 和 stdout 的程序
- C/C++服务器,通过stdin/stdout与客户端通信(阻塞stdin,直到读取了大量字节)
- 如何正确启动进程并转发 stdin/stdout/stderr
- 如何在c++中运行应用程序,并在windows中向其stdin写入和从其stdout读取
- 仅重定向子进程stdin,并从stdout和stderr中删除数据
- 如何用Qt 5.7初始化stdout stdin
- StdIn / StdOut / StdErr重定向到WinSock连接
- NodeJS-C/C++插件通信(stdin-stdout)
- 重定向标准I/O: freopen + stdin/stdout vs open + dup2