epoll的由来
reference
https://www.zhihu.com/question/20122137
数据流有两个重要的参与者:
1、往流中写入数据者
2、从流中读取数据者
假设两个参与者之间,使用一个缓冲区来存放数据,即a往缓冲区中写入数据,b从缓冲区中读出数据。那么对单个流而言,会存在四种状态:
0、当缓冲区为空时,b阻塞,等待数据到达;
1、当a往缓冲区写入数据时,缓冲区非空,b将被从阻塞状态中唤醒;
2、当a拼命往缓冲区中写入数据,而b没有去读,或读的速度跟不上a写入的速度时,缓冲区满。此时,需要通知a进行阻塞,等待缓冲区中重新腾出空间;
3、当b从缓冲区中读出部分数据后,缓冲区非满,则可以通知a从阻塞状态中醒来;
4、当a不再往缓冲区中写数据,而b一直读,将缓冲区中的数据读完时,将变成缓冲区空,此时通知b进入阻塞状态,等待有数据到来。
当有多个流时,可以考虑用轮训的方式逐一查看每个流目前是否有数据,若有,则进行处理。(非阻塞忙轮询--一直主动查看流的状态)
缺点:cpu空耗在无用的流缓冲区检查上,浪费时间。
改进:引入一个代理人(select),当代理人感知到有一个或多个流的数据有变化时,再进行轮询检查。(非阻塞轮询--有流的状态发生变化时,主动检查所有流的状态)
缺点:当只有一个或少数流有更新时,遍历检查所有的流非常浪费时间。(故,亦称为无差别轮询)
改进:当有流的状态改变时,仅处理该流相关的数据变化。(epoll--event poll,事件轮询,精确到“什么流”发生了“什么事件”)
具体实现是引入了一个红黑树及一个就绪列表。
epoll的关键操作:
1、创建一个epoll对象
epollfd=epoll_create()
此时,会在内核中专属于epoll的高速cache区新建一棵红黑树以及一个就绪列表。
2、往epoll中添加或删除某个流的某个事件
epoll_ctl(epollfd, EPOLL_CTL_ADD, socket, EPOLLIN)
epoll_ctl(epollfd, EPOLL_CTL_DEL, socket, EPOLLOUT)
"add"动作会将文件句柄(socket)加入到红黑树中,并向内核注册改句柄的回调函数,当内核检测到该句柄可读或可写时(由中断触发),就将该句柄对应的回调函数加入到就绪列表中。
3、等待事件发生
epoll_wait(epollfd,...)
epoll_wait函数只需要关注就绪列表即可。
当就绪列表中有就绪的socket时,就将这些socket拷贝到用户态,并清空就绪列表。
而后,还会检查这些socket的触法形式(水平出发or边缘触法)
若是水平触发(lt),则若这些socket中还有未处理的事件时,就再把它们加回到就绪列表中;
若是边缘触发(et),则只有当下一次中断到达时,才会把这个socket加回到就绪列表中。
从伪代码上可以更明显的看出三种轮询的区别:
无阻塞忙轮询:
while true{
for i in stream[]{
if i has data
read until unavailable
}
}
无阻塞轮询(无差别轮询):
while true{
select(stream[])
for i in stream[]{
if i has data
read until unavailable
}
}
事件轮询(epoll):
while true{
active_stream[] = epoll_wait(epollfd)
for i in active_stream[]{
read or write until unavailable
}
}

epoll的由来的更多相关文章
- 高性能网络服务器编程:为什么linux下epoll是最好,Netty要比NIO.2好?
基本的IO编程过程(包括网络IO和文件IO)是,打开文件描述符(windows是handler,java是stream或channel),多路捕获(Multiplexe,即select和poll和ep ...
- 从I/O复用谈epoll为什么高效
上一篇文章中,谈了一些网络编程的基本概念.在现实使用中,用的最多的就是I/O复用了,无非就是select,poll,epoll 很多人提到网络就说epoll,认为epoll效率是最高的.单纯的这么认为 ...
- select、poll、epoll之间的区别总结
select.poll.epoll之间的区别总结 05/05. 2014 select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪 ...
- (转载) Linux IO模式及 select、poll、epoll详解
注:本文是对众多博客的学习和总结,可能存在理解错误.请带着怀疑的眼光,同时如果有错误希望能指出. 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案 ...
- linux下select/poll/epoll机制的比较
select.poll.epoll简介 epoll跟select都能提供多路I/O复用的解决方案.在现在的Linux内核里有都能够支持,其中epoll是Linux所特有,而select则应该是POSI ...
- epoll LT/ET 深度剖析
EPOLL事件的两种模型: Level Triggered (LT) 水平触发 .socket接收缓冲区不为空 有数据可读 读事件一直触发 .socket发送缓冲区不满 可以继续写入数据 写事件一直触 ...
- 非阻塞/异步(epoll) openssl
前段时间在自己的异步网络框架handy中添加openssl的支持,当时在网络上搜索了半天也没有找到很好的例子,后来自己慢慢的摸索,耗费不少时间,终于搞定.因此把相关的资料整理一下,并给出简单的例子,让 ...
- select,epoll,poll比较
介绍和比较 http://www.cnblogs.com/maociping/p/5132583.html 比较 http://www.dataguru.cn/thread-336032-1-1.ht ...
- Linux epoll
一. epoll函数集 epoll主要有三个函数: 1. int epoll_create(int size); 创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大.这个参数不同于 ...
随机推荐
- Linux proc目录下 几个系统文件下的各项参数 (cpuinfo,uptime,meminfo,stat,loadavg)
参考链接: Linux 操作系统内核基本实验.pdf http://max.book118.com/html/2015/0919/25787869.shtm Linux下cpuinfo文件各项参数的详 ...
- 求链表的倒数第m个元素
法一: 首先遍历一遍单链表,求出整个单链表的长度n,然后将倒数第m个,转换为正数第n-m+1个,接下去遍历一次就可以得到结果. 不过这种方法需要对链表进行两次遍历,第一次遍历用于求解单链表的长度,第二 ...
- hdu 1166 敌兵布阵【线段树】(求给定区间和)
题目链接:https://vjudge.net/contest/182746#problem/B 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) ...
- Spring框架学习09——基于AspectJ的AOP开发
1.基于注解开发AspectJ (1)AspectJ注解 基于注解开发AspectJ要比基于XML配置开发AspectJ便捷许多,所以在实际开发中推荐使用注解方式.关于注解的相关内容如下: @Aspe ...
- Linux成长之路
Linux命令格式: 命令 选项 参数command [-options] [parameter1] ···· 常用命令: tree 以目录树的方式显示: tree / 以目录树方式显示根目录结构 ...
- Linux输入设备详解
<什么是Linux输入设备> ➤简介 Linux输入设备总类繁杂,常见的包括有按键.键盘.触摸屏.鼠标.摇杆等等,他们本身就是字符设备,而linux内核将这些设备的共同性抽象出来 ...
- mfc调用cmd执行完保留黑框
mfc调用cmd的方法有很多,本文采用 ShellExecute ShellExecute(AfxGetMainWnd()->m_hWnd,L"open",L"cm ...
- Python图形编程探索系列-05-用控制变量构建对话程序
跳转到自己的博客 控制变量 变量 符号 意义 默认值 1 var = tk.BooleanVar() 布尔型 0 2 var = tk.StringVar() 字符串控制变量 空字符串 3 var = ...
- 【模板】倍增LCA
题号:洛谷3379 %:pragma GCC optimize ("Ofast") #include<cstdio> #include<vector> #i ...
- c++模板 与 泛型编程基础
C++模板 泛型编程就是以独立于任何特定类型的方式编写代码,而模板是泛型编程的基础. (1)定义函数模板(function template) 函数模板是一个独立于类型的函数,可以产生函数的特定类型版 ...