如何正确接收管道数据?

时间:2013-08-14 04:29:30

标签: c++ linux exec fork pipe

所以我用管道和execl写了一个程序来做算术。我不确定如何调试管道和不同的进程,但从我可以看到它必须与我的管道读取数字有关。所以我到目前为止的设置是创建了子节点,并且基于给定的操作,它们会执行不同的程序来计算管道中的写入值。在读取结果之前,我不知道在将值写入子节点之后是否应该在父节点中实现等待或某事。我一直把Z作为输出。

所以这是我执行的文件之一,其他文件看起来完全一样,只是显示了相应的操作:

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>

using namespace std;

main(int argc, char *argv[])
{
    int x, y, z;
    while (read(0, (char *)&x, sizeof(int)) &&
           read(3, (char *)&y, sizeof(int))) {
        z = x * y;
        if (argc > 1)
            cerr << "multiply: " << x << " * " << y << " = " << z << endl;
        write(1, (char *)&z, sizeof(int));
    }
}

这是我的代码,它实际上正在进行计算,我认为管道设置正确。关于管道设置的一点解释,以节省时间。子0 - 从管道0读取并写入2.子级1从管道2和3读取并写入4.父级写入0 1 3并从4读取。我的代码:

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>

using namespace std;

const int MAX =21;
int pipes[MAX][2];
char operations[MAX];

int main()
{
    int a=0;
    int n;
    fstream datafile;
    pid_t pid;
    string line;
    datafile.open("data1.txt");


   if(datafile)
    {

        string input;
        getline(datafile, input);

        for(int i=0; i< input.size(); i++)
        {


            if (input[i] == '*'|| input[i] == '/'||input[i] == '+'||input[i] == '-')
            {

                operations[a] = input[i];
                a++;

            }

        }
      n = (a);

        for(int i =0; i<(2*n+1); i++)
           pipe(pipes[i]);

        for (int i=0; i <n; i++)
        {    
           pid = fork();
            if(pid == 0)
            {

                close(0);
                dup(pipes[2*i][0]);
                close(3);
                dup(pipes[2*i+1][0]);
                close(1);
                dup(pipes[2*i+2][1]);


                    switch(operations[i])
                    {
                    case '+':
                        execl("add","add", NULL);
                    case '-': 
                        execl("subtract","multiply", NULL);
                    case '*':
                        execl("multiply","multiply", NULL);
                    case '/':
                        execl("divide","divide", NULL);

                    }

                 cout<< "No match for operation!";
            }
            else if(pid <0)
            cerr<<"Fork has failed";
          }

        int x, y, z;

        for(int i=0; i<3; i++)
          {
            getline(datafile,line);
            istringstream ins(line);
            ins >> x >> y >> z;

            write(0,(char *)&x, sizeof(x));
            write(3,(char *)&z, sizeof(z));
            write(1,(char *)&y, sizeof(y));
          }

          close(0);
          close(3);
          close(1);
        }  

            else
                cerr<<"Error reading file";



          datafile.close();

            int result;
            while(read(pipes[2*n][1],(char *)&result,sizeof(result)))
                cout<<result<<endl;








}

datafile可以是这样的:

  

a * b * c

     

30 40 50

     

100 3 6

1 个答案:

答案 0 :(得分:1)

让我们简化这段代码。没有操作 - 仍然无效。只有一个孩子 - 仍然无法工作。只有一个管道 - 仍然无法正常工作。没有文件I / O - 仍然无法正常工作。我们现在试图将数字30从父母传递给孩子:

  int pipes[1][2];

  pid_t pid;

  pipe(pipes[0]);

  pid = fork();
  if(pid == 0)
    {
      cout << "child here" << endl;
      close(0);
    }
  else if(pid <0)
    cerr<<"Fork has failed";

  cout << "parent here " << endl;

  int x = 30;
  write(0,(char *)&x, sizeof(x));
  close(0);

  int result;
  read(pipes[0][1],(char *)&result,sizeof(result));
  cout << "result is " << result << endl;

看到错误?让我们更进一步,完全删除管道通信:

pid_t pid;
pid = fork();
if(pid == 0)
  {
    cout << "child here" << endl;
  }
else if(pid <0)
  cerr<<"Fork has failed";

cout << "parent here " << endl;

看到错误?我们解决了这个问题:

pid_t pid;
pid = fork();
if(pid == 0)
  {
    cout << "child here" << endl;
    return(0);
  }
else if(pid <0)
  cerr<<"Fork has failed";

cout << "parent here " << endl;

然后把管道放回去:

  int pipes[1][2];

  pid_t pid;

  pipe(pipes[0]);

  pid = fork();
  if(pid == 0)
    {
      cout << "child here" << endl;

      close(0);

      int result;
      read(pipes[0][1],(char *)&result,sizeof(result));
      cout << "result is " << result << endl;
      return(0);
    }
  else if(pid <0)
    cerr<<"Fork has failed";

  cout << "parent here " << endl;

  int x = 30;
  write(0,(char *)&x, sizeof(x));
  close(0);

看到错误?修复管道错误,然后回复2个孩子和5个管道。 单独测试操作内容,然后将其拼接。

我相信这证明了简化代码的能力。