gpt4 book ai didi

c++ - 输入/输出管道

转载 作者:IT王子 更新时间:2023-10-29 00:46:50 25 4
gpt4 key购买 nike

这个问题源于我尝试执行以下指令:

Linux Pipes as Input and Output

How to send a simple string between two programs using pipes?

http://tldp.org/LDP/lpg/node11.html

我的问题与以下问题的思路一致:Linux Pipes as Input and Output , 但更具体。

本质上,我正在尝试替换:

/directory/program < input.txt > output.txt

在 C++ 中使用管道以避免使用硬盘。这是我的代码:

//LET THE PLUMBING BEGIN 
int fd_p2c[2], fd_pFc[2], bytes_read;
// "p2c" = pipe_to_child, "pFc" = pipe_from_child (see above link)
pid_t childpid;
char readbuffer[80];
string program_name;// <---- includes program name + full path
string gulp_command;// <---- includes my line-by-line stdin for program execution
string receive_output = "";

pipe(fd_p2c);//create pipe-to-child
pipe(fd_pFc);//create pipe-from-child
childpid = fork();//create fork

if (childpid < 0)
{
cout << "Fork failed" << endl;
exit(-1);
}
else if (childpid == 0)
{
dup2(0,fd_p2c[0]);//close stdout & make read end of p2c into stdout
close(fd_p2c[0]);//close read end of p2c
close(fd_p2c[1]);//close write end of p2c
dup2(1,fd_pFc[1]);//close stdin & make read end of pFc into stdin
close(fd_pFc[1]);//close write end of pFc
close(fd_pFc[0]);//close read end of pFc

//Execute the required program
execl(program_name.c_str(),program_name.c_str(),(char *) 0);
exit(0);
}
else
{
close(fd_p2c[0]);//close read end of p2c
close(fd_pFc[1]);//close write end of pFc

//"Loop" - send all data to child on write end of p2c
write(fd_p2c[1], gulp_command.c_str(), (strlen(gulp_command.c_str())));
close(fd_p2c[1]);//close write end of p2c

//Loop - receive all data to child on read end of pFc
while (1)
{
bytes_read = read(fd_pFc[0], readbuffer, sizeof(readbuffer));

if (bytes_read <= 0)//if nothing read from buffer...
break;//...break loop

receive_output += readbuffer;//append data to string
}
close(fd_pFc[0]);//close read end of pFc
}

我绝对确定上述字符串已正确初始化。但是,发生了两件对我来说没有意义的事情:

(1) 我正在执行的程序报告“输入文件为空”。因为我没有用“<”调用程序,所以它不应该期待输入文件。相反,它应该期待键盘输入。此外,它应该读取“gulp_command”中包含的文本。

(2) 程序的报告(通过标准输出提供)出现在终端中。这很奇怪,因为此管道的目的是将标准输出传输到我的字符串“receive_output”。但由于它出现在屏幕上,这对我来说表明信息没有通过管道正确传递到变量。如果我在 if 语句的末尾执行以下内容,

cout << receive_output << endl;

我什么也没得到,好像字符串是空的。我很感激你能给我的任何帮助!

编辑:澄清

我的程序当前使用文本文件与另一个程序通信。我的程序写入一个文本文件(例如 input.txt),该文件由外部程序读取。然后该程序生成 output.txt,由我的程序读取。所以它是这样的:

my code -> input.txt -> program -> output.txt -> my code

因此,我的代码目前使用,

system("program < input.txt > output.txt");

我想用管道替换这个过程。我想将我的输入作为标准输入传递给程序,并让我的代码从该程序读取标准输出到一个字符串中。

最佳答案

您的主要问题是您将 dup2() 的参数颠倒了。您需要使用:

dup2(fd_p2c[0], 0);   // Duplicate read end of pipe to standard input
dup2(fd_pFc[1], 1); // Duplicate write end of pipe to standard output

直到我对设置代码进行错误检查并从 dup2() 调用中获得意外值,我才误读了您写的内容,这告诉我问题出在哪里。当出现问题时,插入您之前跳过的错误检查。

您也没有确保从子进程读取的数据的空终止;这段代码可以。

工作代码(带诊断),使用 cat 作为最简单的“其他命令”:

#include <unistd.h>
#include <string>
#include <iostream>
using namespace std;

int main()
{
int fd_p2c[2], fd_c2p[2], bytes_read;
pid_t childpid;
char readbuffer[80];
string program_name = "/bin/cat";
string gulp_command = "this is the command data sent to the child cat (kitten?)";
string receive_output = "";

if (pipe(fd_p2c) != 0 || pipe(fd_c2p) != 0)
{
cerr << "Failed to pipe\n";
exit(1);
}
childpid = fork();

if (childpid < 0)
{
cout << "Fork failed" << endl;
exit(-1);
}
else if (childpid == 0)
{
if (dup2(fd_p2c[0], 0) != 0 ||
close(fd_p2c[0]) != 0 ||
close(fd_p2c[1]) != 0)
{
cerr << "Child: failed to set up standard input\n";
exit(1);
}
if (dup2(fd_c2p[1], 1) != 1 ||
close(fd_c2p[1]) != 0 ||
close(fd_c2p[0]) != 0)
{
cerr << "Child: failed to set up standard output\n";
exit(1);
}

execl(program_name.c_str(), program_name.c_str(), (char *) 0);
cerr << "Failed to execute " << program_name << endl;
exit(1);
}
else
{
close(fd_p2c[0]);
close(fd_c2p[1]);

cout << "Writing to child: <<" << gulp_command << ">>" << endl;
int nbytes = gulp_command.length();
if (write(fd_p2c[1], gulp_command.c_str(), nbytes) != nbytes)
{
cerr << "Parent: short write to child\n";
exit(1);
}
close(fd_p2c[1]);

while (1)
{
bytes_read = read(fd_c2p[0], readbuffer, sizeof(readbuffer)-1);

if (bytes_read <= 0)
break;

readbuffer[bytes_read] = '\0';
receive_output += readbuffer;
}
close(fd_c2p[0]);
cout << "From child: <<" << receive_output << ">>" << endl;
}
return 0;
}

示例输出:

Writing to child: <<this is the command data sent to the child cat (kitten?)>>
From child: <<this is the command data sent to the child cat (kitten?)>>

请注意,您需要小心确保您的代码不会陷入僵局。如果你有一个严格同步的协议(protocol)(所以 parent 写一条消息并在锁步中读取一个响应),你应该没问题,但是如果 parent 试图写一条太大而无法放入管道的消息给 child 当 child 试图写一条太大而无法通过管道返回给 parent 的消息时,每个人都将在等待另一个人读取时被阻止写入。

关于c++ - 输入/输出管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17508626/

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