当前位置: 首页 > 编程日记 > 正文

[epoll]epoll理解

转自:http://blog.51cto.com/yaocoder/888374

1. 流

首先我们来定义的概念,一个流可以是文件,socket,pipe等等,可以进行I/O操作的内核对象,不管是文件,还是套接字,还是管道,我们都可以把他们看作流。
之后我们来讨论I/O的操作,通过read,我们可以从流中读入数据;通过write,我们可以往流写入数据。现在假定一个情形,我们需要从流中读数据,但是流中还没有数据,典型的例子为,客户端要从socket读出数据,但是服务器还没有把数据传回来,这时候该怎么办?

2. 阻塞与非阻塞

  • 阻塞:阻塞是个什么概念呢?比如某个时候你在等快递,但是你不知道快递什么时候过来,而且你没有别的事可以干,或者说接下来的事要等快递来了才能做;那么你可以去睡觉了,因为你知道快递把货送来时一定会给你打个电话(假定一定能叫醒你)。
  • 非阻塞忙轮询:接着上面等快递的例子,如果用忙轮询的方法,那么你需要知道快递员的手机号,然后每分钟给他挂个电话:“你到了没?”
很明显一般人不会用第二种做法,不仅显很无脑,浪费话费不说,还占用了快递员大量的时间。大部分程序也不会用第二种做法,因为第一种方法经济而简单,经济是指消耗很少的CPU时间,如果线程睡眠了,就掉出了系统的调度队列,暂时不会去瓜分CPU宝贵的时间片了。

3. 缓冲区

为了了解阻塞是如何进行的,我们来讨论缓冲区,以及内核缓冲区,最终把I/O事件解释清楚。缓冲区的引入是为了减少频繁I/O操作而引起频繁的系统调用(你知道它很慢的),当你操作一个流时,更多的是以缓冲区为单位进行操作,这是相对于用户空间而言。对于内核来说,也需要缓冲区。
假设有一个管道,进程A为管道的写入方,B为管道的读出方。
  1. 假设一开始内核缓冲区是空的,B作为读出方,被阻塞着。然后首先A往管道写入,这时候内核缓冲区由空的状态变到非空状态,内核就会产生一个事件告诉B该醒来了,这个事件姑且称之为“缓冲区非空”
  2. 但是“缓冲区非空”事件通知B后,B却还没有读出数据;
  3. 且内核许诺了不能把写入管道中的数据丢掉这个时候,A写入的数据会滞留在内核缓冲区中,如果内核也缓冲区满了,B仍未开始读数据,最终内核缓冲区会被填满,这个时候会产生一个I/O事件,告诉进程A,你该等等(阻塞)了,我们把这个事件定义为“缓冲区满”
  4. 假设后来B终于开始读数据了,于是内核的缓冲区空了出来,这时候内核会告诉A,内核缓冲区有空位了,你可以从长眠中醒来了,继续写数据了,我们把这个事件叫做“缓冲区非满”
  5. 也许该事件已经通知了A,但是A也没有数据写入了,而B继续读出数据,知道内核缓冲区空了。这个时候内核就告诉B,你需要阻塞了!,我们把这个事件定为“缓冲区空”
这四个事件涵盖了四个I/O事件,缓冲区满,缓冲区空,缓冲区非空,缓冲区非满(注都是说的内核缓冲区,且这四个术语都是我生造的,仅为解释其原理而造)。这四个I/O事件是进行阻塞同步的根本。(如果不能理解“同步”是什么概念,请学习操作系统的锁,信号量,条件变量等任务同步方面的相关知识)。

4. 阻塞I/O和非阻塞I/O缺点

然后我们来说说阻塞I/O的缺点。阻塞I/O模式下,一个线程只能处理一个流的I/O事件。如果想要同时处理多个流,要么多进程(fork),要么多线程(pthread_create),很不幸这两种方法效率都不高。于是再来考虑非阻塞忙轮询的I/O方式,我们发现我们可以同时处理多个流了(把一个流从阻塞模式切换到非阻塞模式在此不予讨论):
while true {for i in stream[]; {if i has dataread until unavailable}
}            
我们只要不停的把所有流从头到尾问一遍,又从头开始。这样就可以处理多个流了,但这样的做法显然不好,因为如果所有的流都没有数据,那么只会白白浪费CPU。这里要补充一点,阻塞模式下,内核对于I/O事件的处理是阻塞或者唤醒,而非阻塞模式下则把I/O事件交给其他对象(后文介绍的select以及epoll)处理甚至直接忽略。

5. Select和Poll

为了避免CPU空转,可以引进了一个代理(一开始有一位叫做select的代理,后来又有一位叫做poll的代理,不过两者的本质是一样的)。这个代理比较厉害,可以同时观察许多流的I/O事件,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态中醒来,于是我们的程序就会轮询一遍所有的流(于是我们可以把“忙”字去掉了)。代码长这样:
while true {select(streams[])for i in streams[] {if i has dataread until unavailable}
}
于是,如果没有I/O事件产生,我们的程序就会阻塞在select处。但是依然有个问题,我们从select那里仅仅知道了,有I/O事件发生了,但却并不知道是那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。使用select,我们有O(n)的无差别轮询复杂度,同时处理的流越多,没一次无差别轮询时间就越长。

6. Epoll

再次说了这么多,终于能好好解释epoll了
epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll之会把哪个流发生了怎样的I/O事件通知我们。此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))在讨论epoll的实现细节之前,先把epoll的相关操作列出:
epoll_create //创建一个epoll对象,一般epollfd = epoll_create()
epoll_ctl (epoll_add/epoll_del的合体);//往epoll对象中增加/删除某一个流的某一个事件
//比如
epoll_ctl(epollfd, EPOLL_CTL_ADD, socket, EPOLLIN);//注册缓冲区非空事件,即有数据流入
epoll_ctl(epollfd, EPOLL_CTL_DEL, socket, EPOLLOUT);//注册缓冲区非满事件,即流可以被写入
epoll_wait(epollfd,...)等待直到注册的事件发生
(注:当对一个非阻塞流的读写发生缓冲区满或缓冲区空,write/read会返回-1,并设置errno=EAGAIN。而epoll只关心缓冲区非满和缓冲区非空事件)。
一个epoll模式的代码大概的样子是:
while true {active_stream[] = epoll_wait(epollfd)for i in active_stream[] {read or write till}
}

转载于:https://www.cnblogs.com/aaronLinux/p/9039629.html

相关文章:

[kuangbin带你飞]专题五 并查集 E - 食物链 (带权并查集)

E - 食物链 题目链接:https://vjudge.net/contest/66964#problem/E 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。 现有N个动物,以1-N编号。每个动物都是A,B,C中的一种…

关于内网linux系统如果安装nodejs,npm,express,mongodb,forever等

内网的linux系统要安装nodejs以及express等系列的框架,因为系统是局域网和互联网是物理隔离的,所以,没法像官网的安装教程那样直接install了,只能手动安装,这里已经我们自己的linux 系统suse10 为例: 1 No…

【基础知识】如何在word中粘贴出漂亮整洁的代码

使用工具: notepad、WPS 操作实现: 1、右击代码文件使用NPP打开文件 2、选中要复制的代码 3、如图所示,依次点击如下内容 4、直接粘贴到word中,如图

浅析SQL Server数据修复命令DBCC的使用

SQL Server数据库提供了修复命令DBCC,当SQL Server数据库遭到质疑或者是有的无法完成读取时可以尝试用此命令来修复。以下是一些常见的DBCC修复命令,希望会给读者带来帮助。 1. DBCC CHECKDB 重启服务器后,在没有进行任何操作的情况下&#x…

Python之Mysql及SQLAlchemy操作总结

一、Mysql命令总结 1.创建库 create database test1; 2.授权一个用户 grant all privileges on *.* to feng% identified by 1qazWSX; 3.创建表 create table Teacher(teaId int not null, teaname varchar(100), age int, sex enum(M, F), phone int); 4.查询 select * from t…

NSwagStudio for Swagger Api

本案例主要说明如何使用NSwag 工具使用桌面工具快速生成c# 客户端代码、快速的访问Web Api。 NSwagStudio 下载地址 比较强大、可以生成TypeScript、WebApi Controller、CSharp Client 1、运行WebApi项目 URL http://yourserver/swagger 然后你将看到界面如下 1.1 Web API 代…

【html】如何解决标签设置成超链接后字体格式及颜色变化的问题

问题描述: 如图所示,将一个标签设置成超链接后字体颜色和格式会发生改变,如果我只想让它保持原来的格式应该怎么办? 解决方法: 在a标签中添加一个属性: style"color:inherit;" 添加后的代码&…

js判断 IE 浏览器

1 $.browser.msie && ($.browser.version 6.0) 转载于:https://www.cnblogs.com/zhupinglei/archive/2012/04/28/2475186.html

UNIX编程笔记:关于停止的进程接收信号的问题

为什么80%的码农都做不了架构师?>>> 因为资料缺少,按照测试得出来,停止状态的进程貌似只对SIGCONT有反应,而别的默认就是忽略。 转载于:https://my.oschina.net/kut/blog/27736

脱壳 VMProtect 1.70.4

【文章标题】: 脱壳 VMProtect 1.70.4 【文章作者】: hxqlky【作者邮箱】: zmunlkygmail.com【作者主页】: http://www.x5dj.com/hxqlky【下载地址】: 自己搜索下载【加壳方式】: VMProtect 1.70.4【保护方式】: VMProtect 1.70.4【编写语言】: MASM32 / TASM32 【使用工具】:…

互联网协议详解

本文转载自:https://www.cnblogs.com/111testing/p/6942585.html 目录:::::: 一、网络协议 二、TCP(Transmission Control Protocol,传输控制协议) TCP头格式…

【java】巨菜博主安装jdk为什么每次都失败?

今天到公司实习第一天,博主兴高采烈地的使用起来的公司配备的电脑,第一步是干啥?当然是安装JDK了,博主平生安装JDK次数数不胜数,但一遍整下来没有任何差错的情况少之又少。今天也不例外,多敲了个空格害我足…

怎么在vs2010中使用ActiveX Test Container(转)

ActiveX Test Container Application is Still Available(转) Hello, I’m Pat Brenner, a developer on the Visual C Libraries team. I’ve noticed some posts on various forums lamenting the loss of the ActiveX Test Container application and I wanted to address …

C#自定义控件四简易时钟

C#自定义控件四简易时钟效果图:简易时钟,顾名思义,简单容易,简单到什么程度呢?界面只有数字和指针,甚至连与当前时间都不能匹配!呵呵!就这么简单,学习嘛,从简…

GitLab 配置邮箱

设置 SMTP 发送邮件 这里以腾讯企业邮箱为例,其他邮箱可以参考 设置 SMTP 发送邮件。 SMTP 和 POP3/IMAP 协议 SMTP 负责发送邮件,POP3/IMAP 负责接收邮件。其中 IMAP 基本上替换掉了 POP3。 用户在使用客户端(例如 Foxmail)时&am…

在 Ubuntu Natty 中解除系统托盘限制

在 Ubuntu 11.04 Natty 中,Ubuntu 对顶部面板右上角的通知区域(系统托盘)采用了白名单制度,只有支持 Indicators 并位于白名单的部分程序才会被显示在系统托盘中,目前支持的程序有: Java apps, Mumble, Win…

Oracle10g客户端远程连接数据库全过程[转]

最近项目用到了oracle,使用的是oracle10g,因为小组内有多人使用数据库,并且oracle数据库很占内 存,就放在单独的一台服务器上,所以最好每个人都装一个oracle10g的客户端。那么客户端到数据库的远 程访问时免不了的了。…

【css】页面出现两个滚动条以及只有一半页面显示内容的解决方法

可能当修改页面的margin等属性时会出现页面只有一半的页面显示内容的情况,此时我们可以修改css代码来解决问题 代码实现: body{overflow:hidden}html{/*overflow-y:scroll;*/ }html{overflow: auto; } 注意:该代码为css代码,需…

Microsoft Dynamics Marketplace

微软对一些产品提供网上销售第三方插件/解决方案的站点叫做 Marketplace,比如 Windows Phone Marketplace, Dynamics Marketplace.这样可以帮助合作伙伴/客户提供一个网上的产品交流平台,Microsoft Dynamics Marketplace 针对微软CRM/ERP 产品&#xff0…

【hdu】4521 小明序列【LIS变种】【间隔至少为d】

题目链接:https://vjudge.net/contest/228455#problem/B 转载于:https://blog.csdn.net/a709743744/article/details/51765252 题目大意: 求最长上升子序列,其中子序列中相邻的两个数的下标差要超过k 解题分析: 子序列…

【bootstrap】bootstrap-4.5.0-example 各个模板展示

前言:博主做前端开发的时候经常用到bootstrap,但挑选模板的时候,需要一个一个的打开文件夹、打开html文件再查看模板是否合适,这样实在有点浪费时间,所以今天博主将各个页面截图展示出来,之后方便大家也方便…

HDU1053 Entropy 哈夫曼树

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1053 认真读题&#xff0c;别怕题长&#xff0c;此题考查的就是哈夫曼树并求出最小编码值&#xff0c;注意每一次要将数组清0&#xff0c;否则会出错&#xff01; AC代码&#xff1a; #include<iostream>…

C++用数组和链表分别实现Queue

C用数组和链表分别实现Queue 昨天写了《C用数组和链表分别实现Stack》&#xff0c;今天就是《C用数组和链表分别实现Queue》&#xff0c; 队列就是先来的先被处理掉&#xff0c;后来的就等&#xff0c;直到成为先来的&#xff0c;实现起来感觉和栈差不多。 模板好用的&#xff…

bzoj1150 [CTSC2007]数据备份Backup

大概就是写了道生日礼物那个不知道叫啥的贪心。。。。。 大概就是说这道题和那个比较像。。。 所以留着看看吧&#xff0c;哪天想起了回来做这道题咯~ 转载于:https://www.cnblogs.com/LLppdd/p/9051440.html

004本周总结报告

这一周总的来说并没有学到多少东西。只是学习了java数组相关的知识&#xff0c;发现和C/C中的数组基本一样&#xff0c;同时也了解到堆内存和栈内存的概念。在学习数组时发现java数组的length属性很好用&#xff0c;学习了数组的插入赋值&#xff0c;冒泡和选择排序等并用数组的…

JS保留两位小数

JS保留两位小数 对于一些小数点后有多位的浮点数&#xff0c;我们可能只需要保留2位&#xff0c;但js没有提供这样直接的函数&#xff0c;所以我们得自己写函数实现这个功能&#xff0c;代码如下&#xff1a; function changeTwoDecimal(x) { var f_x parseFloat(x); if…

【资源分享】The Beatles(披头士)乐队所有专辑带封面

资源免费分享&#xff0c;送给各位披头士的粉丝。只求个赞可以吗。 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 链接:https://pan.baidu.com/s/1N5BXA18JeaznYhRRy6kiAw 提取码:5439

Serial Communications in Win32

http://msdn.microsoft.com/en-us/library/ms810467.aspx http://hi.baidu.com/beisika/blog/item/b204d58f6c3bece9513d9297.html

platform_driver_register适配的两种方式及probe是否启动与硬件关系

platform_driver_register2种方式学习 1.platform_device_register与platform_driver_register配合使用&#xff1a; 实例代码摘自下述网址&#xff1a; 这样当两个name一样时&#xff0c;就会嗲用mt65xx_leds_probe这个函数了。 static struct platform_driver mt65xx_leds_d…

Java中创建泛型数组

Java中创建泛型数组 使用泛型时&#xff0c;我想很多人肯定尝试过如下的代码&#xff0c;去创建一个泛型数组 T[] array new T[]; 当我们写出这样的代码时编译器会报Cannot create a generic array of T&#xff0c;初学泛型时&#xff0c;看到这个错就以为Java中不能创建泛型…