Yoohao
Yoohao

Reputation: 39

How does this code work between two process?

I am doing some practice and got this code recently.

#include<sys/types.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>

#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1

int main(int argc,char *argv[]){                                    
    if (argc==2){                                                   
        char output[BUFFER_SIZE];                                   
        close(4);                                                   
        while(1){
            read(3,output,BUFFER_SIZE);                             
            if(output[0]=='Q'&&output[1]==NULL){                    
                return 0;
            }
            printf("%s\n",output);                                  
        }
    }

    if(argc==1){                                                    
        char write_msg[BUFFER_SIZE]="A";                            
        int fd[2];                                                  
        pid_t pid;                                                  

        if(pipe(fd)==-1){                                           
            fprintf(stderr,"Pipe failed");
            return 1;
        }

        pid = fork();                                               

        if(pid<0){                                                  
            fprintf(stderr,"Fork failed");
            return 1;
        }

        if(pid>0){                                                  
            close(fd[READ_END]);                                    
            while (write_msg[0]!='Q'||write_msg[1]!=NULL){          
                scanf("%s",write_msg);                              
                write(fd[WRITE_END],write_msg,strlen(write_msg)+1); 
            }

            close(fd[WRITE_END]);                                   
        }
        if(pid==0){                                                 
            execl("/usr/bin/xterm","xterm","-e",argv[0],"1",NULL); 
        }
        return 0;
        }
}

I want to ask that how does this work. In my opinion, pipe can communicate between parent process and child process. But the chile proecss in this execute the execlp function to open a new terminal window and run the same program sequentially. The new window isn't the child of the parent process. However, it can receive the string from the pipe file descriptor. I can't understand why and wanna know that how does it work between two process.

I've been confused for a while. Hope someone could help me. Thanks.

Upvotes: 1

Views: 112

Answers (2)

ilkkachu
ilkkachu

Reputation: 6527

The xterm executed by the child is a child of the original program. The fork, then exec is the normal way to start another process on Unix-like systems.

When the program forks, another copy of it appears. The only difference between them is the return value from fork. Here, the child then replaces itself with xterm, setting the arguments so that xterm starts another copy of the original program. As long as xterm doesn't mess with the file descriptors of the pipe, they stay open and are inherited to whatever process xterm runs.

The one-argument version (argc==2) of the main program trusts that the pipe file descriptors get numbers 3 and 4, which would be the usual result, assuming the original program didn't have any fd's open apart from stdin, stdout and stderr. This isn't robust, though. To do it properly you'd want to give the fd numbers to the child as command line arguments or through the environment; or use dup2() in the parent to make sure the pipe is open on fd's 3 and 4.

Upvotes: 1

P.P
P.P

Reputation: 121387

But the child proccss in this execute the execlp function to open a new terminal window and run the same program sequentially. The new window isn't the child of the parent process.

That's not right. The new window is the child process. execl() just replaces the child process with another process image but it's still the child process. So, the parent and child can communicate via the pipe. Your code is classic example and parent and child can communicate via unix pipe.

The child process executes the if (argc==2){ ... } code because it's given an arugment (in execl() -- so its argc is 2). The parent process is intended to be run with no arguments.

By the way, there are a couple of issues:

1) You probably want to check if output[1] is \0 (null byte), not NULL. That'd make sense in order to terminate the communication (and the processes) by inputting Q. So, this:

 if(output[0]=='Q'&&output[1]==NULL){                    

should be:

 if(output[0] == 'Q'&&output[1] == '\0'){

2) Similarly,

  while (write_msg[0]!='Q'||write_msg[1]!=NULL){

should be:

  while (write_msg[0] != 'Q' || write_msg[1] != '\0'){

Upvotes: 1

Related Questions