IO复用-epoll的简易解析

前提

  • linux中将任何事务的输入输出(IO)都认为是文件读写,因此epoll事件也不例外。
  • epoll有自己对应的文件系统,称为eventpollfs,类比一下其他文件系统,epoll并不算很特殊,相当于epoll线程创建之后,会在epoll文件系统中创建一个epoll文件夹,然后把该线程监听的对象(比如socket)的文件描述符(如socketfd)作为一个个文件夹放入其中。
  • 文件夹中的文件是按照红黑树的方式进行组织的,文件夹则是红黑树的根节点。

EPOLL结构

在这里插入图片描述

  • epoll监听事件大体流程

    • 一个epoll线程会有一个小的epoll文件系统,文件系统中的各个文件是一个个epollitem结构体,里面存放着,并且将所有监听的fd组织为一个红黑树
    • 进入阻塞,维护一个就绪队列(rdlist),如果某一个fd有数据,那么将该fd放置到就绪队列
    • 由于epoll中使用mmap将内核中的内存映射到fd对应的文件位置,因此不需要将数据重新拷贝到内核态,只需要根据事务处理即可
    • 处理完毕之后,重新进入监听状态
  • int epoll_create(int size)

    • 函数意义
      • 创建一个epoll,可以理解为在epoll文件系统中创立了一个文件夹,文件夹作为红黑树的根节点,然后再向里面加入文件就是以红黑树的形式进行组织,此外,还开辟了一个就绪队列,队列的头部是文件夹。
      • 返回epoll文件描述符(后续参数中的epfd),其中最大能处理的fd数量为size
  • int epoll_ctl(int epfd, intop, int fd, struct epoll_event *event)

    • 实现对epoll监控fd的增删改,也就是在红黑树中新增fd或者减少fd
    • 例如可以使用ep_insert将epitem对应的fd插入到eventpoll中的红黑树上,在插入的时候需要判断是否有事件发生,如果有,那么直接唤醒epoll_wait函数
    • epoll_wait(int epfd,struct epoll_event *events,int maxevents, int timeout);返回准备就绪链表里的数据即可,如果没有数据,就进入sleep状态

EPOLL的优缺点

  • 优点
    • 当并发量大,数据不活跃的时候(也就是fd多,但是同一事件有数据到达的fd的数量不多)
    • 实现了共享内核中的内存,监听到的数据传入内核之后,由于epoll文件映射了内核中对应部分的内存,因此处理完成得到结果后不需要从内核到用户的拷贝,少一次拷贝开销
  • 缺点
    • 当并发量大,并且数据活跃的时候,频繁调用回调函数会导致额外事件开销,此时要权衡

边缘触发与水平触发?ET与LT

  • 直观上:与高低电平触发一样的理解
    • 水平触发指的是在高电平(收到数据)的状态下一直轮询提示epoll有事件
    • 边缘触发指的是在高低电平(某fd从未收到数据到有收到数据)切换的时候,向epoll线程发送一个信号
    • ET只触发一次,无论缓冲区中是否还有剩余数据,直到有新的数据到达才会被触发,把剩余的再读取出来,必须采用非阻塞式IO,避免产生死锁
      • 为什么会产生死锁呢?因为如果是阻塞式IO,那么在读取的时候,一定要读到足够字节的数据才可以释放,那么此时如果fd中没有足够多的数据,写数据操作又被阻塞,就会造成相互等待(那为什么一定要读取到足够多的数据?)
    • LT 水平触发: 每次缓冲区都有数据都要触发
      • 优点:逻辑简单,应付并发问题容易
      • 缺点:每次有数据到达都会出发epoll,效率相比ET低

相较于select/poll的优点

  • select告诉内核有数据到达socket是通过copy一个bitmap数组到内核的,能监听的socket文件数量受限于bitmap长度
  • 此外,select/poll每次调用都要将监听的所有fd拷贝到内核的select/poll系统进行调用。
  • 而epoll_wait的过程中,由于实现使用mmap将监听的fd和内核的一段内存进行了地址共享,因此不需要再传递fd列表给内核,因此效率更高,尤其是在海量连接并发的情况下。
  • 因为在epoll文件系统中,除了存储监听fd的红黑树之外,还留有一个fd就绪队列,作用类似于缓存,内核无需遍历整个监听系统来查询哪个fd有数据,因此随并发量的增长,epoll的效率并不会收到急剧影响。
  • 而在select和poll中,内核查看有无数据到达只能通过遍历一整个数组实现,效率会随着并发量的上升而线性下降。
  • 因此,在epoll中返回写好的数据的速度,仅仅取决于准备好数据的fd数量,无论多大的连接两,只要同一时间的活跃数量优先,epoll仍然可以飞快的处理并返回数据。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值