0

I'm very beginner with linux however I've managed to do my own shell. It's time to add pipelines in there. (That's what, the homework says). Could anyone explain me a little bit more how to do that? I know that in theory, it should work like that.

unsigned char* child_results; //buffer to save results from child processes

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

    if (pid == 0) {
        //if it's the first process to launch, close the read end of the pipe
        //otherwise read what the parent writes to the pipe and then close the 
        //read end of the pipe

        //call execvp()
    }
    else {
        //if you've launched the first process, close the write end of the pipe
        //otherwise write the contents of child_result to the child process
        //and then close the write end of the pipe

        //read from the child's pipe what it processed

        //save the results in the child_results buffer

        wait(NULL); //wait for the child to finish
    }
}

However, I can't get it working. I'm doing that whole day and still, nothing. I do understand the idea, but I can't get it work. Could some1 help me? Here's the code of my pipelines part:

for (int i = 0; i <= pipeline_count; i++) { 
    int pdesc[2]; 
    // creating pipe
    pipe(pdesc);
    int b = fork();
    // child
    if (b == 0) {
        // 1st pipeline
        if (i == 0) {       
            //<?>               
        }

        // last pipeline
        if (i == pipeline_count) {                              
            //<?>
        }

        // inside pipeline
        if (i > 0 && i < pipeline_count)  {
            //<?>
        } 
        execvp(array[0], array);
    }
    else { 
        // parent
        //<?>
        wait(NULL);         
    }
}       

and here's an example of a shell command

ls -al | tr a-z A-Z

Thanks

jww
  • 97,681
  • 90
  • 411
  • 885
Patryk
  • 3,042
  • 11
  • 41
  • 83

1 Answers1

2

You must close the input stream on the child and duplicate with dup the pipe for that channel. The parent does the same with the other side of the pipe. Something like this:

b = fork();
if (b == 0) {
  /* Close stdin, and duplicate the input side of the pipe over stdin */
  dup2(0, pdesc[0]);
  execlp(...);
}
else {
  /* Close stdout, and duplicate the output side of the pipe over stdout */
  dup2(1, pdesc[1]);
  execlp(...);
}
...

I've shown you how to do it on a two processes case, but you can get the general idea and adapt it to other situations.

Hope that helped!

felixgaal
  • 2,403
  • 15
  • 24
  • Why should I run execlp in both parent and a child process? Won't that stop my program? – Patryk Nov 10 '12 at 22:19
  • 1
    No! Of course! It's only a sample code! I simply show a simple example of how you must use the dup2 function. In your situation, you must invoke dup2 over the input in the first child, dup2 over the output on the last child, and both sides in the other child processes inbetween. – felixgaal Nov 10 '12 at 22:23
  • if You only told me, how to read out of pipe to a char array and write from char array to a pipe, I would for sure do it :P! – Patryk Nov 10 '12 at 22:27
  • The read from a pipe, manually, just write `int nbytes = read(pdesc[0], inbuf, sizeof(inbuf));`. To write to a pipe, use `int nbytes = write(pdesc[1], outbuf, bytestowrite);`. See the docs of those functions. – felixgaal Nov 10 '12 at 22:34
  • 1
    But... I don't think that is what the homework is about... Reread it, study, the pieces are there. You must connect the processes, not send the data fro one to the other. That is what the pipe is about: the processes read and write to them. You just connect them. – felixgaal Nov 10 '12 at 22:37
  • Yeah, I think so too... But do I need 2 pipes then? Because it's not possible when I'm trying to do that on a 1 pipe (without reading buffer) – Patryk Nov 10 '12 at 23:00
  • You need as much pipes as `|` you write on the command line. For a situation like `ls | wc -l | lpr` you would use 2 pipes, etc. – felixgaal Nov 10 '12 at 23:19