为什么在这种情况下read()块?(linux epoll)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了为什么在这种情况下read()块?(linux epoll),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3708字,纯文字阅读大概需要6分钟。
内容图文
![为什么在这种情况下read()块?(linux epoll)](/upload/InfoBanner/zyjiaocheng/964/6521a25c2b1147a5b1d0023c58920823.jpg)
我是unix编程的新手,今天我正在尝试epoll但遇到问题.
在级别触发模式下,我认为包括Ctrl-D在内的每个新输入事件都会导致epoll_wait返回.它工作正常.但是当我输入像aaa这样的东西时,按下Ctrl-D,读取块.当我键入Ctrl-D时,它不会.
你能解释一下会发生什么吗?
我应该在epoll_wait完成并根据fd准备好时读取所有数据吗?
谢谢!
#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc, const char *argv[]) {
// create event
struct epoll_event stdin_ev, events[10];
// set event
stdin_ev.events = EPOLLIN;
stdin_ev.data.fd = STDIN_FILENO;
// create epoll
int epfd = epoll_create(1), i, rcnt;
char c;
// set monitoring STDIN_FILENO
epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev);
while(1) {
int ret = epoll_wait(epfd, events, 1, 1000);
// timeout or failed
if(ret == 0) {
fprintf(stdout, "timeout\n");
continue;
} else if (ret < 0) {
perror("ret<0");
exit(EXIT_FAILURE);
}
// readable
fprintf(stdout, "%d event(s) happened...\n", ret);
for(i=0; i < ret; i++) {
if(events[i].data.fd == STDIN_FILENO &&\
events[i].events&EPOLLIN) {
// read a char
rcnt = read(STDIN_FILENO, &c, 1);
// if read 0 char, EOF?
if(rcnt != 1) {
fprintf(stdout, "read %d byte\n", rcnt);
continue;
}
// else print ascii
fprintf(stdout, "ascii code: %d\n", c);
}
}
}
close(epfd);
return 0;
}
输入:aaa Ctrl-D,结果:
timeout
aaa // <-- `aaa`+`Ctrl-D`
1 event(s) happened...
ascii code: 97
1 event(s) happened...
ascii code: 97
1 event(s) happened...
ascii code: 97
1 event(s) happened...
^C // <-- read block here, `Ctrl-C` to kill
然后我尝试将STDIN_FILENO设置为非阻塞,我发现虽然read()返回-1,但epoll_wait仍然告诉我有一个可读的事件.但是如果我只输入Ctrl-D,则read()返回0.
#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int set_nonblock(int sfd) {
int flags, s;
flags = fcntl(sfd, F_GETFL, 0);
if(flags == -1) {
perror("fcntl");
return -1;
}
flags |= O_NONBLOCK;
s = fcntl(sfd, F_SETFL, flags);
if(s == -1) {
perror("fcntl");
return -1;
}
return 0;
}
int main(int argc, const char *argv[]) {
// create event
struct epoll_event stdin_ev, events[10];
// set event
stdin_ev.events = EPOLLIN;
stdin_ev.data.fd = STDIN_FILENO;
// create epoll
int epfd = epoll_create(1), i, rcnt;
char c;
// set nonblocking
if(set_nonblock(STDIN_FILENO) != 0) {
exit(EXIT_FAILURE);
};
// set monitoring STDIN_FILENO
epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev);
while(1) {
int ret = epoll_wait(epfd, events, 1, 1000);
// timeout or failed
if(ret == 0) {
fprintf(stdout, "timeout\n");
continue;
} else if (ret < 0) {
perror("ret<0");
exit(EXIT_FAILURE);
}
// readable
fprintf(stdout, "%d event(s) happened...\n", ret);
for(i=0;i < ret;i++) {
if(events[i].data.fd == STDIN_FILENO &&\
events[i].events&EPOLLIN) {
// read a char
rcnt = read(STDIN_FILENO, &c, 1);
// if read 0 char, EOF?
if(rcnt != 1) {
fprintf(stdout, "read %d byte\n", rcnt);
continue;
}
// else print ascii
fprintf(stdout, "ascii code: %d\n", c);
}
}
}
close(epfd);
return 0;
}
结果:
timeout
1 event(s) happened... // <-- `Ctrl-D`
read 0 byte // <-- read() -> 0
timeout
timeout
aaa // `aaa`+`Ctrl-D`
1 event(s) happened...
ascii code: 97
1 event(s) happened...
ascii code: 97
1 event(s) happened...
ascii code: 97
read -1 byte // `EPOLLIN` still happens.
timeout
^C
解决方法:
据我了解的行为:
如果您输入’ENTER’而不是ctrl-D,则报告4个事件与CTRL-D一样.我们看到ascii代码:10代表换行.使用CTRL-D读取块.
CTRL-D不发信号通知EOF,而是清除目前为止输入的数据. CTRL-D本身被认为是一个事件.但实际上没有数据可以提取出来
FD.并且鉴于套接字是阻塞的,我们最终会遇到读取在另一组事件发生之前没有返回的情况.
现在,如果CTRL-D是第一个事件,则通过读取yeilding零来识别它.发出EOF条件信号.如果有东西需要刷新,就不会发生这种情况.
当您使套接字无阻塞时,CTRL-D读取返回-1,并将errno设置为EAGAIN.这意味着’现在没有数据要读.等会再试’.
内容总结
以上是互联网集市为您收集整理的为什么在这种情况下read()块?(linux epoll)全部内容,希望文章能够帮你解决为什么在这种情况下read()块?(linux epoll)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。