Epoll的理解

一、epoll介绍

epoll是绝大多数网络框架的必备使用之一。
epoll是一种IO多路复用技术,在LINUX的网络编程里面,经常用来做事件触发,有特定的事件到来能够检测到,不必阻塞监听。想必不少人知道除了epoll外,经常提及的还有select/poll,相比两者,epoll速度响应更快,因为epoll只是去对活跃的IO进行操作,epoll的数据结构里面有相应的链表,用来存储就绪的IO,每次去内核copy的只是链表上就绪的IO,而不是全部的IO.而且select采用轮询的方式,对socket对的集合的描述表进行扫描,但是大多数的socket属于idle状态,所以实际上select做了许多的无用功。
但是反过来,如果socket大多是活跃的,那么epoll的效率反而会比select低。

二、epoll数据结构

epoll内部是通过红黑树和一个链表实现的,红黑树存储所有的IO,链表储存就绪的IO,图是网上的,如果涉及侵权,请联系我删除,谢谢:

在这里插入图片描述
可以看到,链表和红黑树使用的是同一个结点。实际上是红黑树管理所有的IO,当内部IO就绪的时候就会调用epoll的回调函数,将相应的IO添加到就绪链表上。数据结构有epitm和eventpoll,分别代表红黑树和单个结点,在单个结点上分别使用rbn和rblink使得结点同时指向两个数据结构。

二、epoll接口

众所周知,使用epoll进行编程的话,最重要的有三个API:epoll_create()、epoll_ctl()、epoll_wait();

1. int epoll_create(int size);
函数的作用:创建一个epoll句柄,实际上是创建红黑树的根节点,然后返回一个epoll句柄。
函数参数:从Linux2.6.8开始,size参数被忽略,只要是大于0,就都可以。
函数返回值:创建成功返回一个句柄;否则返回-1代表错误

2. int epoll_ctl(int epfd,int op, int fd,struct epoll_event *event);
函数作用:用于进行红黑树的相应操作,根据op的不同,进行增删改等操作。也就是对应IO的操作。
函数参数:
1> 代表的是的epoll_fd句柄,也就是epoll_create创建的epfd
2> 相应的操作,对应的是不同的宏:
EPOLL_CTL_ADD 注册、
EPOLL_CTL_MOD 修改、
EPOLL_CTL_DEL 删除
3> fd代表的是关联的文件描述符,也就是sockfd
4> 一个epoll_event结构体的指针,结构体如下

typedef union epoll_data {
	void ptr;
	int fd;
	__uint32_t u32;
	__uint64_t u64;
} epoll_data_t;
 
struct epoll_event {
	__uint32_t events;    / Epoll events /
	epoll_data_t data;    / User data variable /
};

结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件,其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器,服务器通过调用accept函数可以得到于这个client对应的socket文件描述符,可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行。epoll_event 结构体的events字段是表示感兴趣的事件和被触发的事件可能的取值为:EPOLLIN :表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET:表示对应的文件描述符设定为edge模式;
这一段取之博客:https://blog.csdn.net/wangpengqi/article/details/9933011

函数返回值:操作成功返回0,否则返回-1;

3. int epoll_wait(int epfd,struct epoll_event evetns,int maxevents,int timeout);
函数作用:去检测就绪链表是否有数据,并将有数据的IO复制到用户态,然后删除清空就绪链表。

函数参数:
1> epoll_fd和上面的一样
2> events是一个返回就绪IO的数组。
3> maxevents是每次能处理的最大事件数
4> timeout是等待IO事件发生的超时值;一般测试的时候是使用-1,代表不超时;0代表立即返回

函数返回值:成功返回就绪IO数;-1代表错误。

三、 LT与ET

epoll事件触发有两种方式:
LT: 水平触发
ET:边沿触发
对应的图:
在这里插入图片描述
设置的时候,是指epoll_ctl的第四个参数设置event = EPOLLIN | EPOLLLT 或者 event = EPOLLIN | EPOLLET分别对应水平和边沿触发。

水平触发和边沿触发影响到的是epoll回调函数的调用次数:边沿触发是和之前的event进行对比,如果发生改变则调用epoll的回调函数,若是水平触发,则是查看是否为EPOLLIN,是就一直调用回调函数。

epoll的一些记录就先写道这里,因为本人技术有限,在学习过程中很多借鉴到网上文章,如有侵权请联系删除,这里只是作为一个记录,防止以后忘记可以重复看,不是作为其他目的。

后面我会实现简单的一个epoll使用案例。到时候再贴出来。


版权声明:本文为weixin_43326322原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。