EPOLL相关接口和原理
这里写目录标题
- epoll介绍
- 操作函数
- epoll_create()
- epoll_ctl()
- epoll_wait()
- 操作步骤
epoll介绍
epoll底层模型是一个红黑树,红黑树的每一个节点(每一个节点代表一个文件描述符)都对应一组事件(events),当某个文件描述符就绪了,就会触发相关的事件,每出发一个事件,就会有一个相关的处理函数被调用。
操作函数
#include<sys/epoll.h>
//创建epoll实例,通过一棵红黑树管理待检测集合
int epoll_create(int size);
//管理红黑树上的文件描述符(添加,修改,删除)
int epoll_ctl(int epfd, int op , int fd , struct epoll_event * event);
//检测 epoll 树中是否有就绪的文件描述符
int epoll_wait ( int epfd , struct epoll_event * events , int maxevents , int timeout );
epoll_create()
会创建一个epoll的实例,(也就是红黑树)
返回值:epoll 实例的 文件描述符,通过这个文件描述符来操作红黑树。
epoll_ctl()
int epoll_ctl(int epfd, int op , int fd , struct epoll_event * event);
int epfd : epoll 实例的文件描述符。
int op:
EPOLL_CTL_ADD : 在红黑树中添加文件描述符,并且指定检测的事件。
EPOLL_CTL_MOD : 修改已经添加到树节点的文件描述符的事件。
EPOLL_CTL_DEL : 删除已经添加到epoll树中的文件描述符
typedef union epoll_data{void *ptr;int fd;uint32_t u32;uint64_t u64;} epoll_data_t;struct epoll_event {uint32_t events; //事件epoll_data_t data;}
events 的取值,对应各种事件。
EPOLLIN : 检测文件描述符的读事件,也就是检测这个文件描述符的读缓冲区中是否还有数据。
EPOLLOUT : 检测文件描述符的写事件,也就是检测写缓冲区是否可写。
EPOLLERR
EPOLLET 水平出发模式,边沿触发模式。
返回值:成功返回0,失败返回 -1 。
epoll_wait()
int epoll_wait (int epfd , struct spoll_event *events , int maxevents , int timeout);
检测添加到树上所有的节点是不是已经处于就绪状态;
如果有处于就绪状态的文件描述符,这个状态就会返回。
告诉我们有哪些文件描述符是就绪的。
如果树上没有就绪的文件描述符,这个就会一直阻塞,一直检测。
struct spoll_event *events : 传出参数,
操作步骤
1,创建监听的套接字
int lfd = socket(AF_INET,SOCK_STREAM);
2,设置端口复用(可选)
int opt = 1;
setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
3,使用本地的 ip 与端口和监听的套接字进行绑定
int ret = bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
4,给监听的套接字设置监听
listen(lfd,128);
5,创建epoll实例对象
// An highlighted block
int epfd = epoll_create(100);
6,将用于监听的套接字添加到epoll实例中
// An highlighted block
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = lfd;
int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);
7,检测添加到epoll实例中的文件描述符是否已经就绪并且将这些已就绪的文件描述符进行处理int num = epoll_wait(epfd,evs,size,-1);如果是监听的文件描述符,和新客户端连接,将此文件描述符加入epoll树中int cfd = accept(curfd,NULL,NULL);ev.events = EPOLLIN;ev.data.fd = cfd;epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);如果是通信的文件描述符,和对应客户端通信