浅谈poll/select epoll的区别

  poll/setect,epoll三个命令都是属于内核方法,是内核实现用一个线程监听多个连接的方法,其中epoll是Linux2.6之后引入的一种高效的连接事件监听机制。

select原理

  select方法是将文件描述符数组从用户控件传入内核空间,内核通过轮询的方式查看所有连接,如何循环一次没有连接事件到底则等待,事件到达后返回。返回之后客户端需要遍历怎个数组,找出产生事件的连接。同时select默认监听的连接数为1024

poll原理

  poll方法与select方法类似,只不过poll使用链表存储文件描述符,因此理论上没有监听连接数量的限制,但都是用户空间向内核空间传递需要监听的文件描述符,然后内核使用轮询的方式查看是否有事件到达,如果没有则等待,有则返回,返回后用户程序仍然要遍历所有文件描述符,找出发生事件的描述符

epoll原理

  epoll是Linux2.6对poll/select方法的改进,他是基于信号驱动的io多路复用方法。epoll由三个内核方法组成:

  1. int epoll_create(int size)
      创建一个epoll对象,size参数用于指定该对象最大内容纳的连接数量,在后来的版本中,弃用了size参数
  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
      epoll对象中有一棵红黑树,用来存储被监听的文件描述符。epoll_ctl命令用来向epoll对象中添加,删除,修改文件描述符。epfd参数指epoll对象;op参数:EPOLL_CTL_ADD(添加操作)、EPOLL_CTL_DEL(删除操作)、EPOLL_CTL_MOD(修改操作);
    fd参数用来指定被操作的文件描述符;event参数用来指定文件描述符关心的事件类型
  3. int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
      阻塞等待事件发生,当事件发生时,内核会调用回调方法将该文件描述符添加到返回值列表中,返回事件的数目和已经发生的事件集合,该方法可以指定等待时间,超出等待时间就直接返回
      epoll每次调用时不必向内核空间传入整个文件描述符数组,而是通过epoll_ctl方法添加、删除、修改部分文件描述符,同时epoll方法返回的不是整个被监听的文件描述符数组,而是事件发生文件描述符数组。

epoll触发方式

  1. 水平触发(LT):对于对操作,只要缓冲器还有未读取的数据就会触发该事件;对于写操作,只要缓冲区还未满,就会返回写就绪
  2. 边缘触发(ET):只要当转态发生变化时才会触发事件。对于读,只有当缓冲区有不可读变为可读时才返回读事件;对于写,只要当缓冲区由不可写变为可写是才返回写就绪。

epoll与select、poll方法的对比

  1. 后两者是通过轮询的方式,每次都要遍历整个被监听的文件描述符数组,因此监听效率低下,没法实现100万级连接的监听,前者采用的是信号驱动,当事件发生时,调用回调函数将对应文件描述符添加到返回值数组中,避免了低效的遍历
  2. 后两者返回的是整个被监听的文件描述符数组,因此每次用户程序都需要遍历整个数组,找出事件发生的是文件描述符,而前者返回的就是发生事件的文件描述符
  3. 后两者存在大量的数据拷贝,每次开始都需要将整个文件描述符数组从用户空间复制到内核空间,结束之后再从内核空间复制到用户空间,而前者只需要操作发生变化的文件描述符,同时返回的是事件到达的那部分文件描述符
  4. epoll使用红黑树存储文件描述符,实现高效的添加、删除和修改操作
  5. epoll无需重构红黑树,可以沿用上次的红黑树
  6. epoll有高效的边缘触发方式,避免了由于数据未读完或则写缓冲区未满而产生的重复触发。
  7. epoll虽然效率高,但是当监听连接少,且连接十分活跃的时候效率不一定比poll高,因为存在很对函数回调
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章