我多次检查此代码,不明白为什么poll()立即返回?
这里文件已打开以供读取,应等待事件。如何使其等待输入?
#include <iostream>
#include <poll.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
ssize_t read_out_to_the_end(int fd){
char chunk[1024];
ssize_t ret = 0, n;
while((n = ::read(fd, chunk, sizeof chunk)) > 0){
ret += n;
cerr << "read chunk: " << n << " | ";
cerr.write(chunk, n);
cerr << endl;
}
if (n < 0) {
cerr << "err in read" << endl;
}
else if (ret == 0){
cerr << "nothing to read" << endl;
}
return ret;
}
int main() {
int bininfd = open("bin-in", O_RDONLY | O_CREAT);//, 0644/*S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH*/);
if (bininfd < 0) {
perror("err in open(binin)");
return -1;
}
struct pollfd pollfds[] = {
{bininfd, POLLIN, 0},
};
auto&[pfd] = pollfds;
while (1) {
pfd.revents = 0; // cleanup, shouldn't it be redundant
int pollret = poll(pollfds, 1, -1);
if (pollret > 0) {
if (pfd.revents & POLLIN) {
cerr << "(pfd.revents & POLLIN)" << endl;
read_out_to_the_end(pfd.fd);
}
} else if (pollret == 0) {
cerr << "poll timed out" << endl;
continue;
} else {
cerr << "check for error" << endl;
continue;
}
}
}
输出为
(pfd.revents & POLLIN)
nothing to read
(pfd.revents & POLLIN)
nothing to read
(pfd.revents & POLLIN)
nothing to read
(pfd.revents & POLLIN)
nothing to read
(pfd.revents & POLLIN)
............... etc ....................
更新:
read_out_to_the_end()
有几个问题:
ret
未初始化。
while
循环在应分配n
时递增。但是,如果while
循环达到EOF,则即使在达到EOF之前实际读取了数据,if( n == 0)
也将为true。
chunk
可以为空值终止,但是根据输入数据,它也可能也接收空值。因此,不应使用cerr
将其写入cout
(为什么不使用operator<<
?),请改用cerr.write()
,以便您可以将读取的实际字节数传递给它。
尝试以下方法:
ssize_t read_out_to_the_end(int fd){
char chunk[1024];
ssize_t ret = 0, n;
while((n = ::read(fd, chunk, sizeof chunk)) > 0){
ret += n;
cerr << "read chunk: " << n << " | ";
cerr.write(chunk, n);
cerr << endl;
}
if (n < 0) {
cerr << "err in read" << endl;
}
else if (ret == 0){
cerr << "nothing to read" << endl;
}
return ret;
}
int main() {
int bininfd = open("bin-in", O_RDONLY | O_CREAT);//, 0644/*S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH*/);
if (bininfd < 0) {
perror("err in open(binin)");
return -1;
}
pollfd pfd = {};
pfd.fd = bininfd;
pfd.events = POLLIN;
while (true) {
pfd.revents = 0; // cleanup, shouldn't it be redundant
int pollret = poll(&pfd, 1, -1);
if (pollret > 0) {
if (pfd.revents & POLLIN) {
cerr << "(pfd.revents & POLLIN)" << endl;
read_out_to_the_end(pfd.fd);
}
} else if (pollret == 0) {
cerr << "poll timed out" << endl;
continue;
} else {
cerr << "poll error " << errno << endl;
break;
}
}
}
此外,open()
documentation说:
open()
自变量指定在创建新文件时应用的文件模式位。 [mode
中指定O_CREAT或O_TMPFILE时必须提供此参数];如果既未指定O_CREAT也未指定O_TMPFILE,则忽略flags
。有效模式由进程的mode
以通常的方式修改:在没有默认ACL的情况下,创建的文件的模式为umask
。请注意,此模式仅适用于将来对新创建文件的访问。创建只读文件的(mode & ~umask)
调用很可能会返回读/写文件描述符。
open()
或poll
永远不会在常规文件上阻止。他们总是将常规文件返回为“就绪”。如果您想使用select
来完成poll
的操作,那么您走的路就错误。