由于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 的易用了。

 int epoll_create(int size);  

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

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

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

 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多路服用技术。服务器框架如下:

 socket( AF_INET,SOCK_STREAM, )
fcntl(listen_fd, F_SETFL,flags|O_NONBLOCK);
bind( listen_fd, (structsockaddr *)&my_addr,sizeof(struct sockaddr_in))
listen( listen_fd, )
epoll_ctl(epfd,EPOLL_CTL_ADD,listen_fd,&ev);
ev_s = epoll_wait(epfd,events,, );
for(i=; i<ev_s;i++){
if(events[i].data.fd==listen_fd){
accept_fd = accept( listen_fd,(structsockaddr *)&remote_addr,&addr_len );
fcntl(accept_fd, F_SETFL,flags|O_NONBLOCK);
epoll_ctl(epfd,EPOLL_CTL_ADD,accept_fd,&ev);
}
else if(events[i].events&EPOLLIN){
recv( events[i].data.fd ,&in_buf, , );
}
}
作者:orange1438
出处:http://www.cnblogs.com/orange1438/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

IO复用_epoll函数的更多相关文章

  1. IO复用_select函数

    select函数: #include <sys/select.h> #include <time.h> #include <sys/types.h> #includ ...

  2. 【Unix网络编程】chapter6 IO复用:select和poll函数

    chapter6 6.1 概述 I/O复用典型使用在下列网络应用场合. (1):当客户处理多个描述符时,必须使用IO复用 (2):一个客户同时处理多个套接字是可能的,不过不叫少见. (3):如果一个T ...

  3. Linux网络编程-IO复用技术

    IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...

  4. Libevent的IO复用技术和定时事件原理

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  5. IO复用三种方式

    简介 IO复用技术,简单来说就是同时监听多个描述符.在没有用到IO复用以前,只能是一个线程或一个 线程去监听,服务端同时有多个连接的时候,需要创建多个线程或者进程.而且,并不是所有的连 接是一直在传输 ...

  6. 高级IO复用应用:聊天室程序

    简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户.这里采用IO复用poll技术.客户端采用了splice零拷贝.服务端采用了空间换时间(分配超大的用户数 ...

  7. select、poll、epoll三组IO复用

    int select(int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,struct timeval* timeout)//其中n ...

  8. Linux中的IO复用接口简介(文件监视?)

    I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...

  9. IO复用

    IO复用:使得程序能同时监听多个文件描述符 select: select在一段指定的时间内,监听用户感兴趣的文件描述符的 读.写.异常事件. select(int nfds,fd_set* readf ...

随机推荐

  1. (4) PIVOT 和 UPIVOT 的使用

    最近项目中用到了行转列,使用SQL SERVER 提供的PIVOT实现起来非常容易. 官方解释:详见这里 可以使用 PIVOT 和 UNPIVOT 关系运算符将表值表达式更改为另一个表. PIVOT ...

  2. java持久层框架mybatis如何防止sql注入

    看到一篇很好的文章:http://www.jfox.info/ava-persistence-framework-mybatis-how-to-prevent-sql-injection sql注入大 ...

  3. 总结整理 -- 爬虫技术(C#版)

    爬虫技术学习总结 爬虫技术 -- 基础学习(一)HTML规范化(附特殊字符编码表) 爬虫技术 -- 基本学习(二)爬虫基本认知 爬虫技术 -- 基础学习(三)理解URL和URI的联系与区别 爬虫技术 ...

  4. Yii的学习(2)--数据访问对象 (DAO)

    摘自Yii官网:http://www.yiiframework.com/doc/guide/1.1/zh_cn/database.dao Yii提供了强大的数据库编程支持.Yii数据访问对象(DAO) ...

  5. PHP Log时时查看小工具

    以前Log都是打印在一个文档中,然后打开文件夹,最后打开文档查看里面的内容,每次打开文件夹感觉很烦. 前些日子看到同事开发.NET的时候,用他自己的一个小工具能够时时查看到Log的内容,非常方便,所以 ...

  6. 【大数据】Linux下Storm(0.9版本以上)的环境配置和小Demo

    一.引言: 在storm发布到0.9.x以后,配置storm将会变得简单很多,也就是只需要配置zookeeper和storm即可,而不再需要配置zeromq和jzmq,由于网上面的storm配置绝大部 ...

  7. Azure Redis Cache (1) 入门

    <Windows Azure Platform 系列文章目录> Microsoft Azure Redis Cache基于流行的开源Redis Cache. 1.功能 Redis 是一种高 ...

  8. 实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法

    关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如: namespace Wcf ...

  9. SpringAOP使用扩展

    在<初识Spring>中我们了解到Spring支持AOP且可配置方法的前置曾强和后置曾强,但其实Spring支持多种曾强类型.下面同过一些例子来介绍Spring的几种常用的曾强(前置增强和 ...

  10. ES6笔记(4)-- Symbol类型

    系列文章 -- ES6笔记系列 Symbol是什么?中文意思是标志.记号,顾名思义,它可以用了做记号. 是的,它是一种标记的方法,被ES6引入作为一种新的数据类型,表示独一无二的值. 由此,JS的数据 ...