我正在使用CreateProcess
启动交互式脚本解释器,并希望透明地将stdin / stdout / stderr转发给解释器。
我的第一次尝试是设置传递给STARTUPINFO
的{{1}}结构,如
CreateProcess
即。我试图使脚本解释器进程使用与我的启动程序进程使用的读/写相同的句柄。这似乎不起作用(我甚至不确定那些标准句柄是否可以继承)。
基于Creating a Child Process with Redirected Input and Output示例的第二个想法是设置三个管道来转发写入任何管道的所有数据。由于我不知道如何等待数据写入多个文件(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
打电话给管道。
我怀疑这可能有点矫枉过正,所以我想知道:有更简单的方法吗?我根本不需要对从/向脚本解释器传递的数据进行任何处理。
作为旁注,在Linux上我使用ReadFile
只是用脚本解释器进程替换当前进程,但在Windows上我需要启动脚本解释器,主线程处于挂起状态(所以我可以做一些字节码修补) - 所以即使因为_execvp似乎可以在Windows上使用,我显然必须使用CreateProcess。
答案 0 :(得分:4)
为了在多个文件或管道上等待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 completion ports。这允许一个线程池处理大量异步I / O.通常用于Web服务器等,可能对您的情况有些过分。
答案 1 :(得分:1)
如OP所示,填充STARTUPINFO
可以正常,如果,请确保不会在CREATE_NO_WINDOW
dwFlags
参数中传递{{1}}参数}}