手动输入时,Poll 对 stdin 起作用,但当输入通过管道传输且未重定向时则不起作用
Poll works on stdin when entering manually, but not when input is piped and not redirected
考虑这个 C 程序:
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
#define TIMEOUT 500 // 0.5 s
#define BUF_SIZE 512
int fd_can_read(int fd, int timeout) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
if (poll(&pfd, 1, timeout)) {
if (pfd.revents & POLLIN) {
return 1;
}
}
return 0;
}
int main(int argv, char **argc) {
int fd;
size_t bytes_read;
char buffer[BUF_SIZE];
fd = STDIN_FILENO;
while (1) {
if (fd_can_read(fd, TIMEOUT)) {
printf("Can read\n");
bytes_read = read(fd, buffer, sizeof(buffer));
printf("Bytes read: %zu\n", bytes_read);
}
else {
printf("Can't read\n");
}
}
}
它尝试轮询给定的文件描述符(在本例中是 stdin 的 fd),并在它可供读取时尝试从中读取。这是一个名为 "input":
的示例输入文件
stuff to be read
假设我 运行 程序,提供一些输入并关闭它:
./a.out
test
Can read
Bytes read: 5
Can't read
Can't read
...
所以让我们尝试通过 piping/redirecting 将文件的内容读取到我程序的 stdin
中:
cat input | ./a.out # Or ./a.out < input
Bytes read: 0
Can read
Bytes read: 0
Can read
...
现在,轮询 returns 立即(不等待超时到 运行 结束),并给出我没有预料到的结果。我知道 poll()
不能正确处理文件,但如果我没记错的话,我不是在读取文件。
问题是poll
(just like select
) only tell you that a call to e.g. read
不会阻塞。它不会告诉你是否真的有什么可读的。
如果你阅读 the read
manual page 你会看到当它 returns 0
时它意味着 文件结束 (或连接关闭套接字)。
poll
告诉你的是 read
可以无阻塞地调用,而 read
通过返回 0
告诉你的是没有什么更多的阅读。
你会得到类似的 "false positive" 通过按文件结束快捷键(默认情况下 Ctrl-D POSIX 系统像 Linux) 对于非管道或 -redirected 输入示例。
考虑这个 C 程序:
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
#define TIMEOUT 500 // 0.5 s
#define BUF_SIZE 512
int fd_can_read(int fd, int timeout) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
if (poll(&pfd, 1, timeout)) {
if (pfd.revents & POLLIN) {
return 1;
}
}
return 0;
}
int main(int argv, char **argc) {
int fd;
size_t bytes_read;
char buffer[BUF_SIZE];
fd = STDIN_FILENO;
while (1) {
if (fd_can_read(fd, TIMEOUT)) {
printf("Can read\n");
bytes_read = read(fd, buffer, sizeof(buffer));
printf("Bytes read: %zu\n", bytes_read);
}
else {
printf("Can't read\n");
}
}
}
它尝试轮询给定的文件描述符(在本例中是 stdin 的 fd),并在它可供读取时尝试从中读取。这是一个名为 "input":
的示例输入文件stuff to be read
假设我 运行 程序,提供一些输入并关闭它:
./a.out
test
Can read
Bytes read: 5
Can't read
Can't read
...
所以让我们尝试通过 piping/redirecting 将文件的内容读取到我程序的 stdin
中:
cat input | ./a.out # Or ./a.out < input
Bytes read: 0
Can read
Bytes read: 0
Can read
...
现在,轮询 returns 立即(不等待超时到 运行 结束),并给出我没有预料到的结果。我知道 poll()
不能正确处理文件,但如果我没记错的话,我不是在读取文件。
问题是poll
(just like select
) only tell you that a call to e.g. read
不会阻塞。它不会告诉你是否真的有什么可读的。
如果你阅读 the read
manual page 你会看到当它 returns 0
时它意味着 文件结束 (或连接关闭套接字)。
poll
告诉你的是 read
可以无阻塞地调用,而 read
通过返回 0
告诉你的是没有什么更多的阅读。
你会得到类似的 "false positive" 通过按文件结束快捷键(默认情况下 Ctrl-D POSIX 系统像 Linux) 对于非管道或 -redirected 输入示例。