我正在做一些练习并且最近得到了这个代码。
#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
函数来打开一个新的终端窗口并按顺序运行相同的程序。新窗口不是父进程的子进程。但是,它可以从管道文件描述符接收字符串。我无法理解为什么并想知道它在两个过程之间是如何工作的。
我已经困惑了一段时间。 希望有人可以帮助我。感谢。
答案 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上打开。