ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 输入/输出管道

2019-09-26 06:50:24  阅读:106  来源: 互联网

标签:c linux pipe


这个问题来自我试图实施以下指令:

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)程序的报告(通过标准输出提供)出现在终端中.这很奇怪,因为这个管道的目的是将stdout传输到我的字符串“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?)>>

请注意,您需要小心确保不会因代码而陷入僵局.如果你有一个严格同步的协议(所以父母写一条消息并以锁定步骤读取一个响应),你应该没事,但如果父母试图写一个太大而不适合孩子的管道的消息当孩子正在尝试写一条太大而无法容纳回父母的管道的消息时,每个人都会被阻止写作,同时等待另一个人阅读.

标签:c,linux,pipe
来源: https://codeday.me/bug/20190926/1819143.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有