免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: cookis
打印 上一主题 下一主题

epoll 边缘触发模式的问题 [复制链接]

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
41 [报告]
发表于 2008-11-09 19:41 |只看该作者
原帖由 wishel 于 2008-11-9 12:08 发表



lt模式下,默认不可读,只有epoll通知你可读才是可读,否则不可读。
et模式下,默认可读。你可以随便读,直到发生EAGAIN。可读时读和不读,怎么读都由你自己决定,中间epoll不管。
EAGAIN后不可读了,等 ...



我知道这个意思,既然EAGAIN后epoll才重新改变事件,那在程序中肯定要读到EAGAIN才行了,但man的这句话就很难懂了 :

Q9 Do I need to continuously read/write an fd until EAGAIN when using the EPOLLET flag ( Edge Triggered behaviour ) ? (意思是,当用EPOLLET 时,是否需要连续的读直到遇到EAGAIN为止?)
A9  No you don't.  (意思是,不,你不用这样)

论坛徽章:
0
42 [报告]
发表于 2008-11-09 21:38 |只看该作者
原帖由 chenzhanyiczy 于 2008-11-9 19:41 发表



我知道这个意思,既然EAGAIN后epoll才重新改变事件,那在程序中肯定要读到EAGAIN才行了,但man的这句话就很难懂了 :

Q9 Do I need to continuously read/write an fd until EAGAIN when using the EP ...


Q:  Do I need to continuously ... until ...
A:  No you don't. When and how ... is entirely up to you.

ps: 回答说 if you call read(2) by asking to read a certain amount of data and read(2) returns a lower number of bytes, you can be sure to have exhausted the read I/O space for such file descriptor.
那么此时是不是不用继续再一次read到EAGAIN。如果此后有人写东西进来,fd变为可读,是不是也会触发et?我现在没有linux环境,大家可以试一下。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
43 [报告]
发表于 2008-11-09 22:49 |只看该作者
所以嘛。。,不过我觉得只有read到EAGAIN下,fd才能再次变成新事件;不过这又跟上面那段e文有冲突

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
44 [报告]
发表于 2008-11-10 10:09 |只看该作者

回复 #36 wishel 的帖子

为什么说et效率高呢,它默认fd是一直可读的。可以一直读直到EAGAIN发生。也就是说它只监控状态的变化。
什么时候能体现这种效率呢?当环境中存在大量慢速连接的时候。因为处理很慢,lt会不停的触发event,但是et就不会。


我理解的是:
1. 慢速链接. 那是网络层的问题了.. 相对于本地向外发送数据可能有影响. 但在接收动作上应该没什么影响. 它一旦到了TCP缓冲区. 那就完全是内存拷贝了. 我想epoll也是监测的TCP缓冲区吧. 如果一个包在网际中漫游了一个小时才到本机. 那么不管是ET还是LT都是一个小时以后才会触发.(LT也不会一直触发一个小时吧)
对于EAGAIN. 如果缓冲区内有10K的数据. LT模式下.你一次读1K. epoll肯定会多次检测到可读事件. 不是一个高效的方法.但如果你一直读.直到返回EAGAIN. 这样应该和ET模式是一样的.

在我看来在同样都读到状态改变的情况下(也就是调用epoll_wait的次数相同的情况下).
两种模式的区别:
ET. 必须要读到errno == EAGAIN
LT. 只需要读到返回长度小于请求长度就可以了. 没有必要再调用 一次recv. 让errno == EAGAIN

可能大家在用LT 模式下都是每次先读一个消息头. 然后从消息头中得到Content-Length. 然后再recv(Content-length),
这样的接收方式.确实比ET模式效率低了.

论坛徽章:
0
45 [报告]
发表于 2008-11-10 10:22 |只看该作者
楼主,你用的man page已经过时了.最新的man page对你这个问题的回答变了,没有no,you don't这句困扰你的话了 .

Q9  Do I need to continuously read/write a file descriptor until EAGAIN when
           using the EPOLLET flag (edge-triggered behavior) ?

A9  Receiving an event from epoll_wait(2) should suggest to you that such file
           descriptor is ready for the requested I/O operation.  You must consider it
           ready until the next (non-blocking) read/write yields EAGAIN.  When and
           how you will use the file descriptor is entirely up to you.

           For packet/token-oriented files (e.g., datagram socket, terminal in
           canonical mode), the only way to detect the end of the read/write I/O
           space is to continue to read/write until EAGAIN.

           For stream-oriented files (e.g., pipe, FIFO, stream socket), the condition
           that the read/write I/O space is exhausted can also be detected by
           checking the amount of data read from / written to the target file
           descriptor.  For example, if you call read(2) by asking to read a certain
           amount of data and read(2) returns a lower number of bytes, you can be
           sure of having exhausted the read I/O space for the file descriptor.  The
           same is true when writing using write(2).  (Avoid this latter technique if
           you cannot guarantee that the monitored file descriptor always refers to a
           stream-oriented file.)


链接是 http://www.kernel.org/doc/man-pa ... s/man7/epoll.7.html

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
46 [报告]
发表于 2008-11-10 11:02 |只看该作者

回复 #45 lipingtababa 的帖子

确实我的版本是老了..但意思没什么变. 不过按照它的 "For stream-oriented files" 做法. 只收到返回值小于请求值的时候. 会丢掉好多 close 事件. 你可以做个实验.

论坛徽章:
0
47 [报告]
发表于 2008-11-10 13:42 |只看该作者
原帖由 cookis 于 2008-11-10 10:09 发表


我理解的是:
1. 慢速链接. 那是网络层的问题了.. 相对于本地向外发送数据可能有影响. 但在接收动作上应该没什么影响. 它一旦到了TCP缓冲区. 那就完全是内存拷贝了. 我想epoll也是监测的TCP缓冲区吧. 如果一 ...


所谓慢速链接,不是传输速度慢,是处理速度。包括协议处理和应用处理的速度。epoll只是通知应用可以读了,怎么处理,应用说了算,所以即使epoll lt每秒通知应用100次,它可能只处理1次(根据自己的逻辑判断),而且这一次也不一定是因为epoll的通知。这样fd就一直读不完,lt就会一直监控和通知,浪费资源。et就不会。
et模式的应用的写法可能是,一直认为fd可读,想什么时候读就什么时候读。直到读到EAGAIN,这时候知道fd不可读了。就不再读。epoll通知fd又可读了,应用知道后,不一定马上就去读。再次变为前面状态:认为fd可读,想什么时候读就什么时候读。

[ 本帖最后由 wishel 于 2008-11-10 13:44 编辑 ]

论坛徽章:
0
48 [报告]
发表于 2008-11-10 13:50 |只看该作者
原帖由 cookis 于 2008-11-10 11:02 发表
确实我的版本是老了..但意思没什么变. 不过按照它的 "For stream-oriented files" 做法. 只收到返回值小于请求值的时候. 会丢掉好多 close 事件. 你可以做个实验.


那就是说光缓冲区读空了还不行,一定要读出个EAGAIN才可以使下次新近来数据时et触发?楼主可不可以再做个试验,把这下一次的close变成继续发一点数据,看看会不会丢。

不过我认为这种处理在语义上可以理解的。从用户的角度看,用户可以一直读,因为没有EAGAIN,就认为一直可读,即使返回值小于请求值,那还继续是可读。不可读只能是读出EAGAIN,再次可读就等et通知。

论坛徽章:
0
49 [报告]
发表于 2008-11-10 13:52 |只看该作者
就是说,用户的应用处理(比如读入)不一定是在et通知后执行的那段代码。那段代码也许只是执行了某种状态设置。真正的处理在其他处,要处理时,先要检验下该状态。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
50 [报告]
发表于 2008-11-10 14:42 |只看该作者

回复 #48 wishel 的帖子

所谓慢速链接,不是传输速度慢,是处理速度。包括协议处理和应用处理的速度。epoll只是通知应用可以读了,怎么处理,应用说了算,所以即使epoll lt每秒通知应用100次,它可能只处理1次(根据自己的逻辑判断),而且这一次也不一定是因为epoll的通知。


哦..这个可能跟应用模式有关系了..我在一般是在epoll 的线程来读取数据..然后交给数据处理线程来解析. 而不是只是标记一下这个fd可读..然后由其他线程来读取数据. 我觉得这样不可取..因为还得设置一个通知数据读取线程什么时候可读了的通知机制(或者你一直循环判断是否可读.但更CPU会100%)..这不是多此一举吗?

那就是说光缓冲区读空了还不行,一定要读出个EAGAIN才可以使下次新近来数据时et触发?楼主可不可以再做个试验,把这下一次的close变成继续发一点数据,看看会不会丢。

这个当然是不会丢的..正因为close事件是没有数据的. 但又是一个可读事件. 才会导致丢失close 事件. (这是在recv返回长度小于请求长度后就停止recv的情况下. 而非遇到EAGAIN)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP