C/C++ Forking and Using Pipes to Exchange Data Between Parent and Child

Aim
Pipes are form of inter-process communication. They are very useful to synchronize access to resources, notification and exchanging data. In this example we will use fork to spawn a process and then communicate between the child process and parent process using pipes.

Assumptions
You have a C++ compiler (g++ in this example) and access to a linux environment or cygwin.

Application
In this simple example we use pipe to create the pipes. We then fork and use write and read on the pipes to exchange information. Also note that we call waitpid in the parent to stop it exiting before the child has quit.

Let us have a look at the code below. This file will be saved as forking_pipes.cpp
 1. #include <stdlib.h>
 2. #include <stdio.h>
 3. #include <string.h>
 4. #include <unistd.h>
 5. #include <errno.h>
 6. #include <sys/types.h>
 7. #include <sys/wait.h>
 8. 
 9. 
10. int main(int argv, char** argc){
11. 
12.     int pipes[2];
13.     char readbuf[64]={0};
14.     char writebuf[64]={0};
15.     int childpid;
16. 
17.     if(pipe(pipes)<0){
18.         perror("Pipe allocation failed");
19.         exit(0);
20.     }
21. 
22.     switch(childpid=fork()){
23.         case -1:
24.             perror("Problem with fork\n");
25.             break;
26. 
27.         case 0:  //Child
28.             //Writing
29.             sprintf(writebuf, "Hello from %d", getpid());
30.             if(write(pipes[1], writebuf, strlen(writebuf))<0){
31.                 perror("Child write failed\n");
32.             }
33. 
34.             //Reading
35.             if(read(pipes[0], readbuf, 64)>0){
36.                 printf("Child read - %s\n", readbuf);
37.             }
38.             else{
39.                 perror("child read failed\n");
40.             }
41. 
42.             break;
43.         
44.         default: //Parent
45.             //Reading
46.             if(read(pipes[0], readbuf, 64)>0){
47.                 printf("Parent read - %s\n", readbuf);
48.             }
49.             else{
50.                 perror("Parent read failed\n");
51.             }
52.             
53.             //Writing
54.             sprintf(writebuf, "Hello from parent");
55.             if(write(pipes[1], writebuf, strlen(writebuf))<0){
56.                 perror("Parent write failed\n");
57.             }
58. 
59.             waitpid(childpid,0,0);
60. 
61.             break;
62.     }
63. }
Hide line numbers

Compile the code

..workspace\Forkingpipes>g++ forking_pipes.cpp

pipes[0] is the reading pipe and pipe[1] is the writing pipe. In the parent whatever you write to pipe[1] can be read at the child using pipe[0]. In the child whatever you write to pipe[1] can be read at the Parent using pipe[0].

If you wish to spawn multiple children then you have to have multiple pipe pairs. This means you will have to use select in the parent to find out which pipes are ready for writing and reading.