gpt4 book ai didi

c - 如何让 Windows Pipe 在进程完成时添加 EOF

转载 作者:行者123 更新时间:2023-11-30 16:15:33 25 4
gpt4 key购买 nike

我正在 Windows 上创建一个模拟管道的递归 C 函数。

到目前为止,这是我的功能:


static BOOL execute_in_pipe(char (*cmdline)[1024], char *env, int index,
int pipe_length, STARTUPINFO *old_suinfo, HANDLE proc_handles[])
{
//Create new startup info
STARTUPINFO suinfo;
memset(&suinfo, 0, sizeof(suinfo));
suinfo.cb = sizeof(suinfo);

//Create new process info
PROCESS_INFORMATION pinfo;

//Make pipe
HANDLE pipe_out_rd, pipe_out_wr;
if(index > 0) {
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

if (! CreatePipe(&pipe_out_rd, &pipe_out_wr, &sa, 0))
{
CloseHandle(pipe_out_wr);
CloseHandle(pipe_out_rd);
//res.tag = NATIVE_ERR_PIPE_FAILED;
//return res;
}

//Set output of last process to write handle
if((*old_suinfo).hStdInput == 0) {
(*old_suinfo).hStdInput = hIn;
}
(*old_suinfo).hStdOutput = pipe_out_wr;
(*old_suinfo).dwFlags = STARTF_USESTDHANDLES;

//Set input of this process to read handle
suinfo.hStdInput = pipe_out_rd;
if(index >= pipe_length-1) {
suinfo.hStdOutput = hOut;
}
suinfo.dwFlags = STARTF_USESTDHANDLES;
}

BOOL result = TRUE;
if(index < pipe_length-1) {
result = execute_in_pipe(cmdline, env, index+1, pipe_length, &suinfo, proc_handles);
}

//Return whether creating process succeeds
if(!CreateProcess(NULL, cmdline[index], NULL, NULL,
(pipe_length>1), 0, env, NULL, &suinfo, &pinfo))
{
return FALSE;
}

CloseHandle(pinfo.hThread);

proc_handles[index] = pinfo.hProcess;

return result;
}

我制作了两个 C 程序来测试管道:

种子.c

#include <stdio.h>

int main() {
printf("Hello");
}

追加.c

#include <stdio.h>
#include <string.h>

int main() {
char str[200];
scanf( "%s", str );

printf("%s World!", str);
}

我使用以下方法调用这些函数:

    STARTUPINFO suinfo;
HANDLE proc_handles[2];
printf("Starting\n");
char cmdline[2][1024] = {"seed.exe", "append.exe"};

execute_in_pipe(cmdline, 0, 0, 2, &suinfo, proc_handles);

WaitForMultipleObjects(2, proc_handles, TRUE, INFINITE);

调用此函数时,控制台打印出“Starting”,然后等待...永远...

我很确定原因是 scanf 正在尝试读取整行(直到某种分隔符)。当我将 Seed.c 更新为 `printf("Hello\n") 时,它工作得很好。

所以是的,这只是一条规则吗?所有管道进程都应该使用换行符吗?

好的,请调用 seed.exe | append.exe在命令提示符下效果很好!即使没有换行符!我的代码缺少什么?

编辑:正如一些人所指出的,当所有管道都关闭时,Unix 管道会遇到“End-of-Stream”(不像我最初想象的那样是 EOF)。在测试Unix管道系统时,不会出现这个问题,因此流结束符就像一个分隔符。 Windows 也做了类似的事情吗?如果是这样,我是否必须关闭某些东西才能结束流?

最佳答案

您应该使用命名管道而不是无名管道来执行 I/O 重定向。当服务器的管道句柄关闭时,客户端上的 scanf() 会知道并停止等待换行符。

下面的代码是pascal语言,但并不难理解。

const
BUFSIZE:integer = 512;
Pipename:String = '\\.\pipe\devcpp_run';

InputWrite := CreateNamedPipe(
pAnsiChar(Pipename), // pipe name
PIPE_ACCESS_OUTBOUND, // read/write access
PIPE_TYPE_BYTE or // message type pipe
PIPE_READMODE_BYTE or // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
0, // client time-out
nil); // default security attribute
if InputWrite = INVALID_HANDLE_VALUE then begin
Exit;
end;
InputRead := CreateFile(
PAnsiChar(Pipename), // pipe name
GENERIC_READ,
0, // no sharing
@sa, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
0);
if InputRead = INVALID_HANDLE_VALUE then begin
Exit;
end;
StartupInfo.dwFlags := StartupInfo.dwFlags or STARTF_USESTDHANDLES;
StartupInfo.hStdInput := InputRead;
StartupInfo.hStdOutput := 7; // Undocumented Handle of Console Output
StartupInfo.hStdError := 11; // Undocumented Handle of Console Error Output
end;

关于c - 如何让 Windows Pipe 在进程完成时添加 EOF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57042246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com