免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: wyezl

epoll模型的使用及其描述符耗尽问题的探讨 [复制链接]

论坛徽章:
0
发表于 2006-08-25 22:57 |显示全部楼层
EAGAIN
             发生这种erro,大多数应该是你程序逻辑的错误。
         这是因为,当select/poll/epoll返回的时候,这些api只是说可以读了,但是没有说可以读多少。
         val=read(fd,buf,n)。如果val已经小于n了,你还读此fd,在__大多数__情况下是会EAGAIN。
         不过,也可以不改,直接再把这些fd放到fdset中继续监测也是可以的。
         
         
     为什么读一次就出错,我推断是这样的。
         就select/poll来说erro也是readable。
         推测epoll也是采取这种策略。所以才有你这种错误。
         这也就说明了,为什么访问量这么大却没有错误发生!你把错误也作为了readable了。
     

        至于llegal seek 。
         不太好说,看不到你的程序。
         不过我觉得你肯定没有seek一个socket。

[ 本帖最后由 nuclearweapon 于 2006-8-27 20:48 编辑 ]

论坛徽章:
0
发表于 2006-08-27 00:13 |显示全部楼层
EPOLLET 是边沿触发。如果epoll_wait返回一个可读的文件描述符,必须要把它缓冲区中的数据都读出来。如果没有读完,就继续下一次epoll_wait(),epoll就不会在这个描述符上被唤醒。

请参考MAN手册的建议

The suggested way to use epoll as an Edge Triggered (EPOLLET) interface is below, and possible pitfalls to avoid follow.

i   with non-blocking file descriptors
ii  by going to wait for an event only after read(2) or write(2) return EAGAIN

[ 本帖最后由 精简指令 于 2006-8-27 00:37 编辑 ]

论坛徽章:
0
发表于 2006-08-27 00:36 |显示全部楼层
突然发现一个问题:

你使用了 EPOLLET(边沿触发)  和 非阻塞IO。

但是在接收数据时,你只接收一次,没有等到recv返回EAGAIN,就设置EPOLLOUT继续等待了。

假如这个描述符的缓冲区内还有数据没有读完,它就可能“死”在epoll里,不再被返回了。

我看到过一个人非常形象的描述这个问题:
  水平触发 --> 有事了,你不处理?不断骚扰你直到你处理。
  边沿触发 --> 有事了,告诉你一次,你不处理?拉倒!

[ 本帖最后由 精简指令 于 2006-8-27 00:37 编辑 ]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2006-08-27 09:41 |显示全部楼层
原帖由 精简指令 于 2006-8-27 00:36 发表
突然发现一个问题:

你使用了 EPOLLET(边沿触发)  和 非阻塞IO。

但是在接收数据时,你只接收一次,没有等到recv返回EAGAIN,就设置EPOLLOUT继续等待了。

假如这个描述符的缓冲区内还有数据没有读完, ...


这么一说我终于理解level和edge的区别了
我只用level和阻塞socket,所以没碰到类似问题

论坛徽章:
0
发表于 2006-08-27 16:48 |显示全部楼层
我又按照下面步骤测试了一下

第一次:
1、epoll 在一个文件描述符上,等待一个EPOLLIN事件。
2、epoll 在这个文件描述符上被唤醒,然后只接收部分数据。(没有等到EAGAIN)
3、继续等待这个EPOLLIN事件。
4、epoll 没有再被唤醒。

正常现象。

第二次:
1、epoll 在一个文件描述符上,等待一个EPOLLIN事件。
2、epoll 在这个文件描述符上被唤醒,然后只接收部分数据。(没有等到EAGAIN)
3、继续等待这个EPOLLIN事件。
4、epoll 没有再被唤醒。
5、再次收到新数据后,epoll又在这个描述符上被唤醒了。

正常现象。

第三次:
1、epoll 在一个文件描述符上,等待一个EPOLLIN事件。
2、epoll 在这个文件描述符上被唤醒,然后只接收部分数据。(没有等到EAGAIN)
3、不再等待EPOLLIN,继续等待另一个EPOLLOUT事件。
4、epoll 在这个文件描述符上被唤醒了。

我怀疑EPOLLIN和EPOLLOUT是分别处理的。但是,也不能保证这种现象是正常行为。

第四次:
1、epoll 在一个文件描述符上,等待一个EPOLLOUT事件。
2、epoll 在这个文件描述符上被唤醒。
3、继续等待EPOLLOUT事件。
4、epoll 没有被唤醒。
5、收到新的数据,epoll_wait 在这个描述符上返回 EPOLLOUT 事件。

是否说明 IN 和 OUT 事件还是会相互影响呢?

[ 本帖最后由 精简指令 于 2006-8-27 17:01 编辑 ]

论坛徽章:
0
发表于 2006-08-27 19:01 |显示全部楼层
顶,关注楼上的结果。

论坛徽章:
0
发表于 2006-08-28 10:44 |显示全部楼层
谢谢楼上那几个兄弟的热心解答。
我试试把数据都读出来,直到EAGAIN。

论坛徽章:
0
发表于 2006-08-28 11:19 |显示全部楼层
int my_read(int fd,void *buffer,int length)
{
        int bytes_left;
        int bytes_read;
        char *ptr;
        ptr=buffer;
        bytes_left=length;
        while(bytes_left>0)
        {
                bytes_read=read(fd,ptr,bytes_read);

                if(bytes_read<0)
                {
                         if(errno==EINTR)
                                bytes_read=0;
                        else if(errno==EAGAIN)
                                break;
                        else
                        {
                                perror("read");
                                return(-1);
                        }
                }
                else if(bytes_read==0)
                break;

                bytes_left-=bytes_read;
                ptr+=bytes_read;

        }

        return(length-bytes_left);
}

把recv改成这个了,还是不行。

论坛徽章:
0
发表于 2006-08-30 15:54 |显示全部楼层
借光,问一个问题,这里对于同一个fd,只能是发送或者接收是吗?不能用同一个fd进行发送和接收吗?

论坛徽章:
0
发表于 2006-08-30 16:26 |显示全部楼层
本来就是用同一个fd,先接受,再发送的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP