0

从父进程,我试图通过标准输入/输出控制子进程。我使用以下 MSDN 示例创建子进程并重定向其标准输入和输出:http: //msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.100%29.aspx

在父端,我使用以下代码两次发送相同的“命令”:

const char cmd[] = "test\n";
DWORD written, read;
BOOL success;
success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);
success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);

在孩子方面,我通过fgets调用读取了这些命令。第一个命令按预期读取。但是当发送第二个命令时, fgets 调用返回一个空字符串,并且下一个 fgets 调用不返回。这是子进程代码:

char *retStrP;
char str[256];
size_t strLen;

retStrP = fgets(str, 256, stdin);
strLen = strlen(str);
if (retStrP != str)
{
    char errorStr[256];
    int a = feof(stdin);
    int b = ferror(stdin);
    sprintf(errorStr, "Fgets error, %d %d\n", a, b);
    OutputDebugString(errorStr);
}
else if (strLen == 0)
{
    char errorStr[256];
    int a = feof(stdin);
    int b = ferror(stdin);
    sprintf(errorStr, "Strlen is 0, %d %d\n", a, b);
    OutputDebugString(errorStr);
}

从前面的代码中,对 fgets 的第二次调用的行为如下:返回的指针等于 str 缓冲区,但 strlen 为 0。

在阅读 MSDN fgets 文档(http://msdn.microsoft.com/en-us/library/c37dh6kf%28v=vs.100%29.aspx)时,我看不出有任何方法可以将指针返回到缓冲区作为第一个参数传递,第一个缓冲区的字节设置为 0(只要缓冲区大小大于 1)。如果发生错误或到达文件末尾,fgets 应该返回 NULL 并且 feof 或 ferror 应该返回不为 0 的值。

我怀疑管道处理出了点问题,但我不知道是什么......从父方来看,除了发送相同的缓冲区两次之外,我对标准输入写入管道没有做任何事情。知道什么会导致这种行为吗?

4

2 回答 2

0

我发现了问题!

从父进程中,WriteFile 调用将 NULL 终止字符发送到管道。

因此,在第一次 WriteFile 调用之后,fgets 将字符串读取到换行符为止。然后在第二次 WriteFile 调用中,fgets 读取从前一个 NULL 终止字符到第二个换行符的字符串。它导致返回的字符串的第一个字符是 NULL 终止字符。这就是为什么 fgets 返回没有错误但字符串长度为 0 的原因。

解决方案是通过从 cmd 缓冲区大小中减去 1 来不发送 NULL 终止字符。

于 2012-11-07T17:49:29.867 回答
0

您的问题与您链接到的示例非常模糊。仍然有一些建议。

尝试这个:

while(!success)
   success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);
while(!success)
   success = WriteFile(g_hChildStd_IN_Wr, cmd, sizeof(cmd), &written, NULL);

原因:如果WriteFile()函数成功,则返回值非零 (TRUE)。如果函数失败或异步完成,则返回值为零 (FALSE)。要获取错误信息,请使用该GetLastError()函数。

在子进程的 for 循环中使用ReadFile()而不是fgets读取由 , 写入的数据。WriteFile()

如果您仍然遇到问题GetLastError(),请在您的代码中使用该功能WriteFile()ReadFile()发布您的错误代码信息。我们或许能更好地帮助您。

于 2012-11-06T18:21:41.213 回答