为什么在这种情况下read()块?(linux epoll)
我是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,"timeoutn"); 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 byten",rcnt); continue; } // else print ascii fprintf(stdout,"ascii code: %dn",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,rcnt; char c; // set nonblocking if(set_nonblock(STDIN_FILENO) != 0) { exit(EXIT_FAILURE); }; // set monitoring STDIN_FILENO epoll_ctl(epfd,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); } } } 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本身被认为是一个事件.但实际上没有数据可以提取出来 现在,如果CTRL-D是第一个事件,则通过读取yeilding零来识别它.发出EOF条件信号.如果有东西需要刷新,就不会发生这种情况. 当您使套接字无阻塞时,CTRL-D读取返回-1,并将errno设置为EAGAIN.这意味着’现在没有数据要读.等会再试’. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |