这段代码在两个流程之间如何运作?

时间:2017-04-05 18:12:16

标签: c linux

我正在做一些练习并且最近得到了这个代码。

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

我想问一下这是如何工作的。在我看来,管道可以在父进程和子进程之间进行通信。但是智能程序执行execlp函数来打开一个新的终端窗口并按顺序运行相同的程序。新窗口不是父进程的子进程。但是,它可以从管道文件描述符接收字符串。我无法理解为什么并想知道它在两个过程之间是如何工作的。

我已经困惑了一段时间。 希望有人可以帮助我。感谢。

2 个答案:

答案 0 :(得分:1)

  

但是子进程执行execlp函数来打开一个新的终端窗口并按顺序运行相同的程序。新窗口不是父进程的子进程。

那不对。新窗口子进程。 execl()只是将子进程替换为另一个进程映像,但它仍然是子进程。因此,父母和孩子可以通过管道进行通信。您的代码是经典示例,父级和子级可以通过unix管道进行通信。

子进程执行if (argc==2){ ... }代码,因为它被赋予了一个句子(在execl()中 - 所以它的argc是2)。父进程旨在不带参数运行。

顺便说一下,有几个问题:

1)您可能想要检查output[1]\0(空字节),而不是NULL。通过输入Q来终止通信(和进程)是有意义的。 所以,这个:

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

应该是:

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

2)同样,

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

应该是:

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

答案 1 :(得分:1)

孩子执行的xterm 是原始程序的子项。 fork,然后exec是在类Unix系统上启动另一个进程的正常方法。

当程序分叉时,会出现另一份副本。它们之间的唯一区别是来自fork的返回值。在这里,孩子用xterm替换自己,设置参数,以便xterm启动原始程序的另一个副本。只要xterm没有弄乱管道的文件描述符,它们就会保持打开状态并继承到xterm运行的任何进程。

主程序的单参数版本(argc==2)信任管道文件描述符得到数字3和4,这是通常的结果,假设原始程序没有任何fd& #st; sst与stdin,stdout和stderr分开。但这并不强大。为了正确地做到这一点,你想把fd号作为命令行参数或通过环境给孩子;或者在父母中使用dup2()以确保管道在fd&#39; s 3和4上打开。