先说个故事html
鬼子进村程序员
处理大量的链接的读写,select 是够低效的。由于 kernel 每次都要对 select 传入的一组 socket 号作轮询,这叫鬼子进村策略。一遍遍的询问“鬼子进村了吗?”,“鬼子进村了吗?”... 大量的 cpu 时间都耗了进去。(更过度的是在 windows 上,还有个万恶的 64 限制。)使用 kqueue 这些,变成了派一些我的去站岗,鬼子来了就能够拿到通知,效率天然高了许多。web
缓存I/O又称为标准I/O,大多数文件系统的默认I/O操做都是缓存I/O。在Linux的缓存I/O机制中,操做系统会将I/O的数据缓存在文件系统的页缓存中,即数据会先被拷贝到操做系统内核的缓冲区中,而后才会从操做系统内核的缓冲区拷贝到应用程序的地址空间。编程
阻塞式I/O模型:默认状况下,全部套接字都是阻塞的。recvfrom等待数据准备好,从内核向进程复制数据。windows
非阻塞式I/O: 进程把一个套接字设置成非阻塞是在通知内核,当所请求的I/O操做非得把本进程投入睡眠才能完成时,不要把进程投入睡眠,而是返回一个错误,recvfrom老是当即返回。数组
I/O多路复用:虽然I/O多路复用的函数也是阻塞的,可是其与以上两种仍是有不一样的,I/O多路复用是阻塞在select,epoll这样的系统调用之上,而没有阻塞在真正的I/O系统调用如recvfrom之上。其本质是经过一种机制(系统内核缓冲I/O数据),让单个进程能够监视多个文件描述符,一旦某个描述符就绪(通常是读就绪或写就绪),可以通知程序进行相应的读写操做。select、poll 和 epoll 都是 Linux API 提供的 IO 复用方式。缓存
信号驱动式I/O:用的不多,就不作讲解了。服务器
异步I/O:这类函数的工做机制是告知内核启动某个操做,并让内核在整个操做(包括将数据从内核拷贝到用户空间)完成后通知咱们。网络
recvfrom函数(经socket接收数据)。数据结构
再看POSIX对这两个术语的定义:
同步I/O操做:致使请求进程阻塞,直到I/O操做完成;
异步I/O操做:不致使请求进程阻塞。
select()的机制中提供一种fd_set
的数据结构,其实是一个long类型的数组,每个数组元素都能与一打开的文件句柄(不论是Socket句柄,仍是其余文件或命名管道或设备句柄)创建联系,创建联系的工做由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一Socket或文件可读。
从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操做,效率更差。可是,使用select之后最大的优点是用户能够在一个线程内同时处理多个socket的IO请求。用户能够注册多个socket,而后不断地调用select读取被激活的socket,便可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须经过多线程的方式才能达到这个目的。
epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减小epoll_wait/epoll_pwait的调用,提升应用程序效率。
LT和ET本来应该是用于脉冲信号的,可能用它来解释更加形象。Level和Edge指的就是触发点,Level为只要处于水平,那么就一直触发,而Edge则为上升沿和降低沿的时候触发。好比:0->1 就是Edge,1->1 就是Level。
ET模式很大程度上减小了epoll事件的触发次数,所以效率比LT模式下高。
一张图总结一下select,poll,epoll的区别:
select | poll | epoll | |
---|---|---|---|
操做方式 | 遍历 | 遍历 | 回调 |
底层实现 | 数组 | 链表 | 哈希表 |
IO效率 | 每次调用都进行线性遍历,时间复杂度为O(n) | 每次调用都进行线性遍历,时间复杂度为O(n) | 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到readyList里面,时间复杂度O(1) |
最大链接数 | 1024(x86)或2048(x64) | 无上限 | 无上限 |
fd拷贝 | 每次调用select,都须要把fd集合从用户态拷贝到内核态 | 每次调用poll,都须要把fd集合从用户态拷贝到内核态 | 调用epoll_ctl时拷贝进内核并保存,以后每次epoll_wait不拷贝 |
既然select,poll,epoll都是I/O多路复用的具体的实现,之因此如今同时存在,其实他们也是不一样历史时期的产物
参考:
https://blog.csdn.net/dapengbusi/article/details/50690690