Pipe implementation
Asked Answered
B

2

9

I am trying to implement a linux shell that supports piping. I have already done simple commands, commands running in background, redirections, but piping is still missing.

I have already read about it and seen some snippets of code, but still haven't been able to sort out a working solution.

What I have so far:

int fd[2];

pipe(fd);

pid_t pid = fork();

if (pid == -1)  
   return -1;  

if (pid == 0)  
{  
   close(fd[1]); //close write to pipe, in child
   execlp("cat", "cat", "names.txt", NULL);
}

else
{
   close(fd[0]); //close read from pipe, in parent
   execlp("sort", "sort", NULL);
}  

I am a novice programmer, as you can probably tell, and when I am programming something I don't know much about, this being obviously the case, I like to start with something really easy and concrete and then build from there.

So, before being able to implement three and more different commands in pipeline, I would like to be able to compute "ls names.txt | sort" or something similiar, in which names.txt is a file of names alfabetically unordered.

Updated code, but still doesn't work.

Thanks.

Batruk answered 17/4, 2010 at 18:59 Comment(0)
H
11

You need to replace one child's stdout with the writing end of the pipe, and the other child's stdin with the reading end:

if (pid == 0)  
{  
   close(fd[0]); //close read from pipe, in parent
   dup2(fd[1], STDOUT_FILENO); // Replace stdout with the write end of the pipe
   close(fd[1]); // Don't need another copy of the pipe write end hanging about
   execlp("cat", "cat", "names.txt", NULL);
}
else
{
   close(fd[1]); //close write to pipe, in child
   dup2(fd[0], STDIN_FILENO); // Replace stdin with the read end of the pipe
   close(fd[0]); // Don't need another copy of the pipe read end hanging about
   execlp("sort", "sort", NULL);
} 
Halverson answered 18/4, 2010 at 10:1 Comment(3)
I cant help but it looks reversed to me. Why are we connecting the standard input of cat with the standard output of sort. Isn't it the other way around? E.g. the output of cats goes to the input of sort.Protestation
@VicenteAdolfoBoleaSánchez: That probably makes more sense, I've updated the answer.Halverson
Oh great! Understood :)Protestation
R
5

Look into the pipe() standard library call. This is used to create a pipe. You must of course do part of the work before you fork(), in order for the child process to inherit the file descriptor properly.

Also note the order of the arguments to dup2():

int dup2(int oldfd, int newfd);

dup2() makes newfd be the copy of oldfd, closing newfd first if necessary

Rickrickard answered 17/4, 2010 at 19:7 Comment(5)
I already knew that, just forgot to add the pipe statement to the code. What do you suggest now? Thanks.Batruk
I thought that dup2(0, fd[0]) was copying what was supposed to go to stdout to fd[0], which is the input of the process. I suppose that what I want, right?Batruk
@nunos: dup2() doesn't do the copying, it copies file descriptors. Since fd[0] is the fd of one end of your newly created pipe, it doesn't make a lot of sense to close it, as dup2() will do.Rickrickard
I understand it now. I have updated the code. Can you please take a look and report what I am missing? Thanks again for your help.Batruk
If you think this answer helps, you should vote it up. :) I think your original code was better, you want to use dup2() but I was trying to imply that you had the arguments the wrong way around.Rickrickard

© 2022 - 2024 — McMap. All rights reserved.