IPC - pipes II

If you have used Linux for some time, you are already familiar with pipes in shell commands represented by |. This just takes the output of one program and gives it as input to another program
e.g.
ls|wc


will take output of ls(directory list-out) command and feed it to wc- word count program.


Can our pipe program do the same?


Yes it can. It can do this with the help of dup system call. dup system call duplicates a file descriptor to lowest available file descriptor.


e.g.
int fd2,fd;
 fd = open("a.txt",O_RDONLY);
 fd2 = dup(fd);

After this fd or fd2 can be used to access the file a.txt. That is to say, fd2 is a copy of fd. Either of them can be used for file access.


Now we use this system call with pipe like this

pipe(fd);
 p1 = fork();
 if (p1) 
 {
  close(fd[1]);
  close(0);/* close the stdin descriptor*/
  dup(fd[0]);/* Now stdin can be used for accessing read end of pipe */
  n=read(0,str,20);
  str[n]=0;
  printf("Read from the pipe %s\n",str);
 }
 else
 {
  close(fd[0]);
  close(1);/* close the stdout descriptor*/
  dup(fd[1]);/* Now stdout can be used for accessing write end of pipe */
  write(1,"Hello world",11);
 }

Now the child process writes Hello world to stdout device. But since it is closed and duplicated to pipe, the content gets written to pipe. The parent process reads from stdin - inturn from pipe and hence reads hello world


The program displays Read from the pipe Hello world




We will now proceed to feed the output of one program as input to another program. After pipe creation and forking and duping, let us exec ls from child process and wc from parent process. Parent will word count from output of ls
#include<stdio.h>
 #include<unistd.h>
 #include<sys/types.h>
 int main()
 {
  int fd[2];
  pid_t p1;
  if (pipe(fd)<0)
   {
   perror("pipe creation error";
   exit(1);
   }
  if ( (p1 = fork()<0))
   {
   perror("fork error);
   exit(1);
   }
  if (p1) 
  {
   close(fd[1]);
   close(0);/* close the stdin descriptor*/
   dup(fd[0]);/* Now stdin can be used for accessing read end of pipe */
   if (execl("/bin/wc","wc",NULL)<0)
   {
    perror("exec wc error");
    exit(1);
   }
  
  }
  else
  {
   close(fd[0]);
   close(1);/* close the stdout descriptor*/
   dup(fd[1]);/* Now stdout can be used for accessing write end of pipe */
   if (execl("/bin/ls","ls","-l","-a",NULL)<0)
   {
    perror("exec wc error");
    exit(1);
   }
  }
  return 0;
 }
After compiling the program and executing it, you should see the same output as ls|wc



Comments

Popular Posts