【发布时间】:2016-05-25 05:51:23
【问题描述】:
更新问题:所以我已经能够创建进程并编译程序。但是,我遇到了一个新问题。当我尝试将 Source 程序通过管道传输到 Filter 程序中时。它似乎没有为 sink 程序提供任何输入。没有错误信息。我还使用 Windows cmd 中的管道运算符测试了我所有的独立程序。
我正在尝试做这个小项目来了解匿名管道和创建过程。我创建了 3 个小型独立程序,分别称为 Source、Filter 和 Sink。这 3 个已经编译并且运行良好。以下是 3 个独立程序的说明。
Source:从命令行获取源文本文件文件名,打开文件,一次一个字符地读取文件内容并将其直接复制到标准输出(stdout)。复制文件后,Source 终止(关闭所有打开的文件句柄)。
过滤程序不使用任何文件名命令行参数。相反,Filter 从标准输入 (stdin) 读取文本文件,并将所有大写字母转换为小写的输入副本写入标准输出 (stdout)。过滤器具体必须设计成读取一个字符,转换它,输出它,然后循环,直到传入的数据完成。
Sink 程序从其命令行获取目标文本文件文件名,打开文件进行写入,然后从标准输入文件 (stdin) 一次读取一个字符,并将每个传入字符直接写入目标 sink 文件。
接下来,我将分别驱动一个主驱动程序,该程序创建 2 个管道并生成 3 个独立的子进程,其输入和输出配置为执行指定的并发执行和数据流。像这样的:
- srcfile -> Source -> pipe1 -> Filter -> Pipe2 -> Sink -> destfile
驱动程序需要2个命令行参数:
C:\> Driver.exe srcfile destfile
其中 srcfile 是现有的数据文本文件,而 destfile 是要由 Sink 应用程序创建的新目标文件的文件名。
这是我的驱动程序代码。它还没有完成。但是我在尝试为 Source 程序创建进程时遇到了问题。
更新代码:
#include <windows.h>
#include <WinBase.h>
#include <stdio.h>
#define DELAY_A_WHILE() {volatile long j; for(j = 1; j< 10000; j++) ; }
int main(int argc, char *argv[])
{
HANDLE hPipeRead, hPipeWrite, hPipeRead2, hPipeWrite2;
STARTUPINFO StartupInfoSource;
STARTUPINFO StartupInfoFilter;
STARTUPINFO StartupInfoSink;
PROCESS_INFORMATION ProcInfoSource;
PROCESS_INFORMATION ProcInfoFilter;
PROCESS_INFORMATION ProcInfoSink;
SECURITY_ATTRIBUTES PipeAttributes;
SECURITY_ATTRIBUTES PipeAttributes2;
char cmdline[200];
PipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
PipeAttributes.lpSecurityDescriptor = NULL; //ignore
PipeAttributes.bInheritHandle = TRUE; //child can inherit
//Create first pipe
if (!CreatePipe(&hPipeRead, &hPipeWrite, &PipeAttributes, 0)) {
fprintf(stderr, "Error creating pipe: %d\n", GetLastError());
exit(1);
}
sprintf_s(cmdline, 200, "Source.exe %s", argv[1]);
printf("Create process: %s\n", cmdline);
GetStartupInfo(&StartupInfoSource);
StartupInfoSource.dwFlags = StartupInfoSource.dwFlags | STARTF_USESTDHANDLES;
//Mapping
StartupInfoSource.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
StartupInfoSource.hStdOutput = hPipeWrite;
StartupInfoSource.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if (!CreateProcess(
NULL, cmdline, NULL, NULL,
TRUE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfoSource,
&ProcInfoSource))
{
fprintf(stderr, "Error creating child process: %d",GetLastError());
exit(1);
}
CloseHandle(hPipeWrite);
CloseHandle(ProcInfoSource.hProcess);
CloseHandle(ProcInfoSource.hThread);
PipeAttributes2.nLength = sizeof(SECURITY_ATTRIBUTES);
PipeAttributes2.lpSecurityDescriptor = NULL; //ignore
PipeAttributes2.bInheritHandle = TRUE; //child can inherit
//Create Second Pipe
if (!CreatePipe(&hPipeRead2, &hPipeWrite2, &PipeAttributes2, 0)) {
fprintf(stderr, "Error creating pipe: %d\n", GetLastError());
exit(1);
}
GetStartupInfo(&StartupInfoFilter);
StartupInfoFilter.dwFlags = StartupInfoFilter.dwFlags | STARTF_USESTDHANDLES;
//Mapping
StartupInfoFilter.hStdInput = hPipeRead;
StartupInfoFilter.hStdOutput = hPipeWrite2;
StartupInfoFilter.hStdError = GetStdHandle(STD_ERROR_HANDLE);
sprintf_s(cmdline, 200, "Filter.exe");
printf("Create process: %s\n", cmdline);
//Filter
GetStartupInfo(&StartupInfoFilter);
if (!CreateProcess(
NULL, cmdline, NULL, NULL,
TRUE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfoFilter,
&ProcInfoFilter))
{
fprintf(stderr, "Error creating child process: %d", GetLastError());
exit(1);
}
// int exitStatus;
// GetExitCodeProcess(ProcInfoFilter.hProcess, &exitStatus);
CloseHandle(hPipeRead);
CloseHandle(hPipeWrite2);
CloseHandle(ProcInfoFilter.hProcess);
CloseHandle(ProcInfoFilter.hThread);
GetStartupInfo(&StartupInfoSink);
StartupInfoSink.dwFlags = StartupInfoSink.dwFlags | STARTF_USESTDHANDLES;
//Mapping
StartupInfoSink.hStdInput = hPipeRead2;
StartupInfoSink.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
StartupInfoSink.hStdError = GetStdHandle(STD_ERROR_HANDLE);
sprintf_s(cmdline, 200, "Sink.exe %s", argv[2]);
printf("Create process: %s\n", cmdline);
GetStartupInfo(&StartupInfoSink);
if (!CreateProcess(
NULL, cmdline, NULL, NULL,
TRUE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfoSink,
&ProcInfoSink))
{
fprintf(stderr, "Error creating child process: %d", GetLastError());
exit(1);
}
CloseHandle(hPipeRead2);
CloseHandle(ProcInfoSink.hProcess);
CloseHandle(ProcInfoSink.hThread);
return 0;
}
程序编译良好。但是,当它尝试创建进程时,它总是失败并退出。 cmdline 解析时的值是“Source.exe test.txt”,这正是我用来执行我的独立源程序的。有人可以解释为什么我的CreateProcess 失败了吗?是不是因为我解析了错误的参数?
【问题讨论】:
-
所以你是说
CreateProcess失败了?然后您应该查看GetLastError返回的错误代码。顺便说一句,您传递调用进程的STARTUPINFO是否正确?这是将句柄传递给标准输入和标准输出吗? -
当我尝试调试时,程序总是执行 if(!CreateProcess()) 里面的代码块,当它创建和退出程序失败时打印错误。
标签: c winapi pipeline createprocess