Epoll 作为Linux 系统中的核心武器之一,在高吞吐、高并发的IO系统中经常遇见Epoll的身影,列如Redis、Nginx、Skynet等都使用到了IO多路复用技术。我们可以先创建一个epoll对象,再将fd(File Descriptor 文件描述符对象)注册到epoll对象里,之后便能通过调用epoll对象的查询函数来获取准备好事件的fd对象。
epoll_create函数
函数声明:int epoll_create(int size);
__size参数 相当于提供给内核一个提示,当前需要监听的fd个数
返回值:当前Epoll对象的fd
Unxi中一切皆文件,在Epoll中也是 。这里Epoll便是一个虚拟文件对象,epoll_create函数了创建一个代表Epoll对象的fd 。这里生成一个epoll专用的文件描述符 在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件
在某个进程调用 epoll_create 方法时,Linux 内核便会创建 eventpoll 结构体,重点在这个结构体里的 rbr 和 rdllist 成员。rbr 成员是红黑树的根节点,这棵树存储着所有需要监听的 socket。rdllist 是双向链表的头结点,链表中就存储着收到数据的 socket
epoll_ctl函数
函数声明:int epoll_ctl (int __epfd, int __op, int __fd,struct epoll_event *__event);
这个函数用于控制创建的Epoll 文件描述符上的事件,可以通过该函数注册事件,修改事件,删除事件
epfd:通过epoll_create方法创建的Epoll 对象
op:将要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD (添加监听的fd)、EPOLL_CTL_MOD (修改监听的fd)、EPOLL_CTL_DEL (删除监听的fd)
__fd:表示关联的文件描述符(需要操作的fd对象)
__event:表示用于描述需要监听的fd对象的感兴趣事件类型
返回值:如果调用0表示成功,-1表示失败
epoll_wait函数
函数声明:epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout);
该函数用于轮询I/O事件的发生,获取Epoll对象监听的fd对象列表,我们可以通过该参数实现我们通过epoll_ctl添加到Epoll对象中监听的且准备好事件的fd对象。
__epfd:由epoll_create 生成的epoll专用的文件描述符
__events:用于接收fd对象的缓冲区
__maxevents:每次能够处理的事件数 这一次调用可以接收多少准备好的fd对象,通常设置为events参数的长度
__timeout:如果没有准备好的事件对象,那么等待多久返回,-1阻塞,0非阻塞
返回值:返回events缓冲区中有效的fd个数,也即准备好事件的fd个数
关于边缘触发(ET)、水平触发(LT)两种工作模式:
Epoll对象对于监听的fd处理方式有两种:边缘触发(edge-triggered)ET、 水平触发(level-triggered)LT。默认情况下,epoll采用 LT模式工作,这时可以处理阻塞和非阻塞套接字。ET模式的效率要比 LT模式高,它只支持非阻塞套接字。在ET模式下,当我们通过epoll_wait函数获取到准备好的事件后,如果没有处理完成所有事件,那么再次调用epoll_wait函数将不会再次返回该fd,而LT模式下如果fd的事件没有处理完成,那么在下一次调用epoll_wait函数时将会返回该fd。ET模式仅当状态发生变化的时候才获得通知,这里所谓的状态的变化并不包括缓冲区中还有未处理的数据,也就是说,如果要采用ET模式,需要一直read/write到出错为止,这就是为什么采用ET模式只接收了一部分数据就不会通知,而LT模式只要有数据没有处理就会一直通知下去。
总结:epoll_create函数用于创建对象,而epoll_ctl函数用于对Epoll对象CRUD,epoll_wait函数用于对Epoll对象进行查询操作。对月ET和LT来说:ET模式一个事件只会触发一次,若是该事件中的数据未处理完成,再下一个事件到来后,就不会再次返回监听的fd。对LT来说的话,若是数据未处理完毕,就可以再次调用epoll_wait函数处理未处理完成数据的fd。
标签:__,函数,epoll,对象,Epoll,详解,fd,Linux From: https://www.cnblogs.com/daomeidan/p/16784728.html