epoll使用与原理
使用要点
边缘模式(ET)与水平模式(LT)区别
下面内容来自linux man page
The epoll event distribution interface is able to behave both as edge-triggered (ET) and as level-triggered (LT). The difference between he two mechanisms can be described as follows. Suppose that this scenario happens:
1. The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.
2. A pipe writer writes 2 kB of data on the write side of the pipe.
3. A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.
4. The pipe reader reads 1 kB of data from rfd.
5. A call to epoll_wait(2) is done.
If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in step 5 will probably hang despite the available data still present in the file input buffer; meanwhile the remote peer might be expecting a response based on the data it already sent. The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor. So, in step 5 the caller might end up waiting for some data that is already present inside the input buffer. In the above example, an event on rfd will be generated because of the write done in 2 and the event is consumed in 3. Since theread operation done in 4 does not consume the whole buffer data, the call to epoll_wait(2) done in step 5 might block indefinitely.
简单来说,如果使用ET模式,对于同一个事件,内核只会上报一次。如果代码没有读取完所有可读取的数据,然后继续调用epoll_wait那么是不会收到事件的。ET模式一般要设定成setnonblocking模式,并且等到读取数据返回EAGAIN或者
如果使用LT模式,则调用epoll_wait后会继续有事件触发。LT模式与poll保持一样的语义,区别是比poll的性能更好一些。
读取数据要点
- 对于流式连接,例如pipe、fifo、tcp等,通过判定read的返回值比指定读取的小,来判断缓冲区中的数据已经读完了
- 对于数据报,例如udp等,则通常需要需要持续读取到EAGAIN返回,才能判断缓冲区数据已经读完了
- 每次从epoll_wait返回后都需要调用epoll_ctl往epoll中继续增加事件
惊群问题解决
- EPOLLEXCLUSIVE 当多个fd指向同一个文件,并且都被添加到epoll中,那么就可能产生惊群问题:一旦这个文件有被写入,那么read事件会触发给多个fd。加了这个标志后,保证至少一个能收到事件。
ET模式下的饥饿现象
某一个文件,可能来的数据非常多,持续的多,那么这个文件会不停的进行read(按照我们前面说的返回EAGAN或者返回小于指定大小的思路)。由于整个运行时单线程的,那么其他fd就会一直等待,造成了所谓的饥饿现象
epoll的饥饿模式如何避免?linux man page中给出的答案时,不直接在epoll_wait返回后直接读取数据,而是将可读的fd放到一个list里面。然后再对这个list中的fd分别执行read,可以通过限制每个fd一次read的字节数来控制切换到其他fd,当一个fd 读完后从list删除掉。
处理使用 epoll ET 模式下文件描述符出现饥饿的情况_epoll wait防饥饿-CSDN博客
句柄数限制
/proc/sys/fs/epoll/max_user_watches 中记录系统范围内,限制加入到epoll中的句柄数,实际上是限制句柄相关的内存(64位下160字节,32位下90字节)最多只能占用内存的4%。
内核实现原理
epoll_wait是如何实现的
- 用户调用epoll_wait,会通过syscall指令执行系统调用
- 系统调用统一入口根据系统调用号走到内核对应的sys_epoll_wait处理函数(内核用call指令 执行)
- 然后回判断epoolfd里面关联的文件句柄是否有可读的句柄
- 如果暂时没有那么epoll_wait线程就会等待在这些句柄的queue上
- 一旦这些文件句柄(例如socket),有数据进来后,内核的ksoftirqd线程会尝试唤醒线程,并从上次线程切换的位置宠幸执行sys_epoll_wait
注意:
- epoll_ctl会将epollfd加入到io句柄的等待队列中
参考资料
- 深入学习Linux_邋遢的流浪剑客的博客-CSDN博客
- linux 源码角度看 epoll - JackTang's Blog (jacktang816.github.io)
- Linux篇-select/poll/epoll源码分析 - 麦奇 (mikeygithub.github.io)
- 深入理解 epoll 原理 - 爱笑的张飞 - 博客园 (cnblogs.com)
- Linux man page 7
- Linux IO模式及 select、poll、epoll详解 - 人云思云 - SegmentFault 思否
epoll使用与原理的更多相关文章
- 深入理解NIO(四)—— epoll的实现原理
深入理解NIO(四)—— epoll的实现原理 本文链接:https://www.cnblogs.com/fatmanhappycode/p/12362423.html 终于来到最后了,万里长征只差最 ...
- Linux下select&poll&epoll的实现原理(一)
最近简单看了一把 linux-3.10.25 kernel中select/poll/epoll这个几个IO事件检测API的实现.此处做一些记录.其基本的原理是相同的,流程如下 先依次调用fd对应的st ...
- Linux下select&poll&epoll的实现原理(一)【转】
转自:http://www.cnblogs.com/lanyuliuyun/p/5011526.html 最近简单看了一把 linux-3.10.25 kernel中select/poll/epoll ...
- epoll详细工作原理(转)
原文:没有找到出处 开发高性能网络程序时,windows开发者们言必称iocp,linux开发者们则言必称epoll.大家都明白epoll是一种IO多路复用技术,可以非常高效的处理数以百万计的sock ...
- linux epoll的实现原理
1 linux的poll操作 linux文件的poll操作有两个主要目的:第一,主动查看该文件上是否有读写事件:第二,提供操作waitqueue的接口给epoll等上层接口使用,比如epoll可以通过 ...
- [转载] select, poll和epoll的区别
源地址:http://sheepxxyz.blog.163.com/blog/static/61116213201022003513530/ 随着2.6内核对epoll的完全支持,网络上很多的文章和示 ...
- 【转载】epoll的使用
select,poll,epoll简介 select select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理.这样所带来的缺点是: 1 单个进程可监视的fd数量被限制 2 需要维 ...
- 深入了解epoll (转)
一. 介绍 Epoll 是一种高效的管理socket的模型,相对于select和poll来说具有更高的效率和易用性.传统的select以及poll的效率会因为 socket数量的线形递增而导致呈二次乃 ...
- 为什么epoll会那么高效
参考(原文简直超赞):https://zhidao.baidu.com/question/687563051895364284.html下面是我结合原文写的,为了便于自己理解:关于阻塞和非阻塞的理解可 ...
- nginx中的epoll模型
要了解epoll模型,就要一个一个知识点由浅至深地去探索. 1.IO复用技术 IO流请求操作系统内核,有串行处理和并行处理两种概念. 串行处理是前面一个操作处理地时候,后面的所有操作都需要等待.因此, ...
随机推荐
- [FAQ] Python的虚拟环境和包管理
1. 创建虚拟环境 $ python -m venv test-env 2. 激活虚拟环境 windows:tutorial-env\Scripts\activate (powershell: . ...
- dotnet 将控制台 Console.WriteLine 内容输出到文件
很多伙伴喜欢使用 Console.WriteLine 打日志,也许是打起来顺手.打完了之后,又想着,要是能够输出到本机文件那就更好了.既然很多伙伴都有这个想法,那 dotnet 自然就是有方便的方法让 ...
- WPF 更改 DrawingVisual 的 RenderOpen 用到的对象的内容将持续影响渲染效果
在 WPF 里面,可以通过 DrawingVisual 来进行使用底层的绘制方法,此方法需要调用 DrawingVisual 的 RenderOpen 拿到 DrawingContext 类型的对象, ...
- C++多态与虚拟:运算符重载(Operator Overloading)
运算符重载:与function overloading异曲同工的是,C++提供所谓的Operator overloading.所谓operators是像 +(加)-(減)*(乘)/(除)>&g ...
- 普冉PY32系列(十五) PY32F0系列的低功耗模式
目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 普冉PY32系列(三) P ...
- Nginx在Windows 10、Ubuntu16.04、Centos7下的安装
目录 一. Windows 10 安装nginx 二. Ubuntu16.04 安装apt nginx 三. Centos7 yum安装nginx 四. ubuntu/centos编译安装nginx ...
- 深入理解Django:中间件与信号处理的艺术
title: 深入理解Django:中间件与信号处理的艺术 date: 2024/5/9 18:41:21 updated: 2024/5/9 18:41:21 categories: 后端开发 ta ...
- uniapp底层跨端原理
uniapp底层跨端原理 - 代码编写:开发者使用Vue.js框架编写uniapp的代码,包括页面结构.样式和逻辑等. - 编译过程:在编译过程中,uniapp会将Vue.js的代码转换为各个平台所需 ...
- C语言:如何打印星星
//打印星星 //k是两个上下部分都一样的空格 /*i j k k ...
- CentOS7 升级 curl 到 HTTP2
目录 文章目录 目录 编译安装 YUM 升级 编译安装 安装编译环境: yum -y groupinstall "Development Tools" yum -y install ...