我的教科书中有以下两个C文件。
第一个文件是写入子进程的父进程
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#define BUFFER_SIZE 25
int main(void) {
HANDLE ReadHandle, WriteHandle;
STARTUPINFO si;
PROCESS_INFORMATION pi;
char message[25] = "Hello";
DWORD written;
/* set up security attributes allowing pipes to be inherited */
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
/* allocate memory */
ZeroMemory(&pi, sizeof(pi));
/* create the pipe */
if (!CreatePipe(&ReadHandle, &WriteHandle, &sa, 0)) {
fprintf(stderr, "Create Pipe Failed");
return 1;
}
/* establish the START INFO structure for the child process */
GetStartupInfo(&si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
/* redirect standard input to the read end of the pipe */
si.hStdInput = ReadHandle;
/* don’t allow the child to inherit the write end of pipe */
SetHandleInformation(WriteHandle, HANDLE_FLAG_INHERIT, 0);
/* create the child process */
CreateProcess(NULL, filter(), NULL, NULL, TRUE,
/* inherit handles */ 0, NULL, NULL, &si, &pi);
/* close the unused end of the pipe */
CloseHandle(ReadHandle);
/* the parent writes to the pipe */
if (!WriteFile(WriteHandle, message, BUFFER_SIZE, &written, NULL))
fprintf(stderr, "\nError writing to pipe abc .\n");
/* close the write end of the pipe */
CloseHandle(WriteHandle);
/* wait for the child to exit */
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
然后为子进程:
#include <Windows.h>
#include <stdio.h>
#include <Stdlib.h>
#define BUFFER_SIZE 25
int filter() {
HANDLE ReadHandle;
char buffer[BUFFER_SIZE];
//char* buffer = malloc(sizeof(char)* (BUFFER_SIZE + 1));
//buffer[BUFFER_SIZE] = '\0';
DWORD read;
/* get the read handle of the pipe */
//ReadHandle = GetStdHandle(STD_INPUT_HANDLE);
//SetHandleInformation(ReadHandle, HANDLE_FLAG_INHERIT, 0);
ReadHandle = GetStdHandle(STD_INPUT_HANDLE);
printf("Please work!!");
/* the child reads from the pipe */
if (ReadFile(ReadHandle, buffer, BUFFER_SIZE, &read, NULL)) {
//return buffer;
printf("child read %s", buffer);
}
else
fprintf(stderr, "Error reading from pipe");
system("Pause");
return 0;
}
当我运行父进程时,我会读到子进程(无论我在提示符中输入什么内容),然后是一堆奇怪的符号(看起来像[][][][][]
行)。但是,似乎我应该接收父进程中定义的消息。我已将si.dwflags
设置为STARTF_USESTDHANDLES
,这应该允许我的si.hStdOutput
和si.hStdInput
不使用控制台,但似乎它仍在使用控制台输入缓冲区{ {1}}。
谁能告诉我为什么会这样?如何通过管道将消息发送到我的子进程而不是控制台输入缓冲区?
答案 0 :(得分:0)
当ReadFile()
退出时,buffer
不能保证以空值终止。你需要:
在打印buffer
之前添加空终止符:
char buffer[BUFFER_SIZE+1]; // <-- add space for null terminator
...
if (ReadFile(ReadHandle, buffer, BUFFER_SIZE, &read, NULL)) {
buffer[read] = 0; // <-- add the null terminator
printf("child read %s", buffer);
}
在打印read
时考虑ReadFile()
输出的buffer
值:
char buffer[BUFFER_SIZE]; // <-- null terminator not needed
...
if (ReadFile(ReadHandle, buffer, BUFFER_SIZE, &read, NULL)) {
printf("child read %.*s", read, buffer);
}
另请注意,您正在关闭父管道句柄,而无需等待确保子进程实际上已完成所有内容的读取。这可能会导致ReadFile()
失败,或者至少返回的字节数少于请求的数量。所以一定要考虑到这一点。在关闭父管道句柄之前等待子进程退出,或者通过在循环中调用ReadFile()
来确保子进程处理部分数据读取,直到收到所有预期的字节为止。
Raymond Chen的MSDN博客也提供了一些关于跨进程读/写管道的重要信息:
Be careful when redirecting both a process's stdin and stdout to pipes, for you can easily deadlock