1、html
select poll 与 epoll的区别,能够参考如下三个连接数组
总结一下服务器
三者区别以下网络
(1)select,poll实现须要本身不断轮询全部fd集合,直到设备就绪,期间可能要睡眠和唤醒屡次交替。而epoll其实也须要调用epoll_wait不断轮询就绪链表,期间也可能屡次睡眠和唤醒交替,可是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,可是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就好了,这节省了大量的CPU时间。这就是回调机制带来的性能提高。并发
(2)select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,而且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,并且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并非设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省很多的开销。socket
epoll优势以下函数
epoll的优势:性能
1.支持一个进程打开大数目的socket描述符(FD)spa
select 最不能忍受的是一个进程所打开的FD是有必定限制的,由FD_SETSIZE设置,默认值是1024/2048。对于那些须要支持的上万链接数目的IM服务器来讲显然太少了。这时候你一是能够选择修改这个宏而后从新编译内核。不过 epoll则没有这个限制,它所支持的FD上限是最大能够打开文件的数目,这个数字通常远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目能够cat /proc/sys/fs/file-max察看,通常来讲这个数目和系统内存关系很大。操作系统
2.IO效率不随FD数目增长而线性降低
传统的select/poll另外一个致命弱点就是当你拥有一个很大的socket集合,不过因为网络延时,任一时间只有部分的socket是"活跃"的,可是select/poll每次调用都会线性扫描所有的集合,致使效率呈现线性降低。可是epoll不存在这个问题,它只会对"活跃"的socket进行操做---这是由于在内核实现中epoll是根据每一个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其余idle状态socket则不会,在这点上,epoll实现了一个"伪"AIO,由于这时候推进力在Linux内核。
3.使用mmap加速内核与用户空间的消息传递。
这点实际上涉及到epoll的具体实现了。不管是select,poll仍是epoll都须要内核把FD消息通知给用户空间,如何避免没必要要的内存拷贝就很重要,在这点上,epoll是经过内核与用户空间mmap同一块内存实现的。
对于poll来讲须要将用户传入的 pollfd 数组拷贝到内核空间,由于拷贝操做和数组长度相关,时间上这是一个O(n)操做,当事件发生,poll返回将得到的数据传送到用户空间并执行释放内存和剥离等待队列等善后工做,向用户空间拷贝数据与剥离等待队列等操做的的时间复杂度一样是O(n)。
epoll的主要优点在于回调函数,可是当socket中90%都是活跃的,epoll效率不必定就会高。(还需进一步了解)
2、
这里面有个概念须要理清楚,内核态 用户态
http://www.cnblogs.com/zemliu/p/3695503.html
内核态: CPU能够访问内存全部数据, 包括外围设备, 例如硬盘, 网卡. CPU也能够将本身从一个程序切换到另外一个程序
用户态: 只能受限的访问内存, 且不容许访问外围设备. 占用CPU的能力被剥夺, CPU资源能够被其余程序获取
因为须要限制不一样的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态 和 内核态
全部用户程序都是运行在用户态的, 可是有时候程序确实须要作一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而惟一能够作这些事情的就是操做系统, 因此此时程序就须要先操做系统请求以程序的名义来执行这些操做.
这时须要一个这样的机制: 用户态程序切换到内核态, 可是不能控制在内核态中执行的指令
这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)
他们的工做流程以下:
3、以poll为例
http://blog.sina.com.cn/s/blog_7943319e0101a5dw.html
经过前面的分析,咱们知道,应用程序中的open、read、write函数系统调用都会触发软中断异常,从而进入异常处理,在异常处理中将会获取用户态传入的系统调用号,根据系统调用号在系统调用表中索引出实际的系统调用处理函数,如内核里的sys_open、sys_read、sys_write函数,而内核里的这些函数又会对应到驱动程序里的open、read、write函数。
poll机制也不例外,用户空间里调用poll函数或者select函数时,都会调用到内核空间的sys_poll或者sys_select函数。
因此 这就涉及到了内存copy的问题。