# Ch15 Interprocess Communication >###### tags: `APUE` ### Pipe Pipes are the oldest form of UNIX IPC with two limitations: 1. half duplex 2. It can be used only betwwen processes that have a common ancestor ```c = #include <unistd.h> int pipe(int filedes[2]); //filedes [0] :open for reading //filedes [1] :open for writing ``` ### Pipe1 Two ends of a pipe connected in a single process. ```c= #include <stdio.h> #include <string.h> #include <unistd.h> int main(int argc,char* argv[]){ int pipefd[2]; char* str = "hello\n\0"; char buffer[100]; pipe(pipefd); write(pipefd[1],str,strlen(str)+1); read(pipefd[0],buffer,200); printf("%s\n",buffer); return 0; } ``` ### Pipe2 Fork after pipe,the child inherits a copy of the file descriptor. So closing the descriptor in the child will close it for the child, but not the parent, and vice versa. Here is the example for communication between a parent process and a child process. ```c= #include <stdio.h> #include <string.h> #include <unistd.h> #include <assert.h> int main(int argc,char* argv[]){ int pipefd[2]; char* str = "hello my child\n"; char buffer[100]; int ret; pipe(pipefd); ret = fork(); assert(ret >= 0); if (ret > 0){ printf("parent\n"); close(pipefd[0]); //parent close its read end write(pipefd[1],str,strlen(str)+1); } else{ printf("child\n"); close(pipefd[1]); //child close its write end read(pipefd[0],buffer,100); printf("%s",buffer); } return 0; } ``` ### Pipe3 Call dup after closing stdin or stdout to redirect them to pipe. The new file descriptor returned by dup() is the lowest-numbered available file descriptor. ```c= #include <stdio.h> #include <string.h> #include <assert.h> #include <unistd.h> int main(int argc,char* argv[]){ int pipefd[2]; char buffer[200]; int ret; pipe(pipefd); ret = fork (); assert(ret >= 0); if (ret == 0){ //child close(1); //close stdout dup(pipefd[1]); close(pipefd[0]); printf("hello\n"); } else{ //parent close(0); dup(pipefd[0]); close(pipefd[1]); scanf("%s",buffer); printf("parent:%s\n",buffer); } return 0; } ``` ### Pipe3-1 Compared with Pipe3, Pipe3-1 use fgets to replace scanf.The most important thing is we shall always remember close the unused pipe fd. ```c= FILE* in_stream; if(ret == 0){ //parent close(1); dup(pipefd[1]); printf("spoiled brat\n"); close(pipefd[0]); close(pipefd[1]); } else{ //child close(0); dup(pipefd[0]); in_stream = fdopen(0,"r"); fgets(buffer,100,in_stream); printf("from parent:%s",buffer); close(pipefd[0]); close(pipefd[1]); } ``` ### Pipe4 Finally, we write a program to implement the command "ls | wc" with fork-exec mechanism. ```c= #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc,char* argv[]) { int pipefd[2]; int pid1,pid2,wstat;; pipe(pipefd); pid1 = fork(); assert(pid1 >= 0); if(pid1 == 0){ //parent printf("I am parent\n"); close(pipefd[0]); close(pipefd[1]); wait(&wstat); } else{ printf("I am child1\n"); pid2 = fork(); assert(pid2 >= 0); if(pid2 > 0){ printf("I am child2\n"); close(0); //close stdin dup(pipefd[0]); //read end close(pipefd[0]); close(pipefd[1]); execlp("/usr/bin/wc","wc",NULL); } close(1); //close stdout dup(pipefd[1]); //write end close(pipefd[0]); close(pipefd[1]); execlp("/bin/ls","ls",NULL); } return 0; } ```