---
# System prepended metadata

title: Ch15 Interprocess Communication
tags: [APUE]

---

# 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;
}

```