套接字知识整理009-epoll 的高性能原理是什么 发布人: sanye 时间: 2021-02-26 分类: 网络SOCKET编程 ## 前言 epoll 的高性能原理是什么 ## 本质 本质上 `epoll` 还是一种` I/O` 多路复用技术, `epoll` 通过监控注册的多个描述字,来进行 `I/O` 事件的分发处理。 epoll 不仅提供了默认的 `level-triggered`(条件触发)机制,还提供了性能更为强劲的 `edge-triggered`(边缘触发)机制。至于这两种机制的区别,我会在后面详细展开。 ## epoll 创建网络程序三个步骤: | 步骤 | | :------------- | | epoll_create | | epoll_ctl | | epoll_wait | ## 函数说明 ## epoll_create epoll_create1 | 函数 | 函数描述 | | :------------- | :------------- | | int epoll_create(int size); |告知内核期望监控的文件描述字大小,然后内核使用这部分的信息来初始化内核数据结构| |int epoll_create1(int flags); | 这个参数不再被需要,因为内核可以动态分配需要的内核数据结构。我们只需要注意,每次将 size 设置成一个大于 0 的整数就可以了。 | ## epoll_ctl | 函数 | 函数描述 | | :------------- | :------------- | | int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);|可以通过调用 epoll_ctl 往这个 epoll 实例增加或删除监控的事件。函数 epll_ctl 有 4 个入口参数。| ### 参数 | 参数 | 参数描述 |参数选项| | :------------- | :------------- | :------------- | |epfd|刚刚调用 `epoll_create` 创建的 `epoll` 实例描述字,可以简单理解成是 `epoll` 句柄。|| |op|增加还是删除一个监控事件,它有三个选项可供选择|`EPOLL_CTL_ADD:` 向 `epoll` 实例注册文件描述符对应的事件;`EPOLL_CTL_DEL`:向 `epoll` 实例删除文件描述符对应的事件; `EPOLL_CTL_MOD` : 修改文件描述符对应的事件。| |fd|注册的事件的文件描述符,比如一个监听套接字。|| |epoll_event|注册的事件类型,并且可以在这个结构体里设置用户需要的数据,其中最为常见的是使用联合结构里的 fd 字段,表示事件所对应的文件描述符| | ```c++ 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 events 事件类型 | 事件 | 描述 | | :------------- | :------------- | | EPOLLIN | 对应的文件描述字可以读; | | EPOLLOUT | 对应的文件描述字可以写; | | EPOLLRDHUP | 套接字的一端已经关闭,或者半关闭 | | EPOLLHUP | 表示对应的文件描述字被挂起 | | EPOLLET | 设置为 `edge-triggered`,默认为 `level-triggered`。 | ## epoll_wait ```c++ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); 返回值: 成功返回的是一个大于0的数,表示事件的个数;返回0表示的是超时时间到;若出错返回-1. ``` | 参数 | 描述 | | :------------- | :------------- | | epfd | epoll 实例描述字,也就是 epoll 句柄。 | |epoll_event|返回给用户空间需要处理的 `I/O` 事件,这是一个数组,数组的大小由 `epoll_wait` 的返回值决定,这个数组的每个元素都是一个需要待处理的 `I/O` 事件,其中 `events` 表示具体的事件类型,事件类型取值和 `epoll_ctl` 可设置的值一样,这个 `epoll_event` 结构体里的 `data` 值就是在 `epoll_ctl` 那里设置的 `data`,也就是用户空间和内核空间调用时需要的数据。| |maxevents|一个大于 0 的整数,表示 epoll_wait 可以返回的最大事件值。| |epoll_wait |阻塞调用的超时值,如果这个值设置为 -1,表示不超时;如果设置为 0 则立即返回,即使没有任何 I/O 事件发生。| ## edge-triggered 和 level-triggered 区别 | edge-triggered | level-triggered | | :------------- | :------------- | | 边缘触发 |条件触发 | |边缘触发的意思是只有第一次满足条件的时候才触发,之后就不会再传递同样的事件了。|只要满足事件的条件,比如有数据需要读,就一直不断地把这个事件传递给用户| |效率高|效率低| ## epoll 历史 | 时间 | 事件 | | :------------- | :------------- | | 1994 | Windows 系统就已经引入了 IOCP,这是一个异步 I/O 模型,用来支持高并发的网络 I/O | |2000| FreeBSD引入了 Kqueue——一个 I/O 事件分发框架。| |2002 |Linux 引入了 epoll,不过相关工作的讨论和设计早在 2000 年就开始了| >Linus 把 `keque` 里面的 `kevent` 函数拆分了两个部分,一部分负责事件绑定,通过 `bind_event` 函数来实现;另一部分负责事件等待,通过 `get_events` 来实现。 标签: 系统, 框架, 机制, int, 函数, 设计, 实例, 文件, 前言, 程序, 动态, 类型, 网络, 描述, 事件, events, epoll 本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。 取消回复 添加新评论 阁下尊名? 📮邮箱(选填) 博客/主页(选填) 大侠请赐教 !支持Markdown格式 spam send以上是我的留言/建议,请查收! 上一篇: 套接字知识整理008-阻塞和非阻塞IO,多路复用,异步IO之间的区别,以及不同函数之间的应用 下一篇: 003-npm 和 npx 的使用区分 apps format_list_bulleted publish 目录 标签 前言 系统 函数 代码 文件 核心 功能 内容 命令 事件 对象 组件 设计 程序 类型 业务 版本 变量 行 数据 分类 默认知识库数学知识库常数数学公式/推导数论统计学机器学习Prolog算法理论深度学习增强现实数据分析计算机知识库网络网络SOCKET编程网络安全nginx汇编/二进制架构设计UML图架构心经范式编程函数式Erlang面向对象JavaC++coding技巧存储中间件MySQL mongodb虚拟化技术Docker操作系统/运维RHCA笔记RHCEAnsible小书常用命令windowslinux编译技术编译原理客户端ios大前端TypeScriptnodejsangularng8Vue浏览器API建筑知识库