IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 简谈epoll -> 正文阅读

[Java知识库]简谈epoll

I/O编程关注的问题

epoll我们经常使用在网络编程I/O模型中,在此模型中我们主要关注的问题点是连接如何建立,连接何时断开,消息如何到达,消息是否发送完毕。 用户空间监测内核的消息得到这个结果。
在这里插入图片描述
在上图的蓝色框中,我们主要的关注的是读写是否被阻塞,数据是否达到,到达了怎么通知给用户空间。

推荐免费的直播课程: https://ke.qq.com/course/417774?flowToken=1040690

阻塞io模型和?阻塞io模型

  • 阻塞在哪里?
  • 什么来决定阻塞还是非阻塞?
//连接的fd
fcntl(c->fd, F_SETFL, O_NONBLOCK);
  • 阻塞和非阻塞具体的差异是什么?
io函数在数据未到达时是否?刻返回

在这里插入图片描述
在这里插入图片描述
阻塞模型和非阻塞模型主要区别在数据准备阶段是否立刻返回,如果是在阻塞模型,数据准备阶段和数据拷贝阶段都会被阻塞,处理时间会比较长;在非阻塞模型中,如果在数据准备阶段,调用read/recv会立刻给一个结果(为准备好返回-1)。

I/O多路复用

I/O多路复用主要有slect, poll 和 epoll 三个主要的函数。这里我们主要介绍epoll函数。实现的机制主要是使用一个线程来检测多个io事件,把相应的事件fd添加到epoll中,使用epoll来管理。如果读写事件准备好时,epoll会触发相应的世间来通知到用户。
在这里插入图片描述

epoll的API

epoll的核心是3个API,核心数据结构是:1个红黑树和1个链表组成。

struct eventpoll {
// ...
struct rb_root rbr; // 管理 epoll 监听的事件
struct list_head rdllist; // 保存着 epoll_wait 返回满?条件的事件
// ...
};
struct epitem {
// ...
struct rb_node rbn; // 红?树节点
struct list_head rdllist; // 双向链表节点
struct epoll_filefd ffd; // 事件句柄信息
struct eventpoll *ep; // 指向所属的eventpoll对象
struct epoll_event event; // 注册的事件类型
// ...
};
struct epoll_event {
__uint32_t events;
epoll_data_t data; // 保存 关联数据
};
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
}epoll_data_t;

主要函数

  • epoll_create系统调?
int epoll_create(int size);

size参数告诉内核这个epoll对象会处理的事件?致数量,?不是能够处理的事件的最?数(同时,size不要传0,会报invalid argument错误)。
在现在linux版本中,这个size参数已经没有意义了;
返回: epoll对象句柄;之后针对该epoll的操作需要通过该句柄来标识该epoll对象;

  • epoll_ctl系统调?
int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);

typedef union epoll_data {
    void *ptr; /* 指向用户自定义数据 */
    int fd; /* 注册的文件描述符 */
    uint32_t u32; /* 32-bit integer */
    uint64_t u64; /* 64-bit integer */
} epoll_data_t;

struct epoll_event {
    uint32_t events; /* 描述epoll事件 */
    epoll_data_t data; /* 见上面的结构体 */
};

epoll_ctl向epoll对象添加、修改或删除事件;
返回: 0表示成功, -1表示错误,根据errno错误码判断错误类型。
op类型:

EPOLL_CTL_ADD 添加新的事件到epoll中
EPOLL_CTL_MOD 修改epoll中的事件
EPOLL_CTL_DEL 删除epoll中的事件

event.events 取值:

EPOLLIN 表示该连接上有数据可读(tcp连接远端主动关闭连接,也是可读事件,因为需要处理发送来的FIN包; FIN包就是read 返回 0)
EPOLLOUT 表示该连接上可写发送(主动向上游服务器发起?阻塞tcp连接,连接建?成功事件相当于可写事件)
EPOLLRDHUP 表示tcp连接的远端关闭或半关闭连接
EPOLLPRI 表示连接上有紧急数据需要读
EPOLLERR 表示连接发?错误
EPOLLHUP 表示连接被挂起
EPOLLET 将触发?式设置为边缘触发,系统默认为?平触发
EPOLLONESHOT 表示该事件只处理?次,下次需要处理时需重新加?epoll
  • epoll_wait系统调?
int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);

收集 epoll 监控的事件中已经发?的事件,如果 epoll 中没有任何?个事件发?,则最多等待timeout 毫秒后返回。
返回:表示当前发?的事件个数
返回0表示本次没有事件发?;
返回-1表示出现错误,需要检查errno错误码判断错误类型。

注意:
events 这个数组必须在?户态分配内存,内核负责把就绪事件复制到该数组中;
maxevents 表示本次可以返回的最?事件数?,?般设置为 events 数组的?度;
timeout表示在没有检测到事件发?时最多等待的时间;如果设置为0,检测到rdllist为空?刻返回;如果设置为-1,?直等待;
所有添加到epoll中的事件都会与?卡驱动程序建?回调关系,相应的事件发?时会调?这?的回调?法(ep_poll_callback) ,它会把这样的事件放在rdllist双向链表中。
在这里插入图片描述

epoll的两种触发方式

epoll监控多个文件描述符的I/O事件。epoll支持边缘触发(edge trigger,ET)或水平触发(level trigger,LT),通过epoll_wait等待I/O事件,如果当前没有可用的事件则阻塞调用线程。ET模式可以理解为状态的改变(无数据->有数据, 有数据->无数据), 而LT可理解为一直持续的某种状态(数据不为空或者不满)。
select和poll只支持LT工作模式,epoll的默认的工作模式是LT模式。

1. 水平触发的时机

  • 对于读操作,只要缓冲内容不为空,LT模式返回读就绪。
  • 对于写操作,只要缓冲区还不满,LT模式会返回写就绪。
    当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你。如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率。
    LT模式适合一次性读大数据。

2. 边缘触发的时机

  • 对于读操作
    当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候。
    当有新数据到达时,即缓冲区中的待读数据变多的时候。
    当缓冲区有数据可读,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时。

当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你。这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符。
ET模式适合读少数据。

在这里插入图片描述

epoll与select、poll的对比

1. 用户态将文件描述符传入内核的方式

  • select:创建3个文件描述符集并拷贝到内核中,分别监听读、写、异常动作。这里受到单个进程可以打开的fd数量限制,默认是1024。
  • poll:将传入的struct pollfd结构体数组拷贝到内核中进行监听。
  • epoll:执行epoll_create会在内核的高速cache区中建立一颗红黑树以及就绪链表(该链表存储已经就绪的文件描述符)。接着用户执行的epoll_ctl函数添加文件描述符会在红黑树上增加相应的结点。

2. 内核态检测文件描述符读写状态的方式

  • select:采用轮询方式,遍历所有fd,最后返回一个描述符读写操作是否就绪的mask掩码,根据这个掩码给fd_set赋值。

  • poll:同样采用轮询方式,查询每个fd的状态,如果就绪则在等待队列中加入一项并继续遍历。

  • epoll:采用回调机制。在执行epoll_ctl的add操作时,不仅将文件描述符放到红黑树上,而且也注册了回调函数,内核在检测到某文件描述符可读/可写时会调用回调函数,该回调函数将文件描述符放在就绪链表中。

3. 找到就绪的文件描述符并传递给用户态的方式

  • select:将之前传入的fd_set拷贝传出到用户态并返回就绪的文件描述符总数。用户态并不知道是哪些文件描述符处于就绪态,需要遍历来判断。

  • poll:将之前传入的fd数组拷贝传出用户态并返回就绪的文件描述符总数。用户态并不知道是哪些文件描述符处于就绪态,需要遍历来判断。

  • epoll:epoll_wait只用观察就绪链表中有无数据即可,最后将链表的数据返回给数组并返回就绪的数量。内核将就绪的文件描述符放在传入的数组中,所以只用遍历依次处理即可。这里返回的文件描述符是通过mmap让内核和用户空间共享同一块内存实现传递的,减少了不必要的拷贝。

4. 重复监听的处理方式

  • select:将新的监听文件描述符集合拷贝传入内核中,继续以上步骤。
  • poll:将新的struct pollfd结构体数组拷贝传入内核中,继续以上步骤。
  • epoll:无需重新构建红黑树,直接沿用已存在的即可。

epoll更高效的原因

  • select和poll的动作基本一致,只是poll采用链表来进行文件描述符的存储,而select采用fd标注位来存放,所以select会受到最大连接数的限制,而poll不会。
  • select、poll、epoll虽然都会返回就绪的文件描述符数量。但是select和poll并不会明确指出是哪些文件描述符就绪,而epoll会。造成的区别就是,系统调用返回后,调用select和poll的程序需要遍历监听的整个文件描述符找到是谁处于就绪,而epoll则直接处理即可。
  • select、poll都需要将有关文件描述符的数据结构拷贝进内核,最后再拷贝出来。而epoll创建的有关文件描述符的数据结构本身就存于内核态中,系统调用返回时利用mmap()文件映射内存加速与内核空间的消息传递:即epoll使用mmap减少复制开销。
  • select、poll采用轮询的方式来检查文件描述符是否处于就绪态,而epoll采用回调机制。造成的结果就是,随着fd的增加,select和poll的效率会线性降低,而epoll不会受到太大影响,除非活跃的socket很多。
  • epoll的边缘触发模式效率高,系统不会充斥大量不关心的就绪文件描述符

虽然epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

Reference:
https://www.jianshu.com/p/31cdfd6f5a48

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:12:19  更:2021-11-23 12:13:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:59:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码