IO事件处理模型

还有谁?

  • select是全平台通用的IO多路复用模块,使用位图,最大支持1024位
  • poll和epoll只能用在linux平台使用,无最大连接数限制
  • kqueue只能在FreeBSD平台(unix的一个分支)使用

select

  • 包含4个属性,等待可读、等待可写、等待出异常、超时时间
  • 当超时时间为0时表示立即返回,这里可以理解为非阻塞
  • 当超时时间设定为正数时,若拿不到返回则一直阻塞到超时返回
  • 当不设置超时时间,则阻塞直到有可读/可写/异常消息返回
  • 每次获取会遍历所有链接,耗时;遍历每个链接会存在阻塞,耗时;遍历完所有链接把对象从CPU复制出来,耗时
  • 位图是内核在维护非应用程序,在每次调用都需要重写
  • 兴趣集和结果集在位图中无法分割
  • select/poll共同问题:兴趣集无结果时,下次会遍历还会重复遍历

poll

  • 使用数组替代位图,好处多多,如下
  • 数组突破了最大连接数1024限制
  • 数组有应用程序自己预设定并后续维护,每次调用无需重写
  • 数组可分割出兴趣集和结果集
  • select/poll共同问题:兴趣集无结果时,下次会遍历还会重复遍历

epoll

  • 预注册事件
  • 事件驱动
  • 异步非阻塞
  • epoll技术为了解决大内存数据拷贝问题,将注册和等待进行拆分,分别针对对应的细小功能模块进行优化和改进,也就是相比select/poll设计上更为细粒度且专业化
  • 为了提升性能,在内部使用SLAB内存管理方式会预先申请连续内存存储对应的对象,也就是在某一个时刻上存在空间的冗余
  • epoll技术通过使用epitem中间层的方式来完成对每个注册的socket进行监控,通过对等待队列上事件节点的轮询将就绪节点以链表的方式连接起来,避免了数组遍历与查找
  • 借助epoll容器来对每个epitem进行管理,由内核对epoll空间进行事件监控,即将所有的事情委托给容器来进行操作,epoll容器将最终的结果返回告知唤醒处理逻辑
  • epoll技术基于SLAB的方式管理内存,通过SLAB的方式来创建epoll空间以及epitem结构体对象
  • 使用连续的内存地址空间来存储epitem/epoll,避免内存碎片(多个epoll的产生是在多核下多进程)
  • 使用的epitem/epoll释放存放在"对象池"中进行重复利用,同时减少创建和销毁epitem带来的性能开销(内存申请和释放的开销),可以理解为高速缓存

kqueue

  • FreeBSD4.1引入kqueue技术,允许进程向内核注册描述所关注的kqueue事件的事件过滤器(event filter)
  • 与epoll的实现原理类似,只不过相比epoll实现,增加更多事件的监听(异步IO/文件修改通知/进程跟踪/信号处理等)
  • 存在的兼容性问题,目前是在FreeBSD系统中

  1. https://blog.csdn.net/wind_602/article/details/104863808
  2. https://www.cnblogs.com/moonz-wu/p/4740908.html
  3. https://segmentfault.com/a/1190000003063859
posted @ 2020-07-16 18:10  小嘟嘟虫  阅读(156)  评论(0编辑  收藏  举报