5

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

我的第一次尝试是设置STARTUPINFO传递给CreateProcesslike的结构

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。

4

2 回答 2

5

为了在多个文件或管道上等待 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如果您想再次调用该句柄从中阅读更多内容,然后继续等待。select这有点类似于Linux 中驱动的非阻塞 I/O 循环。

更先进的技术是I/O 完成端口。这允许一个线程池处理大量异步 I/O。常用于 Web 服务器等,对于您的情况可能有点矫枉过正。

于 2013-12-17T02:22:45.270 回答
1

如果您确保不在. STARTUPINFO_ _CREATE_NO_WINDOWdwFlagsCreateProcess

于 2014-02-11T10:25:59.673 回答