epoll边缘触发out 什么时候会触发

简述Linux&Epoll&ET模式EPOLLOUT和EPOLLIN触发时刻
#define MAXLINE 5
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 4800
#define INFTIM 1000
char *g_local_addr="10.12.22.241";
void setnonblocking(int sock)
opts=fcntl(sock,F_GETFL);
if (opts&0)
perror("fcntl(sock,GETFL)");
opts = opts|O_NONBLOCK;
if (fcntl(sock,F_SETFL,opts)&0)
perror("fcntl(sock,SETFL,opts)");
int main()
int i, maxi, listenfd, connfd, sockfd,epfd,
char line[MAXLINE];
struct epoll_event ev,events[20];
struct sockaddr_
struct sockaddr_
listenfd = socket(AF_INET, SOCK_STREAM, 0);
epfd = epoll_create(256);
setnonblocking(listenfd);
ev.data.fd=
ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
inet_aton(g_local_addr,&(serveraddr.sin_addr));
serveraddr.sin_port=htons(SERV_PORT);
bind(listenfd,(sockaddr *)&serveraddr,
sizeof(serveraddr));
listen(listenfd, LISTENQ);
cout&&" server on ip : "&&g_local_addr&&"
:"&&SERV_PORT&&
for ( ; ; )
nfds=epoll_wait(epfd,events,20,500);
for (i=0;i
if (events[i].data.fd==listenfd)
if (events[i].events&EPOLLIN)
cout&&" listenfd :"&&listenfd&& " with
EPOLLIN"&&
cout&&" listenfd :"&&listenfd&& " not with
EPOLLIN"&&
if (events[i].events&EPOLLOUT)
cout&&" listenfd :"&&listenfd&& " with
EPOLLOUT"&&
cout&&" listenfd :"&&listenfd&& " not with
EPOLLOUT"&&
connfd = accept(listenfd,(sockaddr *)&clientaddr,
if (connfd&0)
perror("connfd&0");
setnonblocking(connfd);
char *str = inet_ntoa(clientaddr.sin_addr);
cout && "accapt a connection from " && str
ev.data.fd=
ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
cout&&"---------------------------------------------------"&&
else if (events[i].events&EPOLLIN)
cout&&"***********process in
event**********"&&
if (events[i].events&EPOLLIN)
cout&&" fd :"&&events[i].data.fd&& " with
EPOLLIN"&&
cout&&" fd :"&&events[i].data.fd&& " not
with EPOLLIN"&&
if ( (sockfd = events[i].data.fd) & 0)
if ( (n = read(sockfd, line, MAXLINE)) &
if (errno == ECONNRESET)
close(sockfd);
events[i].data.fd = -1;
std::cout&&"readline error"&&std::
else if (n == 0)
close(sockfd);
events[i].data.fd = -1;
line[n] = '\0';
cout && "read " && line &&
if (events[i].events&EPOLLOUT)
cout&&" fd :"&&events[i].data.fd&& " with
EPOLLOUT"&&
write(sockfd, line, n);
cout&&" fd :"&&events[i].data.fd&& " not
with EPOLLOUT"&&
//ev.data.fd=
//ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
//epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
cout&&"---------------------------------------------------"&&
else if (events[i].events&EPOLLOUT)
cout&&"***********process out
event**********"&&
if (events[i].events&EPOLLIN)
cout&&" fd :"&&events[i].data.fd&& " with
EPOLLIN"&&
cout&&" fd :"&&events[i].data.fd&& " not
with EPOLLIN"&&
if (events[i].events&EPOLLOUT)
cout&&" fd :"&&events[i].data.fd&& " with
EPOLLOUT"&&
cout&&" fd :"&&events[i].data.fd&& " not
with EPOLLOUT"&&
sockfd = events[i].data.
write(sockfd, line, n);
//ev.data.fd=
//ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
//epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
cout&&"---------------------------------------------------"&&
#define MAXLINE 80
#define SERV_PORT 4800
char *g_local_addr="10.12.22.241";
int main(int argc, char *argv[])
struct sockaddr_
char buf[MAXLINE];
int sockfd,
if (argc != 2)
fputs("usage: ./client message\n", stderr);
str = argv[1];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, g_local_addr,
&servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
connect(sockfd, (struct sockaddr *)&servaddr,
sizeof(servaddr));
write(sockfd, str, strlen(str));
n = read(sockfd, buf, MAXLINE);
cout&&" read "&&n&&"
//sleep(5);
//write(sockfd, str, strlen(str));
//sleep(100);
//n = read(sockfd, buf, MAXLINE);
//printf("Response from server:\n");
//write(STDOUT_FILENO, buf, n);
close(sockfd);
//上述情况(1)无论如何也不会触发EPOLLOUT事件,(2)同时会在EPOLLIN时携带EPOLLOUT事件.
情况(1)分析:
ET模式称为边缘触发模式,顾名思义,不到边缘情况,是死都不会触发的。
EPOLLOUT事件:
EPOLLOUT事件只有在连接时触发一次,表示可写,其他时候想要触发,那要先准备好下面条件:
1.某次write,写满了发送缓冲区,返回错误码为EAGAIN。
2.对端读取了一些数据,又重新可写了,此时会触发EPOLLOUT。
简单地说:EPOLLOUT事件只有在不可写到可写的转变时刻,才会触发一次,所以叫边缘触发,这叫法没错的!
其实,如果真的想强制触发一次,也是有办法的,直接调用epoll_ctl重新设置一下event就可以了,event跟原来的设置一模一样都行(但必须包含EPOLLOUT),关键是重新设置,就会马上触发一次EPOLLOUT事件。
1.&缓冲区由满变空.
2.同时注册EPOLLIN&|&EPOLLOUT事件,也会触发一次EPOLLOUT事件
这个两个也会触发EPOLLOUT事件
EPOLLIN事件:
EPOLLIN事件则只有当对端有数据写入时才会触发,所以触发一次后需要不断读取所有数据直到读完EAGAIN为止。否则剩下的数据只有在下次对端有写入时才能一起取出来了。
现在明白为什么说epoll必须要求异步socket了吧?如果同步socket,而且要求读完所有数据,那么最终就会在堵死在阻塞里。
情况(2)分析:
ET时有IN事件发生时,这时一般都可以写,“顺便”就把可写事件带回来了,大概设计者觉得虽然是ET,
多给事件总不会有错Epoll ET模型下,为什么每次EPOLLIN事件都会带一次EPOLLOUT事件?
[问题点数:40分,结帖人zapperstab]
Epoll ET模型下,为什么每次EPOLLIN事件都会带一次EPOLLOUT事件?
[问题点数:40分,结帖人zapperstab]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2013年10月 Linux/Unix社区大版内专家分月排行榜第二2013年9月 Linux/Unix社区大版内专家分月排行榜第二
2013年12月 Linux/Unix社区大版内专家分月排行榜第三2013年11月 Linux/Unix社区大版内专家分月排行榜第三2013年6月 Linux/Unix社区大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。ET模式下,EPOLLOUT触发条件有:1.缓冲区满--&缓冲区非满;2.同时监听EPOLLOUT和EPOLLIN事件 时,当有IN 事件发生,都会顺带一个OUT事件;3.一个客户端connect过来,accept成功后会触发一次OUT事件。其中2最令人费解,内核代码这块有注释,说是一般有IN 时候都能OUT,就顺带一个,多给了个事件。。以上,当只监听IN事件,读完数据后改为监听OUT事件,有时候会发现触发OUT事件并不方便,想要强制触发,可以重新设置一次要监听的events,带上EPOLLOUT即可。另:一道腾讯后台开发的面试题使用Linux epoll模型,水平触发模式;当socket可写时,会不停的触发socket可写的事件,如何处理?第一种最普遍的方式:需要向socket写数据的时候才把socket加入epoll,等待可写事件。接受到可写事件后,调用write或者send发送数据。当所有数据都写完后,把socket移出epoll。这种方式的缺点是,即使发送很少的数据,也要把socket加入epoll,写完后在移出epoll,有一定操作代价。一种改进的方式:开始不把socket加入epoll,需要向socket写数据的时候,直接调用write或者send发送数据。如果返回EAGAIN,把socket加入epoll,在epoll的驱动下写数据,全部数据发送完毕后,再移出epoll。这种方式的优点是:数据不多的时候可以避免epoll的事件处理,提高效率。EPOLLERR什么时候会触发_百度知道epoll水平触发和边沿触发各有啥优劣? - 开源中国社区
当前访客身份:游客 [
当前位置:
tx面试题,我的回答是水平触发除了编程简单点没任何优势(faster poll),epoll的坑manpage很详细,
然后面试官让我回去再看看书。。。
共有0个答案
更多开发者职位上
有什么技术问题吗?
UchihaR...的其它问题
类似的话题}

我要回帖

更多关于 nginx epoll 触发模式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信