天天看点

io多路复用个人理解

文章目录

        • 概述
        • select
        • poll
          • poll比select的优势
        • epoll
          • ET/LT模式
          • epoll和select、poll的区别
        • 参考

概述

IO多路复用即一个函数(函数集)跟多个套接字进行IO操作,常见类型为select、poll、epoll

select

int select(int maxfdp1, fd_set* readset, fd_set* writeset, fd_set* exceptset, const struct timeval* timeout);
           

​ 检查从0到maxfdp1-1的描述符,检测到可读、可写、异常的描述符会放到各自的链表中,timeout设置阻塞超时时间。

poll

int poll(struct pollfd* fdarray, unsigned long nfds, int timeout);
           
struct pollfd {
    int fd;			// 检查的文件描述符
    short events;	// 要测试的条件
    short revents;  // 返回时对该描述符的状态
}
           

fdarray里面放想要检测的文件描述符

poll比select的优势
  1. 将不同类型的事件放到同一个链表,再统一处理,接口简单
  2. poll在链表上挂的是感兴趣的文件描述符,而select是无差别轮询

epoll

epoll是一个类型,由epoll_create、epoll_ctl、epoll_wait三个函数构成。

  1. epoll_create初始化一个文件描述符,里面包含了两个数据结构,红黑树和双向链表。其中,红黑树上装的是用户感兴趣的事件,双向链表装的是就绪的事件。
    int epollfd = epoll_create(5);	
               
  2. epoll_ctl往红黑树添加、修改、删除用户感兴趣的事件。在往红黑树添加事件的同时,向内核注册一个该事件对应的回调函数。在事件就绪时,内核通过回调函数将该事件添加到双向链表。
    epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
               
  3. epoll_wait将双向链表上的就绪事件复制到用户空间
    int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
               
ET/LT模式
  1. LT模式,水平触发

    LT模式在epoll_wait函数内将就绪事件链表清空,然后创建备份链表,设置为LT模式的事件会放到该链表中(不管是否处理完成),函数结束后,该链表成为新的就绪事件链表。对于处理完成的事件,下次调用的时候返回NULL,内核会将其清除。

  2. ET模式,边缘触发

    对与设置为ET模式的事件不会放到新的链表中,即只触发一次,高效。

epoll和select、poll的区别
  1. 时间复杂度:epoll在拿就绪事件是O(1),select和poll为O(1)
  2. 资源消耗:epoll利用多一个文件描述符记录感兴趣事件和就绪事件,并且每个事件都调用了回调函数。select和poll较简单
  3. 使用:监听事件多,实际发生事件少时用epoll。实际发生事件多时用poll,避免大量回调函数。

参考

  1. https://blog.csdn.net/tianjing0805/article/details/76021440
  2. https://www.cnblogs.com/gaorong/p/7496993.html
  3. 《Linux高性能服务器编程》游双

继续阅读