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

epoll 的实现原理以及与poll,select 的对比

最近面试的时候 被问到epoll的问题,就下来查一查,看到有篇文章不错,就记录下来,供大家参考学习。

以一个生活中的例子来解释.
假设你在大学中读书,要等待一个朋友来访,而这个朋友只知道你在A号楼,但是不知道你具体住在哪里,于是你们约好了在A号楼门口见面.
如果你使用的阻塞IO模型来处理这个问题,那么你就只能一直守候在A号楼门口等待朋友的到来,在这段时间里你不能做别的事情,不难知道,这种方式的效率是低下的.
进一步解释select和epoll模型的差异.
select版大妈做的是如下的事情:比如同学甲的朋友来了,select版大妈比较笨,她带着朋友挨个房间进行查询谁是同学甲,你等的朋友来了。
于是在实际的代码中,select版大妈做的是以下的事情:
int n = select(&readset,NULL,NULL,100);for (int i = 0; n > 0; ++i){if (FD_ISSET(fdarray[i], &readset)){ do_something(fdarray[i]);--n; } 
}

epoll版大妈就比较先进了,她记下了同学甲的信息,比如说他的房间号,那么等同学甲的朋友到来时,只需要告诉该朋友同学甲在哪个房间即可,不用自己亲自带着人满大楼的找人了.
于是epoll版大妈做的事情可以用如下的代码表示:
n = epoll_wait(epfd,events,20,500);for(i=0;i<n;++i) 
{ do_something(events[n]); 
}


在epoll中,关键的数据结构epoll_event定义如下:
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_data是一个union结构体,它就是epoll版大妈用于保存同学信息的结构体,它可以保存很多类型的信息:fd,指针,等等.有了这个结构体,epoll大妈可以不用吹灰之力就可以定位到同学甲. 别小看了这些效率的提高,在一个大规模并发的服务器中,轮询IO是最耗时间的操作之一.再回到那个例子中,如果每到来一个朋友楼管大妈都要全楼的查询同学,那么处理的效率必然就低下了,过不久楼底就有不少的人了. 对比最早给出的阻塞IO的处理模型, 可以看到采用了多路复用IO之后, 程序可以自由的进行自己除了IO操作之外的工作, 只有到IO状态发生变化的时候由多路复用IO进行通知, 然后再采取相应的操作, 而不用一直阻塞等待IO状态发生变化了. 从上面的分析也可以看出,epoll比select的提高实际上是一个用空间换时间思想的具体应用.
二、深入理解epoll的实现原理:开发高性能网络程序时,windows开发者们言必称iocp,linux开发者们则言必称epoll。大家都明白epoll是一种IO多路复用技术,可以非常高效的处理数以百万计的socket句柄,比起以前的select和poll效率高大发了。我们用起epoll来都感觉挺爽,确实快,那么,它到底为什么可以高速处理这么多并发连接呢? 先简单回顾下如何使用C库封装的3个epoll系统调用吧。int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout); 使用起来很清晰,首先要调用epoll_create建立一个epoll对象。参数size是内核保证能够正确处理的最大句柄数,多于这个最大数时内核可不保证效果。 epoll_ctl可以操作上面建立的epoll,例如,将刚建立的socket加入到epoll中让其监控,或者把 epoll正在监控的某个socket句柄移出epoll,不再监控它等等。 epoll_wait在调用时,在给定的timeout时间内,当在监控的所有句柄中有事件发生时,就返回用户态的进程。 从上面的调用方式就可以看到epoll比select/poll的优越之处:因为后者每次调用时都要传递你所要监控的所有socket给select/poll系统调用,这意味着需要将用户态的socket列表copy到内核态,如果以万计的句柄会导致每次都要copy几十几百KB的内存到内核态,非常低效。而我们调用epoll_wait时就相当于以往调用select/poll,但是这时却不用传递socket句柄给内核,因为内核已经在epoll_ctl中拿到了要监控的句柄列表。 所以,实际上在你调用epoll_create后,内核就已经在内核态开始准备帮你存储要监控的句柄了,每次调用epoll_ctl只是在往内核的数据结构里塞入新的socket句柄。 在内核里,一切皆文件。所以,epoll向内核注册了一个文件系统,用于存储上述的被监控socket。当你调用epoll_create时,就会在这个虚拟的epoll文件系统里创建一个file结点。当然这个file不是普通文件,它只服务于epoll。epoll在被内核初始化时(操作系统启动),同时会开辟出epoll自己的内核高速cache区,用于安置每一个我们想监控的socket,这些socket会以红黑树的形式保存在内核cache里,以支持快速的查找、插入、删除。这个内核高速cache区,就是建立连续的物理内存页,然后在之上建立slab层,简单的说,就是物理上分配好你想要的size的内存对象,每次使用时都是使用空闲的已分配好的对象。static int __init eventpoll_init(void) { ... ... /* Allocates slab cache used to allocate "struct epitem" items */ epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem), 0, SLAB_HWCACHE_ALIGN|EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL); /* Allocates slab cache used to allocate "struct eppoll_entry" */ pwq_cache = kmem_cache_create("eventpoll_pwq", sizeof(struct eppoll_entry), 0, EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL); ... ... epoll的高效就在于,当我们调用epoll_ctl往里塞入百万个句柄时,epoll_wait仍然可以飞快的返回,并有效的将发生事件的句柄给我们用户。这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。 那么,这个准备就绪list链表是怎么维护的呢?当我们执行epoll_ctl时,除了把socket放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。所以,当一个socket上有数据到了,内核在把网卡上的数据copy到内核中后就来把socket插入到准备就绪链表里了。 如此,一颗红黑树,一张准备就绪句柄链表,少量的内核cache,就帮我们解决了大并发下的socket处理问题。执行epoll_create时,创建了红黑树和就绪链表,执行epoll_ctl时,如果增加socket句柄,则检查在红黑树中是否存在,存在立即返回,不存在则添加到树干上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据。执行epoll_wait时立刻返回准备就绪链表里的数据即可。 最后看看epoll独有的两种模式LT和ET。无论是LT和ET模式,都适用于以上所说的流程。区别是,LT模式下,只要一个句柄上的事件一次没有处理完,会在以后调用epoll_wait时次次返回这个句柄,而ET模式仅在第一次返回。 这件事怎么做到的呢?当一个socket句柄上有事件时,内核会把该句柄插入上面所说的准备就绪list链表,这时我们调用epoll_wait,会把准备就绪的socket拷贝到用户态内存,然后清空准备就绪list链表,最后,epoll_wait干了件事,就是检查这些socket,如果不是ET模式(就是LT模式的句柄了),并且这些socket上确实有未处理的事件时,又把该句柄放回到刚刚清空的准备就绪链表了。所以,非ET的句柄,只要它上面还有事件,epoll_wait每次都会返回。而ET模式的句柄,除非有新中断到,即使socket上的事件没有处理完,也是不会次次从epoll_wait返回的。
三、扩展阅读(epoll与之前其他相关技术的比较): Linux提供了select、poll、epoll接口来实现IO复用,三者的原型如下所示,本文从参数、实现、性能等方面对三者进行对比。 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); int poll(struct pollfd *fds, nfds_t nfds, int timeout); int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); select、poll、epoll_wait参数及实现对比 1. select的第一个参数nfds为fdset集合中最大描述符值加1,fdset是一个位数组,其大小限制为__FD_SETSIZE(1024),位数组的每一位代表其对应的描述符是否需要被检查。 select的第二三四个参数表示需要关注读、写、错误事件的文件描述符位数组,这些参数既是输入参数也是输出参数,可能会被内核修改用于标示哪些描述符上发生了关注的事件。所以每次调用select前都需要重新初始化fdset。 timeout参数为超时时间,该结构会被内核修改,其值为超时剩余的时间。 select对应于内核中的sys_select调用,sys_select首先将第二三四个参数指向的fd_set拷贝到内核,然后对每个被SET的描述符调用进行poll,并记录在临时结果中(fdset),如果有事件发生,select会将临时结果写到用户空间并返回;当轮询一遍后没有任何事件发生时,如果指定了超时时间,则select会睡眠到超时,睡眠结束后再进行一次轮询,并将临时结果写到用户空间,然后返回。 select返回后,需要逐一检查关注的描述符是否被SET(事件是否发生)。 2. poll与select不同,通过一个pollfd数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd中的events字段和revents分别用于标示关注的事件和发生的事件,故pollfd数组只需要被初始化一次。 poll的实现机制与select类似,其对应内核中的sys_poll,只不过poll向内核传递pollfd数组,然后对pollfd中的每个描述符进行poll,相比处理fdset来说,poll效率更高。 poll返回后,需要对pollfd中的每个元素检查其revents值,来得指事件是否发生。 3. epoll通过epoll_create创建一个用于epoll轮询的描述符,通过epoll_ctl添加/修改/删除事件,通过epoll_wait检查事件,epoll_wait的第二个参数用于存放结果。 epoll与select、poll不同,首先,其不用每次调用都向内核拷贝事件描述信息,在第一次调用后,事件信息就会与对应的epoll描述符关联起来。另外epoll不是通过轮询,而是通过在等待的描述符上注册回调函数,当事件发生时,回调函数负责把发生的事件存储在就绪事件链表中,最后写到用户空间。

转载于:https://www.cnblogs.com/lhzhou/p/4148782.html

相关文章:

js 字符串转换成数字的 三种方法

在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b.value,因为他们都是字符串形式的.在网上找了一下js字符串转数字的文章,这个比较全方法主要有三种 转换函数、强制类型转换、利用js…

Web 开发与设计之 Google 兵器谱

Google 的使命是 Web&#xff0c;在 Google 眼中&#xff0c;未来的一切应用都将 Web 化&#xff0c;一直以来&#xff0c;Google 为 Web 开发与设计者推出了大量免费工具&#xff0c;让他们更好地创建&#xff0c;维护&#xff0c;改善他们的 Web 站点&#xff0c;这些工具包含…

html5新标签使用

HTML 5 视频标签<video> <video width"320" height"240" controls"controls"><source src"/i/movie.ogg" type"video/ogg"><source src"/i/movie.mp4" type"video/mp4">Your b…

调查:“AI红娘”来了,有一半人选择相信TA

作者&#xff1a;REN来源&#xff1a;数据实战派七夕AI红娘来了前言你会相信人工智能&#xff08;AI&#xff09;给你推荐的约会对象吗&#xff1f;最近&#xff0c;卡巴斯基的一项全球调查显示&#xff0c;在使用交友或约会软件时&#xff0c; 44% 的受访者愿意接受 AI 或算法…

Mysql技术内幕——InnoDB存储引擎

一&#xff0e;mysql体系结构和存储引擎 1.1、数据库和实例的区别 数据库&#xff1a;物理操作系统或其他形式文件类型的集合。在mysql下数据库文件可以是frm&#xff0c;myd&#xff0c;myi&#xff0c;ibd结尾的文件。 数据库实例&#xff1a;由数据库后台进程/线程以及一个共…

jQuery插件开发 - 其实很简单

【前言】jQuery已经被广泛使用&#xff0c;凭借其简洁的API&#xff0c;对DOM强大的操控性&#xff0c;易扩展性越来越受到web开发人员的喜爱&#xff0c;我在社区也发布了很多的jQuery插件&#xff0c;经常有人询问一些技巧&#xff0c;因此干脆写这么一篇文章给各位jQuery爱好…

直接选择排序算法

直接选择排序算法 1、选择排序 #include <stdio.h> #include <stdlib.h> #define N 5 //排序的数据个数 typedef struct Num {int data[N-1];int length; }Num;int main(int argc, char *argv[]) {int i,j,min;struct Num La;printf("请输入您要排序的数字序…

大厂的面试官是如何挑人的?

马上就又要到金九银十求职的黄金期了&#xff0c;最近找了很多资深面试官聊天&#xff0c;他们说其实他们每天都要面试考核很多应聘者&#xff0c;但是通过的人却寥寥无几。。为了帮助大家更好的了解大厂面试的知识方向&#xff0c;特别拿出了某大厂大佬整理的非常全面的大厂 A…

使用Mono管理Coyote Linux

Coyote是一个个人防火墙配置Linux的目的是为了保护家庭或教育网络. 这个防火墙产品牌的个人及教育用途,并提供免费下载&#xff1a;http://coyotelinux.com/ CoyoteLinux uses Mono for syadmin tools http://www.coyotelinux.com.cn/index.htm 本文转自 张善友 51CTO博客&…

介绍几款浏览器兼容性测试工具

昨天和朋友聊到了有关浏览器兼容性的问题&#xff0c;在开发中有时的确很让人苦恼&#xff0c;我向他推荐了几款测试浏览器兼容的工具&#xff0c;分享给大伙&#xff0c;有什么更好的工具或是解决方法还希望大家拿出来晒一晒。 IETester 这是我最先用的测试浏览器兼容性的工…

关于android.view.WindowLeaked(窗体泄露)的解决方案

虽然是小问题一个&#xff0c;但也困扰了我一段时间&#xff0c;现在记下来&#xff0c;给自己做个备忘&#xff0c;也可以给其他人一个参考 Java代码 view plaincopy to clipboardprint? 01-08 01:49:27.874: ERROR/WindowManager(473): Activity com.photos.MainActivity …

英伟达推出全球首个元宇宙平台,豪砸数亿是为什么?

编译 | 禾木木 出品 | AI科技大本营(ID:rgznai100) NVIDIA 在 SIGGRAPH 推出首个全球元宇宙平台&#xff0c;并赢得了最佳展示奖。目前处于公测阶段&#xff0c;它对 NVIDIA RTX 和 GeForce RTX GPU 用户免费开放。用户在安装完 NVIDIA Studio 驱动程序后&#xff0c;即可获得…

route命令相关整理

目录&#xff1a; 1. 使用背景 2. route命令 2.1 打印路由信息 2.2 删除路由信息 2.3 添加路由信息 3. 应用实例 3.1 详解案例 3.2 内外网同时上网办法集锦 4、“路由添加失败&#xff0c;找不到元素” 1. 使用背景 需要接入两个网络&#xff0c;一个是部署环境所在内网…

ASP.NET画图控件 Chart Control 免费控件

.NET3.5中中推出了图表控件&#xff0c;可以同时支持Web和WinForm两种方式&#xff0c;由于平时很少使用&#xff0c;一直没有玩玩&#xff0c;闲来无事&#xff0c;简单研究了下&#xff0c;感觉功能真的很强大&#xff0c;基本上可以满足各种图表的应用&#xff0c;感觉这么好…

一步步学敏捷开发:开篇

一步步学敏捷开发&#xff1a;开篇 http://www.cnblogs.com/jetlian/p/3913687.html

算法也是颜值控,Twitter AI更青睐肤白貌美图

【CSDN 编者按】这是不是一个看脸的世界&#xff0c;谁都说不准&#xff0c;但是近期有研究人员发现&#xff0c;Twitter有这样一种AI算法&#xff1a;更青睐于身材好、皮肤白的年轻人的图片&#xff0c;哪怕这些图片经美图软件加工过。具体的情况究竟如何&#xff1f;下面这篇…

esxi4.1使用IDE格式磁盘

1、今天用workstation的“import and export”工具将DataOnTap系统迁移到esxi4.1下面了&#xff08;具体转换方法可以参考http://taotao1240.blog.51cto.com/731446/656853&#xff09;好开心啊&#xff0c;但是启动虚拟机的时候悲剧了&#xff0c;提示“在此版本中&#xff0c…

jQuery 表格插件汇总

本文搜集了大量 jQuery 表格插件&#xff0c;帮助 Web 设计者更好地驾御 HTML 表格&#xff0c;你可以对表格进行横向和竖向排序&#xff0c;设置固定表头&#xff0c;对表格进行搜索&#xff0c;对大表格进行分页&#xff0c;对表格进行滚动&#xff0c;拖放操作等等。这些插件…

程序员门槛再被“神器”降低:只要会英文,就能写代码!

近日&#xff0c;OpenAI带着他们最新、最神自动编码神器Codex霸榜各大科技媒体头条&#xff0c;我们知道OpenAI是微软投资的通用人工智能平台&#xff0c;而GitHub是微软旗下的代码托管平台&#xff0c;这样微软出算力、OpenAI出技术、GitHub出代码的AI编程铁三角就产生了&…

微软职位内部推荐-Software Engineer II-News

微软近期Open的职位:News is a critical areas for integration of mobile and services, one of the top priorities in Microsoft. Microsoft is innovating rapidly to grow its share of this market by providing the news industry with a world-class News platform and…

css3中的box-sizing属性

盒子宽度、高度计算公式&#xff1a;css元素宽度 width padding bordercss元素高度 height padding border css3之前&#xff0c;当我们需要呈现一个宽度为200px的盒子时&#xff0c;我们需要减去它本身的内边距、边框&#xff0c;然后得知属性的width应该设置为多少。例…

影响Lucene索引速度原因以及提高索引速度技巧

在网上看了一篇外文文章&#xff0c;里面介绍了提高Lucene索引速度的技巧&#xff0c;分享给大家。先来看下影响索引的主要因素&#xff1a; MaxMergeDocs该参数决定写入内存索引文档个数&#xff0c;到达该数目后就把该内存索引写入硬盘&#xff0c;生成一个新的索引segment文…

java 反射 动态代理

在上一篇文章中介绍Java注解的时候&#xff0c;多次提到了Java的反射API。与javax.lang.model不同的是&#xff0c;通过反射API可以获取程序在运行时刻的内部结构。反射API中提供的动态代理也是非常强大的功能&#xff0c;可以原生实现AOP中 的方法拦截功能。正如英文单词refle…

公路病害检测有了“智慧眼”,思谋AI“助力”广东省高速公路

近日&#xff0c;思谋科技与广东省某高速企业达成合作&#xff0c;智慧交通一体化平台病害检测模块已成熟落地&#xff0c;将使广东省高速公路病害检测进入高频率、高效率、智能化时代&#xff0c;以行业领先的AI技术助力智慧交通产业的发展。 近年来&#xff0c;我国公路建设…

无准备,不编程——计算机达人成长之路(15)连载

8、俄罗斯方块&#xff08;三&#xff09;编码 嬉闹归嬉闹&#xff0c;最终二人静下心来&#xff0c;绍绍开始请教俄罗斯方块的设计&#xff0c;木鸿飞也不藏拙&#xff0c;马上开始讲解&#xff1b;“游戏其实分为三重循环&#xff0c;也就是可以分为三个部分。” “哪三个&am…

Memcached 缓存系统的-介绍、安装以及应用

一. memcached 是什么?memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.memcached是一个高性能的、分布式内存对象缓存系统&am…

被算法“监控”的打工人,这家公司 150 人被算法裁定为“不敬业”

整理 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 近日&#xff0c;一家公司通过 AI 算法裁掉三成员工的消息在网上引起热议。当你上班时突然收到一封邮件显示“效率低下”而要求马上离开公司&#xff0c;你会怎么想呢&#xff1f; 据 Game World Obser…

(转)I 帧和 IDR 帧的区别

I 帧和 IDR 帧的区别&#xff1a;http://blog.csdn.net/skygray/article/details/6223358 IDR 帧属于 I 帧。解码器收到 IDR frame 时&#xff0c;将所有的参考帧队列丢弃 &#xff08;用x264_reference_reset 函数实现——在 encoder.c 文件中&#xff09; 。这点是所有 I 帧…

ExtJs 备忘录(3)—— Form表单(三) [ 数据验证 ]

正文一、资料 1.1. 表单提示的方式设置&#xff0c;如&#xff1a; Ext.form.Field.prototype.msgTargetside 该设置为枚举值&#xff1a;qtip,side,title,under qtip&#xff1a;把鼠标移动到控件就可以显示提示信息了&#xff0c;有点像设置了title的input标签一样的效果…

Dynamo 以及一致性哈希简介

本介绍参考 Amazon 的 Dynamo 论文。需要更详细更准确信息的同学请直接阅读原文。 (原文地址http://s3.amazonaws.com/AllThingsDistributed/sosp/amazon-dynamo-sosp2007.pdf) 这篇论文本身没提出什么新的思想&#xff0c;正如论文中所说&#xff0c;贡献在于把非常多的技术结…