免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
61 [报告]
发表于 2008-11-10 18:29 |只看该作者
原帖由 wishel 于 2008-11-10 18:00 发表
就是说,epoll et把它的event通知塞到这个中间队列里,然后通知线程池的线程去取event通知,取走event通知的线程后面怎么处理是它自己的事情了。各线程是平等的,没有L和F之分,它们唯一要做的就是在取通知的时 ...



我就知道你应该是这么想的.
难道这样就会避免下面这个问题了吗?
但我做了一个实验. 如果 step-3 休息一下..没有recv. 这时候client又发数据过来(epoll 可能当做是新的事件). step-4马上会被唤醒.这时候一个fd会被两个线程操作

所以我说过..只要是线程池. 应该都会存在这个问题.

论坛徽章:
0
62 [报告]
发表于 2008-11-10 18:37 |只看该作者
前面懒了点,没说清楚。前面说的IOCP和epoll语义一样指的是其中一个api,不是说iocp的整体语义
proactor要用的,也就是iocp和aio的语义是:
当fd上I/O完成后,通知预先注册的handler
iocp名字叫完成端口,其实是误导,实际上是一个完成通知队列,队列元素中存放每次I/O结果等参数

注意异步io的语义是,完成后通知,此时io已经完成。
而select,poll,epoll的语义是,ready后通知。就是可读或可写时通知,此时io可以无阻塞进行,但收到通知后是否进行io,什么时候完成io,取决于应用。

所谓用epoll模拟aio,epoll先发readay通知,就是线程收到ready通知后,处理,处理完成后,再发完成通知给应用。这个过程对应用透明,在应用看来,就是一次完成通知。

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

论坛徽章:
0
63 [报告]
发表于 2008-11-10 18:41 |只看该作者
step-3 休息一下..没有recv. 这时候client又发数据过来(epoll 可能当做是新的事件).  


晕死。。。。。还是没搞明白et的语义???
没有recv,client再发数据过来,et怎么会当成新的事件???

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
64 [报告]
发表于 2008-11-10 21:34 |只看该作者
wishel  分析的有道理

不过通过队列来保存fd有一点比较耗时,就是需要互斥,有什么好的方法来避免这个呢,暂时没想出来

论坛徽章:
0
65 [报告]
发表于 2008-11-10 22:14 |只看该作者
原帖由 chenzhanyiczy 于 2008-11-10 21:34 发表
wishel  分析的有道理

不过通过队列来保存fd有一点比较耗时,就是需要互斥,有什么好的方法来避免这个呢,暂时没想出来


想用多线程并发又不想互斥同步,这个貌似无解。

论坛徽章:
0
66 [报告]
发表于 2008-11-11 01:44 |只看该作者
看到这里,我忍不住要说上一说。大家都在讨论EPOLL的ET和LT模式,但是实际具体怎么运作,不知有多少人认真看了代码和做过试验看过效果的。

man说的没有错,但是会让你有个误会。
man说ET模式下,如果接收到了2k数据,但只是读了1k,然后不会再次触发可读事件。这是对的。
读到EAGAIN之后,再来2k的数据,会触发可读事件,也没有错。但是有个细节没有说清楚,那就是如果剩下1k数据的时候,又来了2k的数据,是什么情况。

事实上是会触发EPOLL的可读事件。

试验表明,EPOLL所谓的ET模式,每个数据包都会触发一次可读事件。TCP是流协议,我怎么又说数据包呢,自己去理解下吧。这个情况和我之前想象的有出入。

实际上,EPOLL还是有第三种模式,就是EPOLLONESHOT,这个有点类似一旦触发EPOLL的任意一个事件,立刻将fd从EPOLL中移除。这个才是真正的仅触发一次的模式。

我觉得EPOLL的ET模式,仅仅在多个线程同时对一个epoll调用epoll_wait才适用。因为EPOLLET使得这个事件仅仅在一个线程中触发一次,从而避免了所有线程epoll_wait全部返回的的问题。

论坛徽章:
0
67 [报告]
发表于 2008-11-11 09:05 |只看该作者
原帖由 smzgl 于 2008-11-11 01:44 发表
看到这里,我忍不住要说上一说。大家都在讨论EPOLL的ET和LT模式,但是实际具体怎么运作,不知有多少人认真看了代码和做过试验看过效果的。

man说的没有错,但是会让你有个误会。
man说ET模式下,如果接收到 ...


哈哈,不是man没说清楚,是我没看仔细

      Since even with the edge-triggered epoll multiple events can be  gener-
       ated upon receipt of multiple chunks of data, the caller has the option
       to specify the EPOLLONESHOT flag, to tell epoll to disable the  associ-
       ated  file descriptor after the receipt of an event with epoll_wait(2).
       When the EPOLLONESHOT flag is specified, it is the  caller's  responsi-
       bility   to   rearm   the   file  descriptor  using  epoll_ctl(2)  with
       EPOLL_CTL_MOD.
所以多线程用et时,最好specify the EPOLLONESHOT flag,当读到EAGAIN时(或者返回读到的size小于要读的size时,但是楼主的实验这样会丢掉fin包,如果确实这样,那还是只能再次读出EAGAIN),rearm   the   file  descriptor  using  epoll_ctl(2)  with EPOLL_CTL_MOD

[ 本帖最后由 wishel 于 2008-11-11 09:09 编辑 ]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
68 [报告]
发表于 2008-11-11 10:10 |只看该作者
原帖由 wishel 于 2008-11-10 18:41 发表


晕死。。。。。还是没搞明白et的语义???
没有recv,client再发数据过来,et怎么会当成新的事件???


这点你不要凭空想象 ..你做一下实验.. 在我写我的库时..我已经做了充分的实验.  这个绝对会当做新的事件来触发.
看66楼的哥们说的:
man说的没有错,但是会让你有个误会。
man说ET模式下,如果接收到了2k数据,但只是读了1k,然后不会再次触发可读事件。这是对的。
读到EAGAIN之后,再来2k的数据,会触发可读事件,也没有错。但是有个细节没有说清楚,那就是如果剩下1k数据的时候,又来了2k的数据,是什么情况。

事实上是会触发EPOLL的可读事件。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
69 [报告]
发表于 2008-11-11 10:12 |只看该作者
这贴到此结束吧..

论坛徽章:
0
70 [报告]
发表于 2009-02-03 17:37 |只看该作者

回复 #17 cookis 的帖子

楼主,虽然可能出现如下情况:

客户端发送数据(比如100字节),然后马上调用close关闭socket
这时,服务端可能只检测到一个EPOLLIN事件

但是,此时你在服务端读这个socket时,比如你请求读1000字节,读到100字节客户端数据后
你再读一次,会发现此次读会返回0(也就是说虽然事件合并了,但客户端关闭仍然是可以检测到的)
然后你读到了0,就能检测出此客户端已经关闭

不知道你所谓的“close事件丢失”是什么意思
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP