﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-BeyondCN-随笔分类-Linux</title><link>http://www.cppblog.com/BeyondCN/category/8517.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 16 Oct 2008 02:38:42 GMT</lastBuildDate><pubDate>Thu, 16 Oct 2008 02:38:42 GMT</pubDate><ttl>60</ttl><item><title>epoll为什么这么快</title><link>http://www.cppblog.com/BeyondCN/archive/2008/10/16/64100.html</link><dc:creator>BeyondCN</dc:creator><author>BeyondCN</author><pubDate>Thu, 16 Oct 2008 01:40:00 GMT</pubDate><guid>http://www.cppblog.com/BeyondCN/archive/2008/10/16/64100.html</guid><wfw:comment>http://www.cppblog.com/BeyondCN/comments/64100.html</wfw:comment><comments>http://www.cppblog.com/BeyondCN/archive/2008/10/16/64100.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/BeyondCN/comments/commentRss/64100.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/BeyondCN/services/trackbacks/64100.html</trackback:ping><description><![CDATA[
<span style="color: rgb(204, 0, 102); font-family: verdana; font-size: 22px; font-weight: bold; text-decoration: underline;"><span style="color: rgb(0, 0, 102); font-size: 16px; font-weight: normal; "><div class="posttitle" style="padding-top: 5px; padding-right: 0px; padding-bottom: 5px; padding-left: 0px; "><a id="viewpost1_TitleUrl" class="singleposttitle" href="http://www.cppblog.com/converse/archive/2008/10/12/63836.html" style="text-decoration: underline; color: rgb(0, 107, 173); font-size: 22px; background-color: rgb(255, 255, 255); font-weight: bold; ">epoll为什么这么快</a></div>epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,在开始讨论这个问题之前,先来解释一下为什么需要多路复用IO.<br><br>以一个生活中的例子来解释.<br><br>假设你在大学中读书,要等待一个朋友来访,而这个朋友只知道你在A号楼,但是不知道你具体住在哪里,于是你们约好了在A号楼门口见面.<br><br>如果你使用的阻塞IO模型来处理这个问题,那么你就只能一直守候在A号楼门口等待朋友的到来,在这段时间里你不能做别的事情,不难知道,这种方式的效率是低下的.<br><br>现在时代变化了,开始使用多路复用IO模型来处理这个问题.你告诉你的朋友来了A号楼找楼管大妈,让她告诉你该怎么走.这里的楼管大妈扮演的就是多路复用IO的角色.<br><br>进一步解释select和epoll模型的差异.<br><br>select版大妈做的是如下的事情:比如同学甲的朋友来了,select版大妈比较笨,她带着朋友挨个房间进行查询谁是同学甲,你等的朋友来了,于是在实际的代码中,select版大妈做的是以下的事情:<br><div style="border-left-color: rgb(204, 204, 204); padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%; "><span style="color: rgb(0, 0, 0); "><br></span><span style="color: rgb(0, 0, 255); ">int</span><span style="color: rgb(0, 0, 0); ">&#160;n&#160;</span><span style="color: rgb(0, 0, 0); ">=</span><span style="color: rgb(0, 0, 0); ">&#160;select(</span><span style="color: rgb(0, 0, 0); ">&amp;</span><span style="color: rgb(0, 0, 0); ">readset,NULL,NULL,</span><span style="color: rgb(0, 0, 0); ">100</span><span style="color: rgb(0, 0, 0); ">);<br><br></span><span style="color: rgb(0, 0, 255); ">for</span><span style="color: rgb(0, 0, 0); ">&#160;(</span><span style="color: rgb(0, 0, 255); ">int</span><span style="color: rgb(0, 0, 0); ">&#160;i&#160;</span><span style="color: rgb(0, 0, 0); ">=</span><span style="color: rgb(0, 0, 0); ">&#160;</span><span style="color: rgb(0, 0, 0); ">0</span><span style="color: rgb(0, 0, 0); ">;&#160;n&#160;</span><span style="color: rgb(0, 0, 0); ">></span><span style="color: rgb(0, 0, 0); ">&#160;</span><span style="color: rgb(0, 0, 0); ">0</span><span style="color: rgb(0, 0, 0); ">;&#160;</span><span style="color: rgb(0, 0, 0); ">++</span><span style="color: rgb(0, 0, 0); ">i)<br>{<br>&#160;&#160;&#160;</span><span style="color: rgb(0, 0, 255); ">if</span><span style="color: rgb(0, 0, 0); ">&#160;(FD_ISSET(fdarray[i],&#160;</span><span style="color: rgb(0, 0, 0); ">&amp;</span><span style="color: rgb(0, 0, 0); ">readset))<br>&#160;&#160;&#160;{<br>&#160;&#160;&#160;&#160;&#160;&#160;do_something(fdarray[i]);<br>&#160;&#160;&#160;&#160;&#160; --n;<br>&#160;&#160;&#160;}<br>}<br></span></div><br>epoll版大妈就比较先进了,她记下了同学甲的信息,比如说他的房间号,那么等同学甲的朋友到来时,只需要告诉该朋友同学甲在哪个房间即可,不用自己亲自带着人满大楼的找人了.于是epoll版大妈做的事情可以用如下的代码表示:<br><div style="border-left-color: rgb(204, 204, 204); padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%; "><span style="color: rgb(0, 0, 0); ">n</span><span style="color: rgb(0, 0, 0); ">=</span><span style="color: rgb(0, 0, 0); ">epoll_wait(epfd,events,</span><span style="color: rgb(0, 0, 0); ">20</span><span style="color: rgb(0, 0, 0); ">,</span><span style="color: rgb(0, 0, 0); ">500</span><span style="color: rgb(0, 0, 0); ">);<br></span><span style="color: rgb(0, 128, 0); "></span><span style="color: rgb(0, 128, 0); ">&#160;&#160;&#160;&#160;</span><span style="color: rgb(0, 128, 0); "><br></span><span style="color: rgb(0, 0, 255); ">for</span><span style="color: rgb(0, 0, 0); ">(i</span><span style="color: rgb(0, 0, 0); ">=</span><span style="color: rgb(0, 0, 0); ">0</span><span style="color: rgb(0, 0, 0); ">;i</span><span style="color: rgb(0, 0, 0); ">&lt;</span><span style="color: rgb(0, 0, 0); ">n;</span><span style="color: rgb(0, 0, 0); ">++</span><span style="color: rgb(0, 0, 0); ">i)<br>{<br>&#160;&#160;&#160;&#160;do_something(events[n]);<br>}<br></span></div><br>在epoll中,关键的数据结构epoll_event定义如下:<br><div style="border-left-color: rgb(204, 204, 204); padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%; "><span style="color: rgb(0, 0, 0); ">typedef&#160;union&#160;epoll_data&#160;{<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</span><span style="color: rgb(0, 0, 255); ">void</span><span style="color: rgb(0, 0, 0); ">&#160;</span><span style="color: rgb(0, 0, 0); ">*</span><span style="color: rgb(0, 0, 0); ">ptr;<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</span><span style="color: rgb(0, 0, 255); ">int</span><span style="color: rgb(0, 0, 0); ">&#160;fd;<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;__uint32_t&#160;u32;<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;__uint64_t&#160;u64;<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;epoll_data_t;<br><br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</span><span style="color: rgb(0, 0, 255); ">struct</span><span style="color: rgb(0, 0, 0); ">&#160;epoll_event&#160;{<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;__uint32_t&#160;events;&#160;&#160;&#160;&#160;&#160;&#160;</span><span style="color: rgb(0, 128, 0); ">/*</span><span style="color: rgb(0, 128, 0); ">&#160;Epoll&#160;events&#160;</span><span style="color: rgb(0, 128, 0); ">*/</span><span style="color: rgb(0, 0, 0); "><br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;epoll_data_t&#160;data;&#160;&#160;&#160;&#160;&#160;&#160;</span><span style="color: rgb(0, 128, 0); ">/*</span><span style="color: rgb(0, 128, 0); ">&#160;User&#160;data&#160;variable&#160;</span><span style="color: rgb(0, 128, 0); ">*/</span><span style="color: rgb(0, 0, 0); "><br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;};&#160;</span></div>可以看到,epoll_data是一个union结构体,它就是epoll版大妈用于保存同学信息的结构体,它可以保存很多类型的信息:fd,指针,等等.有了这个结构体,epoll大妈可以不用吹灰之力就可以定位到同学甲.<br><br>别小看了这些效率的提高,在一个大规模并发的服务器中,轮询IO是最耗时间的操作之一.再回到那个例子中,如果每到来一个朋友楼管大妈都要全楼的查询同学,那么处理的效率必然就低下了,过不久楼底就有不少的人了.<br><br>对比最早给出的阻塞IO的处理模型, 可以看到采用了多路复用IO之后, 程序可以自由的进行自己除了IO操作之外的工作, 只有到IO状态发生变化的时候由多路复用IO进行通知, 然后再采取相应的操作, 而不用一直阻塞等待IO状态发生变化了.<br><br>从上面的分析也可以看出,epoll比select的提高实际上是一个用空间换时间思想的具体应用</span><br></span><img src ="http://www.cppblog.com/BeyondCN/aggbug/64100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/BeyondCN/" target="_blank">BeyondCN</a> 2008-10-16 09:40 <a href="http://www.cppblog.com/BeyondCN/archive/2008/10/16/64100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>