繁体   English   中英

如何正确启动进程并转发stdin / stdout / stderr?

[英]How do I correctly launch a process and forward stdin/stdout/stderr?

我正在使用CreateProcess启动交互式脚本解释器,并希望透明地从解释器转发stdin / stdout / stderr。

我的第一次尝试是设置传递给CreateProcessSTARTUPINFO结构,例如

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调用。

我怀疑这可能会矫kill过正,所以我想知道:有没有更简单的方法可以做到这一点? 我根本不需要对从/从脚本解释器传递的数据进行任何形式的处理。

附带说明一下,在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);

ReadFileWaitForMultipleObjects将需要在循环中调用。 您检查WaitForMultipleObjects的返回值以了解哪个操作已完成,使用GetOverlappedResult查找该操作的结果(是否成功,以及是否成功,检索到了多少个字节),处理数据,并在以下情况下再次调用ReadFile进行处理:您想从中了解更多信息,然后回到等待状态。 这有点类似于Linux中select驱动的非阻塞I / O循环。

I / O完成端口是更高级的技术。 这使一个线程池可以处理大量异步I / O。 通常用于Web服务器等,可能对您的情况有些大材小用。

如果确保不要在CreateProcessdwFlags参数中传递CREATE_NO_WINDOW参数,则按OP所示弹出STARTUPINFO效果很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM