1. epoll概念
在Linux的Man文档中,我们可以看到如下定义Epoll - I/O event notification facility
epoll是一种I/O事件通知机制
I/O事件I/O
输入输出(input/output),输入输出的对象可以是 文件(file), 网络(socket), 进程之间的管道(pipe), 在linux系统中,都用文件描述符(fd)来表示
事件
可读事件, 当文件描述符关联的内核读缓冲区可读,则触发可读事件
什么是可读呢? 就是内核缓冲区非空,有数据可以读取
可写事件, 当文件描述符关联的内核写缓冲区可写,则触发可写事件
什么是可写呢?就是内核缓冲区不满,有空闲空间可以写入
通知机制通知机制,就是当事件发生的时候,去通知他
通知机制的反面,就是轮询机制
以上两点结合起来理解epoll是一种当文件描述符的内核缓冲区非空的时候,发出可读信号进行通知,当写缓冲区不满的时候,发出可写信号通知的机制
2. 水平触发与边缘触发
水平触发(level-trggered)只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,
当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知
边缘触发(edge-triggered)当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,
当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知两者的区别在哪里呢?水平触发是只要读缓冲区有数据,就会一直触发可读信号,而边缘触发仅仅在空变为非空的时候通知一次,举个例子:读缓冲区刚开始是空的
读缓冲区写入2KB数据
水平触发和边缘触发模式此时都会发出可读信号
收到信号通知后,读取了1kb的数据,读缓冲区还剩余1KB数据
水平触发会再次进行通知,而边缘触发不会再进行通知
所以边缘触发需要一次性的把缓冲区的数据读完为止,也就是一直读,直到读到EGAIN为止,EGAIN说明缓冲区已经空了,因为这一点,边缘触发需要设置文件句柄为非阻塞//水平触发
ret = read(fd, buf, sizeof(buf));
//边缘触发
while(true) {
ret = read(fd, buf, sizeof(buf);
if (ret == EAGAIN) break;
}
3. epoll接口介绍epoll_create
创建epoll实例,会创建所需要的红黑树,以及就绪链表,以及代表epoll实例的文件句柄int epoll_create(int size); Man文档中说明了在老的内核版本中,入参size用来指出创建的内部数据结构的大小,目前已经可以动态调整,但是为了兼容老的版本,所以仍然保留,这个size其实意义已经不大epoll_ctl
添加,修改,或者删除 注册到epoll实例中的文件描述符上的监控事件int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
对于添加到epfd的文件描述符fd, 添加或者删除或者修改, 对应的eventepfd: 通过epoll_create创建的文件描述符
op:操作类型
EPOLL_CTL_ADD, 为相应fd添加事件
EPOLL_CTL_MOD, 修改fd的事件
EPOLL_CTL_DEL,删除fd上的某些事件
fd: 操作的目标文件描述符
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 */
};
events可以是一组bit的组合
EPOLLIN:可读
EPOLLOUT: 可写
EPOLLET: 边缘触发,默认是水平触发epoll_waitint epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
等待注册的事件发生,返回事件的数目,并将触发的事件写入events数组中epfd: epoll实例文件描述符
events: 数组出参,用来记录被触发的events,其大小应该和maxevents一致
maxevents: 返回的events的最大个数,如果最大个数大于实际触发的个数,则下次epoll_wait的时候仍然可以返回
timeout: 等待事件,毫秒为单位 -1:无限等待 0:立即返回了解以上这些,面试是足够了,但是对于工程中的实际使用,仍然不足,后续会以epoll在redis中的使用为例,为大家进行剖析
作者:ld9183
链接:https://www.jianshu.com/p/41dc33b97419
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。