C - 如何在只读取单个字符时检测管道中的 EOF?
C - How to detect EOF in pipe when reading only single char?
如 this 回答中所述,我希望 reader 进程 在 [= 之后立即捕获 EOF
21=]writer 进程 关闭所有相关的文件描述符。
但这并没有发生,这个程序最终陷入了无限循环。
Parent 等待它 child 完成 & child 等待 EOF
发出关闭管道的信号。
为什么 reader 进程没有收到 EOF
?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#define STRING_TO_SEND "Hello, world!\n"
int main() {
int fd[2], i = 0;
__pid_t pid;
char _char;
ssize_t nbytes;
pipe(fd);
pid = fork();
if (pid == -1) {
// Error
perror("Error forking!");
return EXIT_FAILURE;
} else if (pid == 0) {
// Child
close(fd[1]);
while ((nbytes = read(fd[0], &_char, 1)) != EOF) {
if (nbytes == 0)
continue;
putchar(_char);
}
close(fd[0]);
} else {
// Parent
close(fd[0]);
for(;;) {
_char = STRING_TO_SEND[i++];
write(fd[1], &_char, 1);
if (_char == '[=10=]')
break;
}
close(fd[1]);
close(STDOUT_FILENO);
while (wait(NULL)>0) {}
}
return 0;
}
您只是误解了 read()
的 "end of file" 指示,它只是意味着 read()
不再需要阅读(在这种情况下,read() returns 0)。但是 read()
实际上 return 值 EOF
。所以你的条件应该是:
while ((nbytes = read(fd[0], &_char, 1)) > 0) {
另外 __pid_t
是您的 C 库的内部类型。你不应该使用它;只需使用 pid_t
.
有关详细信息,请参阅 read(2) 的手册页。
EOF
是一个常量,通常定义为 -1,stdio
(原始系统调用周围的 C 库缓冲层)用于在 getchar()
等函数中发出文件结束信号它将 returned 字符与文件结束信号混为一谈。
read
通过简单地 returning 0
发出文件结束信号。请注意,如果出现错误,它也可以 return -1(例如,如果读取在读取任何内容之前被信号处理程序中断,您可以获得 EINTR
)。
因此,您想要的是:
while ((nbytes = read(fd[0], &_char, 1)) > 0){ /*...*/ }
if (0>nread) { /*report error (or maybe repeat if it's EINTR)*/ }
联机帮助页(read(2)) or the POSIX spec for read 记录所有这些内容。
如 this 回答中所述,我希望 reader 进程 在 [= 之后立即捕获 EOF
21=]writer 进程 关闭所有相关的文件描述符。
但这并没有发生,这个程序最终陷入了无限循环。
Parent 等待它 child 完成 & child 等待 EOF
发出关闭管道的信号。
为什么 reader 进程没有收到 EOF
?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#define STRING_TO_SEND "Hello, world!\n"
int main() {
int fd[2], i = 0;
__pid_t pid;
char _char;
ssize_t nbytes;
pipe(fd);
pid = fork();
if (pid == -1) {
// Error
perror("Error forking!");
return EXIT_FAILURE;
} else if (pid == 0) {
// Child
close(fd[1]);
while ((nbytes = read(fd[0], &_char, 1)) != EOF) {
if (nbytes == 0)
continue;
putchar(_char);
}
close(fd[0]);
} else {
// Parent
close(fd[0]);
for(;;) {
_char = STRING_TO_SEND[i++];
write(fd[1], &_char, 1);
if (_char == '[=10=]')
break;
}
close(fd[1]);
close(STDOUT_FILENO);
while (wait(NULL)>0) {}
}
return 0;
}
您只是误解了 read()
的 "end of file" 指示,它只是意味着 read()
不再需要阅读(在这种情况下,read() returns 0)。但是 read()
实际上 return 值 EOF
。所以你的条件应该是:
while ((nbytes = read(fd[0], &_char, 1)) > 0) {
另外 __pid_t
是您的 C 库的内部类型。你不应该使用它;只需使用 pid_t
.
有关详细信息,请参阅 read(2) 的手册页。
EOF
是一个常量,通常定义为 -1,stdio
(原始系统调用周围的 C 库缓冲层)用于在 getchar()
等函数中发出文件结束信号它将 returned 字符与文件结束信号混为一谈。
read
通过简单地 returning 0
发出文件结束信号。请注意,如果出现错误,它也可以 return -1(例如,如果读取在读取任何内容之前被信号处理程序中断,您可以获得 EINTR
)。
因此,您想要的是:
while ((nbytes = read(fd[0], &_char, 1)) > 0){ /*...*/ }
if (0>nread) { /*report error (or maybe repeat if it's EINTR)*/ }
联机帮助页(read(2)) or the POSIX spec for read 记录所有这些内容。