前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >unix网络编程——I/O多路复用之epoll

unix网络编程——I/O多路复用之epoll

作者头像
Mister24
发布2018-09-19 16:19:01
6210
发布2018-09-19 16:19:01
举报
文章被收录于专栏:java初学java初学java初学

1. 基本概念

  当程序进行IO时,如果数据尚未准备好,那么IO将处于阻塞状态。当某个进程有多个打开的文件,比如socket,那么其后的所有准备好读写的文件将受到阻塞的影响而不能操作。不借助线程,单一进程无法在同一时间服务多个文件描述符。非阻挡式IO可以作为一个解决方案,但是效率并不高。首先进程需要不断发IO请求,其次,如果程序可以休眠,让出CPU将提高效率。多任务式IO是在其中任何一个文件描述符就绪时收到通知,此时IO将不会受到阻挡,其余时间处于休眠状态,将CPU资源让给别的进程。

  为了实现I/O多路复用,epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。

2. api

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
  • int epoll_create(int size) [创建句柄]

创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

  函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd数。随你定好了。只要你有空间。可参见上面与select之不同

  • int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)[事件注册函数]

  epoll的事件注册函数,对比select()函数,select()是在监听事件时告诉内核要监听什么类型的事件,而epoll是在调用epoll_ctl函数的时候,先注册要监听的事件类型。

  epfd:epoll_create()的返回值;   op:表示要进行的操作,操作的动作使用了宏定义:

    1. EPOLL_CTL_ADD: 注册新的fd到epfd中;
    2. EPOLL_CTL_MOD: 修改已经注册的fd的监听事件;
    3. EPOLL_CTL_DEL: 删除epfd中的一个fd;

fd:关联的文件描述符,表示需要监听的fd; event:指向epoll_event的指针,告诉内核需要监听什么事件,epoll_event的结构如下:

struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};

 events描述事件类型,使用了宏定义:

  1. EPOLLIN:表示对应的文件描述符可以读(包括对端socket正常关闭);

  2. EPOLLOUT: 表示对应的文件描述符可以写;

  3. EPOLLPRI: 表示对应的文件描述符有紧急的数据可读(表示有外数据到来);

  4. EPOLLHUP: 表示对应的文件描述符被挂断;

  5. EPOLLET: 将EPOLL设置为边缘触发(Edge Triggered)模式;

  6. EPOLLONESHOT: 只监听一次事件,当监听玩这次事件之后,如果还需要继续监听,需要再次将该socket加入EPOLL队列中。

  • int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout) [等待事件触发]

  等待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1表示不确定)。该函数返回需要处理的事件数目,如返回0表示已超时。

3.epoll工作模式

  epoll对文件描述符的操作有两种模式:LT(level trigger,水平触发)和ET(edge trigger,边缘触发)。

LT模式:水平触发是缺省的工作方式。当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件(进行IO操作)。下次调用epoll_wait时,会再次响应应用程序并通知此事件。由于对于描述事件符在处理前会进行多次通知,因此出错的概率小;

ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,此时它会假设你知道文件描述符已就绪,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件,直到做了一定操作导致该文件描述符再次变为未就绪状态。但是如果一直对该fd进行IO操作()

 ET模式在很大程度上减少了epoll事件被重复触发的次数,因此效率要比LT模式高。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 基本概念
  • 2. api
  • 3.epoll工作模式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档