C: 未检测到从 parent 到 child 进程的管道中的 EOF
C: Not detecting EOF in pipe from parent to child process
我正在学习 C 语言的编程课程,目前我们正在学习管道和进程。在 class activity 中分配了一个,我必须让 parent 创建一个 child 来打印从 parent 管道传输的输入。我可以让程序将输入通过管道传输到 child 并输出它,但是当我为 EOF 按 ctrl + D 时,我仍然可以输入(没有输出)。
我试着按照我的逻辑写在纸上,似乎是正确的,但有些地方不对。我试图硬编码一个我可以写的短语,这样我就可以退出我的child,但是当我试图补救这种情况时,我的管道坏了。
这是我的 2 个文件:
newshell.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
int main(void){
pid_t child1;
int fd[2];
char buffer1[100];
int bytes;
pipe(fd);
child1 = fork();
if (child1 == 0){
dup2(fd[0],fileno(stdin));
close(fd[1]);
printf("You are in the child.\n");
execlp("./printdata","printdata.c",0);
}
else {
dup2(fd[1],fileno(stdout));
close(fd[0]);
while(fgets(buffer1,sizeof(buffer1),stdin) != NULL){
write(fd[1],buffer1,(strlen(buffer1)+1));
}
write(fd[1],"999",sizeof("999"));
wait(0);
close(fd[1]);
close(fd[0]);
printf("Child ended. You are in the parent.\n");
}
return 0;
}
printdata.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void){
char buffer[100];
int bytes;
printf("You're in the new process\n");
while(bytes = read(fileno(stdin),buffer,sizeof(buffer)) >= 0){
printf("%s\n",buffer);
if (strcmp(buffer,"999") == 0){
return 0;
}
}
printf("Done here\n");
return 0;
}
这里的逻辑是,我在 parent 中创建了一个 child 进程,等待来自 parent 的输入。我硬编码了一个 'sentinel'(正如我的教授所说),因为当我输入它时没有检测到我的 EOF。老师接受了我的东西,因为大多数人都没有完成作业,但我想知道为什么它对我自己不起作用。
谢谢。
要点是:当您按下 CTRL+D
时,您会在 parent 的标准输入上发出 EOF 信号。
所以 parent 离开这个循环
while(fgets(buffer1,sizeof(buffer1),stdin) != NULL)
因为 fgets()
returns NULL
在 EOF。
但是现在,您需要关闭 fd[1]
和 fileno(stdout)
(因为您复制了它并且在 [=30 之前都做了=] 调用 wait(0)
),因为关闭引用该管道的最后一个文件描述符将在 child 进程的输入上发出 EOF 信号!我有点不清楚为什么你 dup2()
fd[1]
到 fileno(stdout)
,也许你应该把它去掉。
经过这些修改后,它应该可以正常工作。
parent 需要在调用等待之前关闭 fd[1]
。只要任何进程打开管道的写入端,child 中的读取就会阻塞。在您的情况下,parent 保持写入端打开,等待 child 终止。并且 child 在等待 parent 关闭管道的写入端的读取时被阻塞。换句话说,写:
close(fd[1]);
wait(0);
并且,正如 ctx 指出的那样,您需要关闭 parent 中的标准输出,或者停止无意义的 dup2
。
我正在学习 C 语言的编程课程,目前我们正在学习管道和进程。在 class activity 中分配了一个,我必须让 parent 创建一个 child 来打印从 parent 管道传输的输入。我可以让程序将输入通过管道传输到 child 并输出它,但是当我为 EOF 按 ctrl + D 时,我仍然可以输入(没有输出)。
我试着按照我的逻辑写在纸上,似乎是正确的,但有些地方不对。我试图硬编码一个我可以写的短语,这样我就可以退出我的child,但是当我试图补救这种情况时,我的管道坏了。
这是我的 2 个文件:
newshell.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
int main(void){
pid_t child1;
int fd[2];
char buffer1[100];
int bytes;
pipe(fd);
child1 = fork();
if (child1 == 0){
dup2(fd[0],fileno(stdin));
close(fd[1]);
printf("You are in the child.\n");
execlp("./printdata","printdata.c",0);
}
else {
dup2(fd[1],fileno(stdout));
close(fd[0]);
while(fgets(buffer1,sizeof(buffer1),stdin) != NULL){
write(fd[1],buffer1,(strlen(buffer1)+1));
}
write(fd[1],"999",sizeof("999"));
wait(0);
close(fd[1]);
close(fd[0]);
printf("Child ended. You are in the parent.\n");
}
return 0;
}
printdata.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void){
char buffer[100];
int bytes;
printf("You're in the new process\n");
while(bytes = read(fileno(stdin),buffer,sizeof(buffer)) >= 0){
printf("%s\n",buffer);
if (strcmp(buffer,"999") == 0){
return 0;
}
}
printf("Done here\n");
return 0;
}
这里的逻辑是,我在 parent 中创建了一个 child 进程,等待来自 parent 的输入。我硬编码了一个 'sentinel'(正如我的教授所说),因为当我输入它时没有检测到我的 EOF。老师接受了我的东西,因为大多数人都没有完成作业,但我想知道为什么它对我自己不起作用。
谢谢。
要点是:当您按下 CTRL+D
时,您会在 parent 的标准输入上发出 EOF 信号。
所以 parent 离开这个循环
while(fgets(buffer1,sizeof(buffer1),stdin) != NULL)
因为 fgets()
returns NULL
在 EOF。
但是现在,您需要关闭 fd[1]
和 fileno(stdout)
(因为您复制了它并且在 [=30 之前都做了=] 调用 wait(0)
),因为关闭引用该管道的最后一个文件描述符将在 child 进程的输入上发出 EOF 信号!我有点不清楚为什么你 dup2()
fd[1]
到 fileno(stdout)
,也许你应该把它去掉。
经过这些修改后,它应该可以正常工作。
parent 需要在调用等待之前关闭 fd[1]
。只要任何进程打开管道的写入端,child 中的读取就会阻塞。在您的情况下,parent 保持写入端打开,等待 child 终止。并且 child 在等待 parent 关闭管道的写入端的读取时被阻塞。换句话说,写:
close(fd[1]);
wait(0);
并且,正如 ctx 指出的那样,您需要关闭 parent 中的标准输出,或者停止无意义的 dup2
。