Monday, November 10, 2014

Unix Prog: IPC Pipe(2)

1. Pipe Example:
pipe.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<string.h>  
   
 #define DEF_PAGER "/bin/more" // Default Pager program  
 #define MAXLINE 20  
   
 int main(int argc, char* argv[])  
 {  
  int n;  
  int fd[2];  
  pid_t pid;  
  char *pager, *argv0;  
  char line[MAXLINE];  
  FILE *fp;  
   
  // Open the file  
  if((fp = fopen(argv[1], "r")) == NULL) {  
   printf("can't open %s", argv[1]);  
   exit(1);  
  }  
   
  // Build the pipe  
  if(pipe(fd) < 0) {  
   printf("pipe error!\n");  
   exit(2);  
  }  
   
  if((pid = fork()) < 0) {  
   printf("fork error!\n");  
   exit(3);  
  } else if(pid > 0) {  
   close(fd[0]); // close read end  
   
   // Copy the content to pipe  
   while(fgets(line, MAXLINE, fp) != NULL) {  
    n = strlen(line);  
    if(write(fd[1], line, n) != n) {  
     printf("write error to pipe\n");  
     exit(4);  
    }  
   }  
   
   if(ferror(fp)) {  
    printf("fgets error!\n");  
    exit(5);  
   }  
   
   // close the write end  
   close(fd[1]);  
   
   if(waitpid(pid, NULL, 0) < 0) {  
    printf("waitpid error!\n");  
    exit(6);  
   }  
  } else {  
   close(fd[1]);  
   
   // duplicate the file descriptor if fd[0] is not standard input  
   // after this step, both fd[0] and STDIN_FILENO point to the same  
   // file table entry  
   if(fd[0] != STDIN_FILENO) {  
    if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {  
     printf("dup2 error to stdin\n");  
     exit(7);  
    }  
    close(fd[0]);  
   }  
   
   // Get the pager  
   if((pager = getenv("PAGER")) == NULL) {  
    pager = DEF_PAGER;  
   }  
   
   // Make argv0 point to the next char of last '/' in pager path  
   if((argv0 = strrchr(pager, '/')) != NULL)  
    argv0++;  
   else  
    argv0 = pager;  
   
   // Execute the pager with pipe input from parent process  
   if(execl(pager, argv0, (char*)0) < 0) {  
    printf("execl error for %s\n", pager);  
    exit(8);  
   }  
  }  
   
  exit(0);  
 }  

shell:
The program create the child process which make pipe file descriptor pointing to the standard input, and it will just make kernel give the pipe content through standard input.
So in the end the pager: /bin/more just print out the 2 lines from test1:
Hello world!
amazing world!
 ubuntu@ip-172-31-23-227:~$ ./pipe.out test1  
 Hello world!  
 amazing world!  

No comments:

Post a Comment