C++ 输入/输出管道
这个问题源于我尝试执行中的说明: 我的问题与中的问题大致相同,但更具体 基本上,我试图取代:C++ 输入/输出管道,c++,linux,pipe,C++,Linux,Pipe,这个问题源于我尝试执行中的说明: 我的问题与中的问题大致相同,但更具体 基本上,我试图取代: /directory/program < input.txt > output.txt 因此,我的代码目前使用 system("program < input.txt > output.txt"); system(“程序output.txt”); 我想用管道代替这个过程。我想将我的输入作为标准输入传递给程序,并让我的代码将该程序的标准输出读入字符串。听起来像是您在寻找
/directory/program < input.txt > output.txt
因此,我的代码目前使用
system("program < input.txt > output.txt");
system(“程序output.txt”);
我想用管道代替这个过程。我想将我的输入作为标准输入传递给程序,并让我的代码将该程序的标准输出读入字符串。听起来像是您在寻找的。您可以用C/C++对它们进行编程,但是由于它们已经在(bash)shell中可用,所以shell的使用更容易,对吗 首先用
coproc
内置程序启动外部程序:
coproc external_program
coproc
在后台启动程序,并将与之通信的文件描述符存储在数组shell变量中。现在,您只需启动程序,将其连接到这些文件描述符:
your_program <&${COPROC[0]} >&${COPROC[1]}
您的_程序&${COPROC[1]}
您的主要问题是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
我被误导,误读了你写的“OK”,直到我对设置代码进行了错误检查,并从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;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
int fd_p2c[2],fd_c2p[2],字节读取;
pid_t childpid;
字符读取缓冲区[80];
字符串program_name=“/bin/cat”;
string gulp_command=“这是发送给小猫的命令数据”;
字符串receive_output=“”;
如果(管道(fd|p2c)!=0 |管道(fd|c2p)!=0)
{
cerr#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
int i,状态,len;
char-str[10];
mknod(“管道”,S|iffo | S|IRUSR | S|IWUSR,0);//创建命名管道
pid_t pid=fork();//创建新进程
/*过程A*/
如果(pid==0){
int myPipe=open(“pipe”,O_WRONLY);//返回管道的文件描述符
cout您的出发点不清楚。您声明要使用管道替换/directory/program output.txt
,以避免文件系统访问。但您“需要”多个进程才能合理使用管道。(您可以在单个进程中使用管道,但通常没有意义。)因此,您可能有/directory/program1 output.txt
;这很有意义(您以前可能使用过/directory/program1 intermediate.txt;/directory/program2 output.txt
)。请澄清你的意图。说得好。我编辑了这个问题。作为额外的澄清,我的目标基本上与你之前回答的:stackoverflow.com/questions/1734932/…中的问题相同(顺便说一句,回答得很好).@Ericinlan如果我想做同样的事情,但只针对两个子进程,我们将如何运行此代码?这意味着在两个子进程之间发送和接收字符串时忽略父进程。@Mohsin我以前从未尝试过这样做。不幸的是,我现在无法给你指导。在我的情况下,我的程序反复调用外部_程序(数千次),每次都有不同的输入。这看起来像是启动时执行的一次性bash脚本,对吗?我对文件描述符不太了解,但如果要使用它,这是否意味着我必须写入驱动器上的文件,或者文件描述符可以指向代码中的字符串?在这种情况下,文件描述符连接到管道,而不是文件。此外,您还可以运行bash脚本数千次。这非常有效。感谢您的帮助,以及对死锁代码的提醒。我认为我不会有这个程序的问题,但知道这一点很好。如果我想做同样的事情,但只为两个子进程,我们将如何运行此代码?意思是发送和接收在忽略父进程的两个子进程之间接收字符串。@Mohsin:这部分取决于子进程将如何通信,以及父进程在启动两个子进程后将执行什么操作。有多种方法可以处理此问题。一种方法是在执行上述任何代码之前简单地使用父进程分支,而父进程或者,父进程设置两个管道,分叉两次,每个子进程整理自己的管道,而父进程关闭这两个管道的四个文件描述符并按自己的方式进行。是的,我做的正是第二种方法按照你的建议,我只是简单地创建一个管道并调用两个fork,一个用于child_a,另一个用于child_b,如果pid_child_a为零,它会写入管道,否则如果pid_child_b为零,它会从缓冲区读取并打印值,问题是当我第一次运行它时,它运行良好,但第二次运行时,它不会打印任何内容e project或再次进行一些编辑会给出正确的输出,但第二次又开始不打印任何内容,以此类推。而且,如果我在调试模式下运行它,每次都会给出正确的输出
your_program <&${COPROC[0]} >&${COPROC[1]}
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
#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?)>>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <iostream>
using namespace std;
int main() {
int i, status, len;
char str[10];
mknod("pipe", S_IFIFO | S_IRUSR | S_IWUSR, 0); //create named pipe
pid_t pid = fork(); // create new process
/* Process A */
if (pid == 0) {
int myPipe = open("pipe", O_WRONLY); // returns a file descriptor for the pipe
cout << "\nThis is process A having PID= " << getpid(); //Get pid of process A
cout << "\nEnter the string: ";
cin >> str;
len = strlen(str);
write(myPipe, str, len); //Process A write to the named pipe
cout << "Process A sent " << str;
close(myPipe); //closes the file descriptor fields.
}
/* Process B */
else {
int myPipe = open("pipe", O_RDONLY); //Open the pipe and returns file descriptor
char buffer[21];
int pid_child;
pid_child = wait(&status); //wait until any one child process terminates
int length = read(myPipe, buffer, 20); //reads up to size bytes from pipe with descriptor fields, store results
// in buffer;
cout<< "\n\nThis is process B having PID= " << getpid();//Get pid of process B
buffer[length] = '\0';
cout << "\nProcess B received " << buffer;
i = 0;
//Reverse the string
for (length = length - 1; length >= 0; length--)
str[i++] = buffer[length];
str[i] = '\0';
cout << "\nRevers of string is " << str;
close(myPipe);
}
unlink("pipe");
return 0;
}