`
zhaohaolin
  • 浏览: 984251 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

在Linux上开发网络服务器的一些相关细节:poll与epoll(转)

阅读更多

随着2.6内核对epoll的完全支持,网络上很多的文章和示例代码都提供了这样一个信息:使用epoll代替传统的poll能给网络服务应用带来性能上 的提升。但大多文章里关于性能提升的原因解释的较少,这里我将试分析一下内核(2.6.21.1)代码中poll与epoll的工作原理,然后再通过一些 测试数据来对比具体效果。

   POLL:

   先说poll,poll或select为大部分Unix/Linux程序员所熟悉,这俩个东西原理类似,性能上也不存在明显差异,但select对所监控 的文件描述符数量有限制,所以这里选用poll做说明。

   poll是一个系统调用,其内核入口函数为sys_poll,sys_poll几乎不做任何处理直接调用do_sys_poll,do_sys_poll 的执行过程可以分为三个部分:

   1,将用户传入的pollfd数组拷贝到内核空间,因为拷贝操作和数组长度相关,时间上这是一个O(n)操作,这一步的代码在do_sys_poll中包 括从函数开始到调用do_poll前的部分。

   2,查询每个文件描述符对应设备的状态,如果该设备尚未就绪,则在该设备的等待队列中加入一项并继续查询下一设备的状态。查询完所有设备后如果没有一个设 备就绪,这时则需要挂起当前进程等待,直到设备就绪或者超时,挂起操作是通过调用schedule_timeout执行的。设备就绪后进程被通知继续运 行,这时再次遍历所有设备,以查找就绪设备。这一步因为两次遍历所有设备,时间复杂度也是O(n),这里面不包括等待时间。相关代码在do_poll函数 中。

   3,将获得的数据传送到用户空间并执行释放内存和剥离等待队列等善后工作,向用户空间拷贝数据与剥离等待队列等操作的的时间复杂度同样是O(n),具体代 码包括do_sys_poll函数中调用do_poll后到结束的部分。

   EPOLL:

   接下来分析epoll,与poll/select不同,epoll不再是一个单独的系统调用,而是由epoll_create/epoll_ctl /epoll_wait三个系统调用组成,后面将会看到这样做的好处。

   先来看sys_epoll_create(epoll_create对应的内核函数),这个函数主要是做一些准备工作,比如创建数据结构,初始化数据并最 终返回一个文件描述符(表示新创建的虚拟epoll文件),这个操作可以认为是一个固定时间的操作。

       epoll是做为一个虚拟文件系统来实现的,这样做至少有以下两个好处:

       1,可以在内核里维护一些信息,这些信息在多次epoll_wait间是保持的,比如所有受监控的文件描述符。

       2, epoll本身也可以被poll/epoll;

   具体epoll的虚拟文件系统的实现和性能分析无关,不再赘述。

   在sys_epoll_create中还能看到一个细节,就是epoll_create的参数size在现阶段是没有意义的,只要大于零就行。

   接着是sys_epoll_ctl(epoll_ctl对应的内核函数),需要明确的是每次调用sys_epoll_ctl只处理一个文件描述符,这里主 要描述当op为EPOLL_CTL_ADD时的执行过程,sys_epoll_ctl做一些安全性检查后进入ep_insert,ep_insert里将 ep_poll_callback做为回掉函数加入设备的等待队列(假定这时设备尚未就绪),由于每次poll_ctl只操作一个文件描述符,因此也可以 认为这是一个O(1)操作

       ep_poll_callback函数很关键,它在所等待的设备就绪后被系统回掉,执行两个操作:

   1,将就绪设备加入就绪队列,这一步避免了像poll那样在设备就绪后再次轮询所有设备找就绪者,降低了时间复杂度,由O(n)到O(1);

   2,唤醒虚拟的epoll文件;

   最后是sys_epoll_wait,这里实际执行操作的是ep_poll函数。该函数等待将进程自身插入虚拟epoll文件的等待队列,直到被唤醒(见 上面ep_poll_callback函数描述),最后执行ep_events_transfer将结果拷贝到用户空间。由于只拷贝就绪设备信息,所以这 里的拷贝是一个O(1)操作。

   还有一个让人关心的问题就是epoll对EPOLLET的处理,即边沿触发的处理,粗略看代码就是把一部分水平触发模式下内核做的工作交给用户来处理,直 觉上不会对性能有太大影响,感兴趣的朋友欢迎讨论。

   POLL/EPOLL对比:

   表面上poll的过程可以看作是由一次epoll_create/若干次epoll_ctl/一次epoll_wait/一次close等系统调用构成, 实际上epoll将poll分成若干部分实现的原因正是因为服务器软件中使用poll的特点(比如Web服务器):

   1,需要同时poll大量文件描述符;

   2,每次poll完成后就绪的文件描述符只占所有被poll的描述符的很少一部分。

   3,前后多次poll调用对文件描述符数组(ufds)的修改只是很小; 

   传统的poll函数相当于每次调用都重起炉灶,从用户空间完整读入ufds,完成后再次完全拷贝到用户空间,另外每次poll都需要对所有设备做至少做一 次加入和删除等待队列操作,这些都是低效的原因。

       epoll将以上情况都细化考虑,不需要每次都完整读入输出ufds,只需使用epoll_ctl调整其中一小部分,不需要每次 epoll_wait都执行一次加入删除等待队列操作,另外改进后的机制使的不必在某个设备就绪后搜索整个设备数组进行查找,这些都能提高效率。另外最明 显的一点,从用户的使用来说,使用epoll不必每次都轮询所有返回结果已找出其中的就绪部分,O(n)变O(1),对性能也提高不少。

   此外这里还发现一点,是不是将epoll_ctl改成一次可以处理多个fd(像semctl那样)会提高些许性能呢?特别是在假设系统调用比较耗时的基础 上。不过关于系统调用的耗时问题还会在以后分析。

   POLL/EPOLL测试数据对比:

   测试的环境:我写了三段代码来分别模拟服务器,活动的客户端,僵死的客户端,服务器运行于一个自编译的标准2.6.11内核系统上,硬件为 PIII933,两个客户端各自运行在另外的PC上,这两台PC比服务器的硬件性能要好,主要是保证能轻易让服务器满载,三台机器间使用一个100M交换 机连接。

   服务器接受并poll所有连接,如果有request到达则回复一个response,然后继续poll。

   活动的客户端(Active Client)模拟若干并发的活动连接,这些连接不间断的发送请求接受回复。

   僵死的客户端(zombie)模拟一些只连接但不发送请求的客户端,其目的只是占用服务器的poll描述符资源。

       测试过程:保持10个并发活动连接,不断的调整僵并发连接数,记录在不同比例下使用poll与epoll的性能差别。僵死并发连接数根据比例分别 是:0,10,20,40,80,160,320,640,1280,2560,5120,10240。

   下图中横轴表示僵死并发连接与活动并发连接之比,纵轴表示完成40000次请求回复所花费的时间,以秒为单位。红色线条表示poll数据,绿色表示 epoll数据。可以看出,poll在所监控的文件描述符数量增加时,其耗时呈线性增长,而epoll则维持了一个平稳的状态,几乎不受描述符个数影响。

   在监控的所有客户端都是活动时,poll的效率会略高于epoll(主要在原点附近,即僵死并发连接为0时,图上不易看出来),究竟epoll实现比 poll复杂,监控少量描述符并非它的长处。
分享到:
评论

相关推荐

    linux网络编程

    17socket编程(十二) select限制 poll 18socket编程(十三) epoll使用 epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程...

    linux C语言 网络编程教程及源码

    20、Linux网络编程——tcp高效并发服务器(poll实现) 21、Linux网络编程——tcp高效并发服务器(epoll实现) 二、网络底层编程(黑客模式) 1、Linux网络编程1——啥叫原始套接字 2、Linux网络编程2——原始套接字...

    linux网络编程之 epoll简介

    编写连接数巨大的高负载服务器程序时,经典的多线程模式和 select模式都不再适 用。应当抛弃它们,采用 epoll/kqueue/dev_poll 来捕获 I/O 事件。最后简要介绍了 AIO。 --------- from 搜狗实验室

    linux epoll模型

    不过传统的select/poll函数有着一些无法忍受的缺点,所以改进一直是2.4-2.5开发版本内核的任务,包括/dev/poll,realtime signal等等。 最终,Davide Libenzi开发的epoll进入2.6内核成为正式的解决方案。

    论文研究-LINUX平台下基于EPOLL的FTP服务器设计与实现 .pdf

    LINUX平台下基于EPOLL的FTP服务器设计与实现,王亚昌,,网络服务器通常采用多进程、多线程并发机制或者是基于select/poll的I/O复用模型实现,传统的FTP服务器大都使用前者。本文针对Linux 2.6内�

    利用epoll编写echo客户端/服务器

    epoll是Linux内核为处理大批量文件描述符而作了改进的epoll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。

    EPOLL模型详解

    在一些 benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境,epoll并不比select/poll有什么效率,相 反,如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN...

    EPOLL模型:关于并发连接的处理

    Linux 2.6内核中提高网络I/O性能的新方法-epoll I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数。 1、为什么select落后  首先,在Linux内核中,select所用到的FD_SET是有限的,即内核...

    linux epoll机制详解

    在linux 没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用的方法来实现并发服务程序。在linux新的内核中,有了一种替换它的机制,就是epoll。 select()和poll() IO多路复用模型 select的...

    Linux网络编程 视频 教程

    Linux网络编程(总共41集) 讲解Linux网络编程知识,分以下四个篇章。 Linux网络编程之TCP/IP基础篇 Linux网络编程之socket编程篇 Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP...

    linux 下 select 编程 librtspserver

    linux 下 select 编程 我们知道 select 是IO 多路复用的一个最简单支持,poll 和 epoll 是 select 的升级版。在 UNIX 网络编程第五章读书笔记 我们遇到这样一个问题:当客户端阻塞在 fgets() 等待客户输入的时候,...

    Linux网络编程socket编程学习

    自学Linux网络编程关于socket...重点介绍多路I/O转接服务器的实现,包括select函数poll函数epoll函数;最后介绍了UDP协议的服务器编写和本地套接字的程序实现。资源里面有笔记,C语言代码,参考书及参考书包含的程序。

    socket网络编程-epoll-水平触发和边缘触发源码

    (1)I/O多路复用技术用于监控多个TCP连接上的数据收发,而epoll就是一种在Linux上使用的I/O多路复用并支持高并发的典型技术。传统的select、poll也是I/O多路复用技术,但这2种技术受内部实现的限制,不支持高并发,...

    C++教程网《Linux网络编程》视频百度云地址

    Linux网络编程(总共41集) 讲解Linux网络编程知识,分以下四个篇章。 Linux网络编程之TCP/IP基础篇 Linux网络编程之socket编程篇 Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP...

    Linux高性能服务器编程

    内容简介《Linux高性能服务器编程》是Linux服务器编程领域的经典著作,由资深Linux软件开发工程师撰写,从网络协议、服务器编程核心要素、原理机制、工具框架等多角度全面阐释了编写高性能Linux服务器应用的方法、...

    LINUX 网络通信引擎中间件

    血与荣誉网络通信引擎2013PT1-2.4.2.1001 Build1231 集成了LINUX下的 TCP UDP ...还包含了LINUX 系统API 资源API 基础库 算法库 客户端开发包等等,与网络相关的功能集成。 与之对应的是WINDOWS网络通信引擎!同时发布

    C++教程网视频:linux网络编程

    Linux网络编程(总共41集) 讲解Linux网络编程知识,分以下四个篇章。 Linux网络编程之TCP/IP基础篇 Linux网络编程之socket编程篇 Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP...

    libevent for qt网络模块,直接替换qt的select模型,支持epoll,select,pool.使用非常简单,无需修改以前的代码结构

    最近在开发im服务器 需要大并发链接 QT默认的是使用select模型的 这种轮询方式非常慢 在高并发连接 我们需要epoll才能发挥linux服务器的性能 而且使用简单 整个服务端代码架构无需修改 直接可以使用 只要在 main...

    [免费]2018年C++教程网的linux网络编程视频百度云下载链接.rar

    epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 ...

    c++教程网的linux网络编程视频下载

    epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 ...

Global site tag (gtag.js) - Google Analytics