I/O Loop using Fork() and Pipe()

Hi, everyone, I'm working on a college assignment and I'm having a bit of difficulty getting it to work properly. The assignment calls for us to write a C++ program using Linux system calls which creates a pipe and forks a child process. As a whole, this program is supposed to loop accepting input from the user, write it to the pipe, and then print the command it received back into the console, unless it receives a "T" command, which terminates the program.

The parent process is responsible for prompting, accepting input, and writing to the pipe. The child process is responsible for reading from the pipe, and displaying this result in the console.

The problem I have, is that it continues to loop asking for input commands, but only prints the first command it receives. I've sat here for hours trying to figure this out. Read the relevant man pages. Watched YouTube videos. Nothing is helping me. I'm obviously pretty new to programming and I assume I'm just not seeing it. What am I doing wrong here?

Thanks in advance for any help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
       #include <sys/types.h>
       #include <sys/wait.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <string.h>  
       #include <iostream>

       using namespace std;

       int
       main()
       {
           int pipefd[2];
           pid_t cpid;
           char buf;
           
           if (pipe(pipefd) == -1) {
               perror("pipe");
               exit(EXIT_FAILURE);
           }
           
           cpid = fork();
           if (cpid == -1) {
               perror("fork");
               exit(EXIT_FAILURE);
           }  
              
           if (cpid == 0) {    //Child process
               read(pipefd[0], &buf, 1);
               cout << buf << " command received.\n";
           }
           else {  //Parent process
               do{
               cout << "Enter a command (q, u, p, t): "; 
               cin >> buf; 
               write(pipefd[1], &buf, 1);
               wait(NULL);
               }while(buf != 't');
               if(buf == 't'){
                   cout << "\nExiting program...";
                   close(pipefd[1]);
                   close(pipefd[0]);
                   exit(EXIT_SUCCESS);
               }
           }  
       }
You do a single read in the child process. Then the process terminates. The parent process repeats actions via a loop. Perhaps, you could do the same in the child process.
Solved it! This put me on the right track. Thank you!

I kept encountering issues when I would put a loop in the child process, and the program would get stuck in a loop refusing to accept input or output anything. I must have misunderstood the lab directions as well, because it seemed as if we were instructed to put the loop in either or, but not both processes. Without a loop, though, the child process will terminate after one cycle, so I was confused.

This is how I realized that my inclusion of wait() in the parent process was causing problems. I misunderstood the way it worked. When I would put a loop in the child process, and wait() in the parent process, the program would hang waiting for the child process to terminate, which would never occur with the inclusion of the loop.

I ended up moving the close() system calls, writing a loop in the child, and just deleting the line of code containing wait(NULL);, and my problems were solved.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
       #include <sys/types.h>
       #include <sys/wait.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <string.h>  
       #include <iostream>

       using namespace std;

       int
       main()
       {
           int pipefd[2];
           pid_t cpid;
           char buf;
           
           if (pipe(pipefd) == -1) {
               perror("pipe");
               exit(EXIT_FAILURE);
           }
           
           cpid = fork();
           if (cpid == -1) {
               perror("fork");
               exit(EXIT_FAILURE);
           }  
              
           if (cpid == 0) {    //Child process
               do{    
               read(pipefd[0], &buf, 1);
               cout << buf << " command received.\n";
               }while(buf != 't');
                   if(buf =='t'){
                       close(pipefd[0]);
                       close(pipefd[1]);
                       _exit(EXIT_SUCCESS);
                   }
           }
           else {  //Parent process
               do{
               cout << "Enter a command (q, u, p, t): ";   
               cin >> buf; 
               write(pipefd[1], &buf, 1);
               }while(buf != 't');
               if(buf == 't'){
                   cout << "\nExiting program...";
                   close(pipefd[1]);
                   close(pipefd[0]);
                   exit(EXIT_SUCCESS);
               }
           }  
       }
Topic archived. No new replies allowed.