zoukankan      html  css  js  c++  java
  • IO复用_epoll函数

        由于poll()和select()的局限,2.6内核以上引用了event poll机制(就是说的epoll),虽然比前2个实现复杂得多,epoll解决了它们共有的基本性能问题,并增加了新的特性。

        poll()和select()每次调用的时候,都需要所有被监听的文件的描述符。内核必须遍历所有被监视的文件描述符。当这个表变得很大时,每次调用,都会成为性能降低。

        epoll把监听注册从实际监听中分离出来,从而解决这个问题:一个系统调用初始化一个epoll上下文,另一个从上下文中加入或删除需要监视的文件描述符,第三个执行真正的事件等待(event wait)。

    先来看看常用模型的缺点(如果不摆出来其他模型的缺点,怎么能对比出 Epoll 的优点呢):

    ① PPC/TPC 模型

    这两种模型思想类似,就是让每一个到来的连接一边自己做事去,别再来烦我 。只是 PPC 是为它开了一个进程,而 TPC 开了一个线程。可是别烦我是有代价的,它要时间和空间啊,连接多了之后,那么多的进程 / 线程切换,这开销就上来了;因此这类模型能接受的最大连接数都不会高,一般在几百个左右。

    ② select 模型

    1. 最大并发数限制,因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048 ,因此 Select 模型的最大并发数就被相应限制了。自己改改这个 FD_SETSIZE ?想法虽好,可是先看看下面吧 …

    2. 效率问题, select 每次调用都会线性扫描全部的 FD 集合,这样效率就会呈现线性下降,把 FD_SETSIZE 改大的后果就是,大家都慢慢来,什么?都超时了。

    3. 内核 / 用户空间 内存拷贝问题,如何让内核把 FD 消息通知给用户空间呢?在这个问题上 select 采取了内存拷贝方法。

    总结为:1.连接数受限  2.查找配对速度慢 3.数据由内核拷贝到用户态

    ③ poll 模型

    基本上效率和 select 是相同的, select 缺点的 2 和 3 它都没有改掉。

    三). Epoll 的提升

    把其他模型逐个批判了一下,再来看看 Epoll 的改进之处吧,其实把 select 的缺点反过来那就是 Epoll 的优点了。

    ①. Epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于 2048, 一般来说这个数目和系统内存关系很大 ,具体数目可以 cat /proc/sys/fs/file-max 察看。

    ②. 效率提升, Epoll 最大的优点就在于它只管你“活跃”的连接 ,而跟连接总数无关,因此在实际的网络环境中, Epoll 的效率就会远远高于 select 和 poll 。

    ③. 内存拷贝, Epoll 在这点上使用了“共享内存 ”,这个内存拷贝也省略了。

    使用 Epoll

    既然 Epoll 相比 select 这么好,那么用起来如何呢?会不会很繁琐啊 … 先看看下面的三个函数吧,就知道 Epoll 的易用了。 

    1 int epoll_create(int size);  

    生成一个 Epoll 专用的文件描述符,其实是申请一个内核空间,用来存放你想关注的 socket fd 上是否发生以及发生了什么事件。 size 就是你在这个 Epoll fd 上能关注的最大 socket fd 数,大小自定,只要内存足够。

    1 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event );  

    控制某个 Epoll 文件描述符上的事件:注册、修改、删除。其中参数 epfd 是 epoll_create() 创建 Epoll 专用的文件描述符。相对于 select 模型中的 FD_SET 和 FD_CLR 宏。

    1 int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);  

    等待 I/O 事件的发生;参数说明:

    epfd: 由 epoll_create() 生成的 Epoll 专用的文件描述符;

    epoll_event: 用于回传代处理事件的数组;

    maxevents: 每次能处理的事件数;

    timeout: 等待 I/O 事件发生的超时值;

    返回发生事件数。

    相对于 select 模型中的 select 函数。

    epoll的LT和ET的区别

    LT:水平触发,效率会低于ET触发,尤其在大并发,大流量的情况下。但是LT对代码编写要求比较低,不容易出现问题。LT模式服务编写上的表现是:只要有数据没有被获取,内核就不断通知你,因此不用担心事件丢失的情况。
    ET:边缘触发,效率非常高,在并发,大流量的情况下,会比LT少很多epoll的系统调用,因此效率高。但是对编程要求高,需要细致的处理每个请求,否则容易发生丢失事件的情况。
    下面举一个列子来说明LT和ET的区别(都是非阻塞模式,阻塞就不说了,效率太低):
    采用LT模式下, 如果accept调用有返回就可以马上建立当前这个连接了,再epoll_wait等待下次通知,和select一样。
    但是对于ET而言,如果accpet调用有返回,除了建立当前这个连接外,不能马上就epoll_wait还需要继续循环accpet,直到返回-1,且errno==EAGAIN

     

    Epoll是linux2.6内核以后支持的一种高性能的IO多路服用技术。服务器框架如下:

     1 socket( AF_INET,SOCK_STREAM,0 )
     2 fcntl(listen_fd, F_SETFL,flags|O_NONBLOCK);
     3 bind( listen_fd, (structsockaddr *)&my_addr,sizeof(struct sockaddr_in))
     4 listen( listen_fd,1 )
     5 epoll_ctl(epfd,EPOLL_CTL_ADD,listen_fd,&ev);
     6 ev_s = epoll_wait(epfd,events,20,500 );
     7 for(i=0; i<ev_s;i++){
     8                    if(events[i].data.fd==listen_fd){
     9                             accept_fd = accept( listen_fd,(structsockaddr *)&remote_addr,&addr_len );
    10                             fcntl(accept_fd, F_SETFL,flags|O_NONBLOCK);
    11                             epoll_ctl(epfd,EPOLL_CTL_ADD,accept_fd,&ev);
    12                    }
    13                    else if(events[i].events&EPOLLIN){
    14                             recv( events[i].data.fd ,&in_buf,1024 ,0 );
    15                    }
    16 }
    作者:orange1438
    出处:http://www.cnblogs.com/orange1438/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    AfxMessageBox详细使用说明
    动态规划: 求一个一维整数数组的最大子序列和
    常见HTTP状态码
    PHP 基础系列(三) 【转】PHP 函数实现原理及性能分析
    empty() isset() isnull() 比较
    isset() 与 array_key_exists() 比较
    PHP基础系列(二) PHP数组相关的函数分类整理
    PHP基础系列(一) PHP字符串相关的函数分类整理
    linux df 命令
    grep 同时满足多个关键字和满足任意关键字
  • 原文地址:https://www.cnblogs.com/orange1438/p/4637810.html
Copyright © 2011-2022 走看看