﻿<?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++博客-Bugs</title><link>http://www.cppblog.com/Bugs/</link><description>MMORPG game develop.</description><language>zh-cn</language><lastBuildDate>Wed, 08 Apr 2026 22:47:58 GMT</lastBuildDate><pubDate>Wed, 08 Apr 2026 22:47:58 GMT</pubDate><ttl>60</ttl><item><title>我自己的blog！</title><link>http://www.cppblog.com/Bugs/archive/2008/11/11/66614.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Tue, 11 Nov 2008 08:15:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/11/11/66614.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/66614.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/11/11/66614.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/66614.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/66614.html</trackback:ping><description><![CDATA[欢迎大家光临我自己的Blog：http://iBugs.net&#160;<img src ="http://www.cppblog.com/Bugs/aggbug/66614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-11-11 16:15 <a href="http://www.cppblog.com/Bugs/archive/2008/11/11/66614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SCTP vs. TCP</title><link>http://www.cppblog.com/Bugs/archive/2008/06/26/54651.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Thu, 26 Jun 2008 03:28:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/06/26/54651.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/54651.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/06/26/54651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/54651.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/54651.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>1 流控制传输协议（SCTP）发展简介</p>
<p><br>　　随着IP网向多业务网发展，尤其是目前IP电话、IP视频会议等业务的发展，在IP网中传送信令信息成为必然。目前IP网中信令消息的交换通常是使用TCP或UDP完成，但是这两个协议都不能满足电信运营网中信令承载的要求。</p>
<p><br>　　为适应IP网成为电信运营核心网的发展趋势，IETF 的信令传输工作组（SIGTRAN）一直在研究和制定IP网新一代的传输协议，并在IETF RFC 2960中定义了流控制传输协议（SCTP，Stream Control Transmission Protocol）。SCTP是面向连接的可靠传送协议，它向上层应用提供了下列服务：</p>
<p><br>　　&#183; 应用数据的无错误无重复的可靠传输；</p>
<p><br>　　&#183; 根据检测到的MTU长度进行数据包分段处理，避免IP层的分段；</p>
<p><br>　　&#183; 在多个流间的用户消息有序递交，及单用户消息按到达顺序递交的选项；</p>
<p><br>　　&#183; 通过支持关联的多宿主机特性，实现网络级容错。</p>
<p><br>　　SCTP是为传输信令业务流而制定的，它本身所具有的、优于TCP的一些先进协议机制，如选择性重传、无序递交和支持多种网络特性等，使得SCTP能够在一定程度上满足高性能传输的需求。而且，SCTP采用了类同TCP的流量控制机制，不存在类似基于UDP的实时媒体流对TCP性能造成的劣化干扰问题和公平性问题。因此，SCTP将有可能取代TCP，成为下一代IP网上面向连接的可靠传送层协议。</p>
<p><br>2 TCP的不足</p>
<p><br>　　TCP是目前Internet上应用最广泛的面向连接的传送层协议，它为通信的两端提供了可靠的数据传输，而且提供了流量控制和拥塞控制功能。由于原来IP网提供的是&#8220;尽力而为（best-effort）&#8221;的服务，因此TCP存在许多不足之处：</p>
<p><br>　　&#183; TCP是面向字节流的。这意味着消息的描述必须由应用来完成，而且要在消息结束时显示通知TCP以迫使其立即发送相应的数据。</p>
<p><br>　　&#183; 许多应用只需要信令信息的部分有序，例如属于同一呼叫或同一会话的消息就是这样。而TCP只提供严格的数据按序传输，这会导致不必要的队头拥塞并使消息的传输时延增大。</p>
<p><br>　　&#183; TCP连接直接由一对传送层地址（IP地址和端口号）识别，无法提供对多宿主机的透明支持。</p>
<p><br>　　&#183; 典型的TCP实现不允许高层应用设定协议控制参数。但是一些应用可能会需要调节传送层协议的属性以满足其要求，例如某些应用有较高的时延要求，而另一些则只要求较高的可靠性。</p>
<p><br>3 连接与关联</p>
<p><br>　　TCP中的连接是指两个TCP端点通过&#8220;三次握手&#8221;过程建立的由一对传送层地址（IP地址和端口号）识别的传送通道。</p>
<p><br>　　在SCTP中, TCP中的连接被引申为关联(associ-<br>ation）。一个关联的两个SCTP端点都向对方提供一个SCTP端口号和一个IP地址列表，这样每个关联都由两个SCTP端口号和两个IP地址列表来识别。在一个关联内的拥塞控制机制与TCP连接的拥塞控制机制类似。</p>
<p><br>　　一个关联是由多个单向的流组成的。各个流之间相对独立，可以单独发送数据而不受其他流的影响，也可以共同实现用户数据的有序递交。流的建立和拆除过程相对独立、简单。而关联的建立过程相对而言就比较复杂，是个&#8220;四次握手&#8221;过程，而且其中要用到&#8220;cookie&#8221;的概念。所谓&#8220;cookie&#8221;实际就是一个含有端点初始信息和加密信息的数据块，它在关联建立时被通信的两端处理并交换。</p>
<p><br>4 SCTP的多宿主机特性及应用</p>
<p><br>　　SCTP支持传送层的多宿主机服务。当网络发生故障时，多宿主机服务可以增强网络的健壮性（robustness）。在某些应用场合，这个特性非常重要。SCTP对多宿主机服务的支持要求关联的一端或两端在不同的网络接口上分配有多个IP地址。</p>
<p><br>　　一般来说，要在通信的两端实现真正的故障弹性恢复，每个端点都需要有一个以上的IP网络接口，以支持多宿主机服务。在这种情况下，路径使用的数量就是所有端点的网络接口的最小数，此时端点要正确选择自己的源地址才能获得最佳路径。但是，如果端点总是使用同一个源地址，那么端点就同样会出现单点故障。因为当端点选择一个源地址时，它总是选择数据包的源地址来对应网络接口的IP地址，而在网络接口上数据包将受到绑定地址的限制。换句话说，由于绑定地址的限制，端点永远都不能选择不属于该SCTP关联的源地址，同时对端端点也必须认可该SCTP关联使用的任何一个源地址。</p>
<p><br>　　当端点在一个多宿主机上时，如果关联的两端绑定有多个地址，SCTP关联的可用性将大大增强。利用多宿主机这个特性可以在两个SCTP端点间建立冗余的路径，这对那些一直寻求在网络的传送层次就能提供容错机制的应用特别有用。要在SCTP的两个端点间建立冗余路径，要求两个端点的设备都必须有多个接口，并分配多个地址，而且必须配置好路由。</p>
<p><br>　　因此，通过&#8220;多宿主机&#8221;特性，SCTP提供了较TCP强大得多的路径状态监控功能。SCTP可以监测远端地址的可达性，当远端地址不可达时，它能通过使用备用地址替换主用地址实现故障的自动恢复，而且这一过程不需要上层协议的干预。也就是说，&#8220;多宿主机&#8221;特性可以使一个关联可以在多个传输路径间选择和切换，从而提高了网络级容错的能力。</p>
<p><br>5 TCP与SCTP的安全比较</p>
<p><br>　　1. TCP的安全问题</p>
<p><br>　　一些TCP应用被公认会受到DoS攻击。例如，攻击者可以通过发送大量的连接建立请求（TCP-SYN数据包）来攻击目的地，有可能来自伪装的IP地址。被攻击主机将不停地发送SYN-ACK数据包来回复，并进入SYN-received状态，甚至SYN队列将被挤满（例如，等待建立的连接数会达到一个极限），而且它将拒绝新的连接建立请求。</p>
<p><br>　　另外，伪装连接是对TCP的另一个潜在威胁。通过猜测有效的序列号，攻击者将可能伪装成一个合法连接。但是，通过使用一个安全的Hashsum算法，对目前SYN-cookie进行伪装的攻击的可能性只有1/224。例如当使用SYS-cookie时，要成功作为一个伪装的连接时，攻击者将不得不发送224个数据包。</p>
<p><br>　　2. SCTP的安全机制</p>
<p><br>　　SCTP在设计时就充分考虑了TCP的不足。为防止攻击者发送伪装的SCTP数据包到现有的连接中，SCTP的两端都使用一个称为&#8220;认证标记&#8221;的32bit数据来确保数据包真正属于现有的连接。因此，除了合并属于一个连接的源端口和目的端口的地址外，一个有效的SCTP数据包还必须有一个正确的标记。</p>
<p><br>　　跟TCP不同的是，SCTP要求在连接建立时必须使用&#8220;cookie&#8221;。对服务器来说，必须交换3个信息包（INIT、INIT-ACK、COOKIE-ECHO），才能建立一个完整的新连接。&#8220;cookie&#8221;是个长度可变的，包含所有和在服务器端初始化TCB的相关数据，加上使用HMAC来确保它的安全。HMAC是在cookie中用来计算的，是一个保密、服务器所拥有的key。引入这种机制的目的在于增强协议的安全性，防止DoS攻击和伪装等潜在的攻击。</p>
<p><br>　　同使用SYN-cookie的TCP相比较，SCTP被攻击者伪装的可能性大大降低。因为，攻击者不得不去猜测包含在cookie中的HMAC值。可能性小于2128。</p>
<p><br>　　值得注意的是，SCTP仅仅试图来增强网络的可用性，它没有包含任何直接和用户信息认证、完整性和保密功能的协议机制，因为这些特性主要取决于IPSec协议和应用层协议的安全特性。</p>
<p><br>6 SCTP与TCP的功能及应用比较</p>
<p><br>　　由于SCTP也是一个面向连接的协议，可提供所有TCP能够提供的传送层服务。因此，现有的许多Internet应用将面临选择使用TCP或SCTP，来满足他们对传送层服务的需求。需要注意的是，对处理成本比较敏感的应用，在使用SCTP或TCP得到的服务是不一样的，SCTP可以为应用提供一个单独定制的流传输，而TCP为应用提供的是一对地址。</p>
<p><br>　　当然，SCTP还具有一些TCP所不具备的功能，这样，在某些应用场合，选择SCTP实现传送层服务将是更好的选择。SCTP在一个连接中可以支持多个独立用户信息流的发送。正确使用该功能，可以有效减少所谓的&#8220;head-of-line-blocking&#8221;问题带来的影响，在TCP中出现该问题，主要是因为数据包的发送有严格的顺序控制。因此，对那些需要在一个连接中同时支持多个逻辑上独立的信息流传送的应用，SCTP就特别有用。<br>　　SCTP保留有应用信息的边界。当应用数据不是连续的字节流，而是要接收端单独处理大块的数据包时，该功能就非常有用。相反，TCP在提供可靠数据流传送的同时，并不能指出应用中包含的大块数据包。</p>
<p><br>　　SCTP支持没有指明应用类别的用户信息的传送，而且能够保证数据的可靠传送。对那些需要发送没有顺序的可靠信息流的应用，或者喜欢使用自身的信息排序机制的应用，SCTP的这个功能就特别有用。<br></p>
<img src ="http://www.cppblog.com/Bugs/aggbug/54651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-06-26 11:28 <a href="http://www.cppblog.com/Bugs/archive/2008/06/26/54651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下设置Shell的颜色！</title><link>http://www.cppblog.com/Bugs/archive/2008/06/24/54442.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Tue, 24 Jun 2008 03:06:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/06/24/54442.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/54442.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/06/24/54442.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/54442.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/54442.html</trackback:ping><description><![CDATA[<p>&nbsp; 首先使用一个例子来说明如何实现Shell彩色：<br>&nbsp;&nbsp;&nbsp; PS1="\[ \033[0;32;40m\u@\h:\w\$ \033[0m \]" </p>
<p><br>&nbsp;&nbsp; 在上面命令中，&#8220;\033[0;32;40m&#8221;表示定义后面文本的颜色，&#8220;\033&#8221;表示启动一个转义序列，&#8220;[&#8221;定义开始颜色定义，&#8220;0&#8221;定义默认的字体颜色，其它部分稍后定义。<br>&nbsp;&nbsp;&nbsp; &#8220;32&#8221;定义文本的前景色，这里32表示绿色；&#8220;40&#8221;定义文本的背景色，40表示黑色。<br>&nbsp;&nbsp;&nbsp; 在字符串的最后定义了&#8220; \033[0m&#8221;，它是用来恢复了默认的文本颜色设置，这样就只会得到一个彩色提示符，而不会影响命令和其输出的颜色显示（即黑底白字）。 </p>
<p>&nbsp;&nbsp;&nbsp; 我们一共有8种字体颜色可供选择，它们分别是30 (黑色)、31 (红色)、32 (绿色)、33 (黄色)、34 (蓝色)、35 ( 紫红色)、36 (青色)和37 (白色)。<br>&nbsp;&nbsp;&nbsp; 对于底色也有8种颜色可供选择，只需要将字体颜色的3修改为4即可，例如40、41、42、43、44、45、46、47。&nbsp;<br><br>&nbsp;&nbsp;&nbsp; 文本属性 </p>
<p>&nbsp;&nbsp;&nbsp; 我们前面提到，转义序列符后面的&#8220;0&#8221;表示定义文本的颜色设置。<br>&nbsp;&nbsp;&nbsp; 除了颜色设置以外，还可以设置文本的其它属性。<br>&nbsp;&nbsp;&nbsp; 转义序列符后可以跟以下数值：0、1、22、4、24、5、25、7、27，分别定义颜色、黑体、非黑体、下画线、非下画线、闪烁、非闪烁、翻转、非翻转。<br></p>
<img src ="http://www.cppblog.com/Bugs/aggbug/54442.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-06-24 11:06 <a href="http://www.cppblog.com/Bugs/archive/2008/06/24/54442.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Epoll笔记！</title><link>http://www.cppblog.com/Bugs/archive/2008/06/23/54350.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Mon, 23 Jun 2008 02:17:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/06/23/54350.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/54350.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/06/23/54350.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/54350.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/54350.html</trackback:ping><description><![CDATA[epoll的接口非常简单，一共就三个函数：<br><span style="COLOR: rgb(255,1,2)">1. int epoll_create(int size);</span><br>创建一个epoll的句柄，size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数，给出最大监听的fd+1的值。需要注意的是，当创建好epoll句柄后，它就是会占用一个fd值，在linux下如果查看/proc/进程id/fd/，是能够看到这个fd的，所以在使用完epoll后，必须调用close()关闭，否则可能导致fd被耗尽。<br><br><br><span style="COLOR: rgb(255,1,2)">2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);</span><br>epoll的事件注册函数，它不同与select()是在监听事件时告诉内核要监听什么类型的事件，而是在这里先注册要监听的事件类型。第一个参数是epoll_create()的返回值，第二个参数表示动作，用三个宏来表示：<br>EPOLL_CTL_ADD：注册新的fd到epfd中；<br>EPOLL_CTL_MOD：修改已经注册的fd的监听事件；<br>EPOLL_CTL_DEL：从epfd中删除一个fd；<br>第三个参数是需要监听的fd，第四个参数是告诉内核需要监听什么事，struct epoll_event结构如下：<br>struct epoll_event {<br>&nbsp; __uint32_t events;&nbsp; /* Epoll events */<br>&nbsp; epoll_data_t data;&nbsp; /* User data variable */<br>};<br><br>events可以是以下几个宏的集合：<br>EPOLLIN ：表示对应的文件描述符可以读（包括对端SOCKET正常关闭）；<br>EPOLLOUT：表示对应的文件描述符可以写；<br>EPOLLPRI：表示对应的文件描述符有紧急的数据可读（这里应该表示有带外数据到来）；<br>EPOLLERR：表示对应的文件描述符发生错误；<br>EPOLLHUP：表示对应的文件描述符被挂断；<br>EPOLLET： 将EPOLL设为边缘触发(Edge Triggered)模式，这是相对于水平触发(Level Triggered)来说的。<br>EPOLLONESHOT：只监听一次事件，当监听完这次事件之后，如果还需要继续监听这个socket的话，需要再次把这个socket加入到EPOLL队列里<br><br><br><span style="COLOR: rgb(255,1,2)">3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);</span><br>等待事件的产生，类似于select()调用。参数events用来从内核得到事件的集合，maxevents告之内核这个events有多大，这个maxevents的值不能大于创建epoll_create()时的size，参数timeout是超时时间（毫秒，0会立即返回，-1将不确定，也有说法说是永久阻塞）。该函数返回需要处理的事件数目，如返回0表示已超时。<br><br>EPOLL事件有两种模型：<br>Edge Triggered (ET)<br>Level Triggered (LT)<br><br>ET(edge-triggered)是高速工作方式，只支持no-block socket。在这种模式下，当描述符从未就绪变为就绪时，内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪，并且不会再为那个文件描述符发送更多的就绪通知，直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如，你在发送，接收或者接收请求，或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误）。但是请注意，如果一直不对这个fd作IO操作(从而导致它再次变成未就绪)，内核不会发送更多的通知(only once),<span style="FONT-WEIGHT: bold; FONT-STYLE: italic">不过在TCP协议中，ET模式的加速效用仍需要更多的benchmark确认<br><br>另外，当使用epoll的ET模型来工作时，当产生了一个EPOLLIN事件后，<br><span style="COLOR: rgb(255,1,2)">读数据的时候需要考虑的是当recv()返回的大小如果等于请求的大小，那么很有可能是缓冲区还有数据未读完，也意味着该次事件还没有处理完，所以还需要再次读取</span>：<br>while(rs)<br>{<br>&nbsp; buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);<br>&nbsp; if(buflen &lt; 0)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; // 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读<br>&nbsp;&nbsp;&nbsp; // 在这里就当作是该次事件已处理处.<br>&nbsp;&nbsp;&nbsp; if(errno == EAGAIN)<br>&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; else if(buflen == 0)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; // 这里表示对端的socket已正常关闭.<br>&nbsp;&nbsp; }<br><span style="COLOR: rgb(255,1,2)">&nbsp;&nbsp; if(buflen == sizeof(buf)</span><br style="COLOR: rgb(255,1,2)"><span style="COLOR: rgb(255,1,2)">&nbsp;&nbsp;&nbsp;&nbsp; rs = 1;&nbsp;&nbsp; // 需要再次读取</span><br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp; rs = 0;<br>}<br><br><br><span style="FONT-WEIGHT: bold; COLOR: rgb(255,1,2)">还有，假如发送端流量大于接收端的流量(意思是epoll所在的程序读比转发的socket要快),由于是非阻塞的socket,那么send()函数虽然返回,但实际缓冲区的数据并未真正发给接收端,这样不断的读和发，当缓冲区满后会产生EAGAIN错误(参考man send),同时,不理会这次请求发送的数据.所以,需要封装socket_send()的函数用来处理这种情况,该函数会尽量将数据写完再返回，返回-1表示出错。在socket_send()内部,当写缓冲已满(send()返回-1,且errno为EAGAIN),那么会等待后再重试.这种方式并不很完美,在理论上可能会长时间的阻塞在socket_send()内部,但暂没有更好的办法.</span><br><br>ssize_t socket_send(int sockfd, const char* buffer, size_t buflen)<br>{<br>&nbsp; ssize_t tmp;<br>&nbsp; size_t total = buflen;<br>&nbsp; const char *p = buffer;<br><br>&nbsp; while(1)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; tmp = send(sockfd, p, total, 0);<br>&nbsp;&nbsp;&nbsp; if(tmp &lt; 0)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 当send收到信号时,可以继续写,但这里返回-1.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(errno == EINTR)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 在这里做延时后再重试.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(errno == EAGAIN)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usleep(1000);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; if((size_t)tmp == total)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return buflen;<br><br>&nbsp;&nbsp;&nbsp; total -= tmp;<br>&nbsp;&nbsp;&nbsp; p += tmp;<br>&nbsp; }<br><br>&nbsp; return tmp;<br>} </span>
<img src ="http://www.cppblog.com/Bugs/aggbug/54350.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-06-23 10:17 <a href="http://www.cppblog.com/Bugs/archive/2008/06/23/54350.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】使用异步 I/O 大大提高应用程序的性能</title><link>http://www.cppblog.com/Bugs/archive/2008/06/19/54038.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Thu, 19 Jun 2008 09:53:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/06/19/54038.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/54038.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/06/19/54038.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/54038.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/54038.html</trackback:ping><description><![CDATA[出处：<a href="http://www.ibm.com/developerworks/cn/linux/l-async/">http://www.ibm.com/developerworks/cn/linux/l-async/</a><br><br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr vAlign=top>
            <td width="100%">
            <h1>使用异步 I/O 大大提高应用程序的性能</h1>
            <p id=subtitle>学习何时以及如何使用 POSIX AIO API</p>
            <img class=display-img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=1></td>
            <td class=no-print width=192><img height=18 alt=developerWorks src="http://www.ibm.com/developerworks/i/dw.gif" width=192></td>
        </tr>
    </tbody>
</table>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr vAlign=top>
            <td width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td>
            <td width="100%">
            <table class=no-print cellSpacing=0 cellPadding=0 width=160 align=right border=0>
                <tbody>
                    <tr>
                        <td width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td>
                        <td>
                        <table cellSpacing=0 cellPadding=0 width=150 border=0>
                            <tbody>
                                <tr>
                                    <td class=v14-header-1-small>文档选项</td>
                                </tr>
                            </tbody>
                        </table>
                        <table class=v14-gray-table-border cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td class=no-padding width=150>
                                    <table cellSpacing=0 cellPadding=0 width=143 border=0>
                                        <img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8>
                                        <form name=email action=https://www.ibm.com/developerworks/secure/email-it.jsp cM1="1">
                                            <input type=hidden value="Linux 中最常用的输入/输出（I/O）模型是同步 I/O。在这个模型中，当请求发出之后，应用程序就会阻塞，直到请求满足为止。这是很好的一种解决方案，因为调用应用程序在等待 I/O 请求完成时不需要使用任何中央处理单元（CPU）。但是在某些情况中，I/O 请求可能需要与其他进程产生交叠。可移植操作系统接口（POSIX）异步 I/O（AIO）应用程序接口（API）就提供了这种功能。在本文中，我们将对这个 API 概要进行介绍，并来了解一下如何使用它。" name=body cM1="1" cM3 cM2="0"><input type=hidden value="使用异步 I/O 大大提高应用程序的性能" name=subject cM1="1" cM3 cM2="1"><input type=hidden value=cn name=lang cM1="1" cM3 cM2="2">
                                            <script language=JavaScript type=text/javascript>
                                            <!--
                                            document.write('
                                            <tr valign="top">
                                                <td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td>
                                                <td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送" /></td>
                                                <td width="122">
                                                <p><a class="smallplainlink" href="javascript:document.email.submit();"><strong>将此页作为电子邮件发送</strong></a></p>
                                                </td>
                                            </tr>
                                            ');
                                            //-->
                                            </script>
                                            <tbody>
                                                <tr vAlign=top>
                                                    <td width=8><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></td>
                                                    <td width=16><img height=16 alt=将此页作为电子邮件发送 src="http://www.ibm.com/i/v14/icons/em.gif" width=16 vspace=3></td>
                                                    <td width=122>
                                                    <p><a class=smallplainlink href="javascript:document.email.submit();" cmImpressionSent="1"><strong><font color=#5c81a7 size=2>将此页作为电子邮件发送</font></strong></a></p>
                                                    </td>
                                                </tr>
                                                <noscript></noscript>
                                            </form>
                                        </tbody>
                                    </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas --><!--end RESERVED FOR FUTURE USE INCLUDE FILES--><br></td>
                    </tr>
                </tbody>
            </table>
            <p>级别： 中级</p>
            <p><a href="http://www.ibm.com/developerworks/cn/linux/l-async/#author" cmImpressionSent="1"><font color=#5c81a7>M. Tim Jones</font></a> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#116;&#106;&#64;&#109;&#116;&#106;&#111;&#110;&#101;&#115;&#46;&#99;&#111;&#109;&#63;&#115;&#117;&#98;&#106;&#101;&#99;&#116;&#61;&#20351;&#29992;&#24322;&#27493;&#32;&#73;&#47;&#79;&#32;&#22823;&#22823;&#25552;&#39640;&#24212;&#29992;&#31243;&#24207;&#30340;&#24615;&#33021;&#38;&#97;&#109;&#112;&#59;&#99;&#99;&#61;&#116;&#111;&#109;&#121;&#111;&#117;&#110;&#103;&#64;&#117;&#115;&#46;&#105;&#98;&#109;&#46;&#99;&#111;&#109;" cmImpressionSent="1"><font color=#5c81a7>mtj@mtjones.com</font></a>), 顾问工程师, Emulex<br></p>
            <p>2006 年 9 月 28 日</p>
            <blockquote>Linux&#174; 中最常用的输入/输出（I/O）模型是同步 I/O。在这个模型中，当请求发出之后，应用程序就会阻塞，直到请求满足为止。这是很好的一种解决方案，因为调用应用程序在等待 I/O 请求完成时不需要使用任何中央处理单元（CPU）。但是在某些情况中，I/O 请求可能需要与其他进程产生交叠。可移植操作系统接口（POSIX）异步 I/O（AIO）应用程序接口（API）就提供了这种功能。在本文中，我们将对这个 API 概要进行介绍，并来了解一下如何使用它。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p><a name=N1005E><span class=atitle>AIO 简介 </span></a></p>
            <p>Linux 异步 I/O 是 Linux 内核中提供的一个相当新的增强。它是 2.6 版本内核的一个标准特性，但是我们在 2.4 版本内核的补丁中也可以找到它。AIO 背后的基本思想是允许进程发起很多 I/O 操作，而不用阻塞或等待任何操作完成。稍后或在接收到 I/O 操作完成的通知时，进程就可以检索 I/O 操作的结果。</p>
            <p><a name=N10068><span class=atitle>I/O 模型 </span></a></p>
            <p>在深入介绍 AIO API 之前，让我们先来探索一下 Linux 上可以使用的不同 I/O 模型。这并不是一个详尽的介绍，但是我们将试图介绍最常用的一些模型来解释它们与异步 I/O 之间的区别。图 1 给出了同步和异步模型，以及阻塞和非阻塞的模型。</p>
            <br><a name=fig1><strong>图 1. 基本 Linux I/O 模型的简单矩阵</strong></a><br><img height=225 alt="基本 Linux I/O 模型的简单矩阵" src="http://www.ibm.com/developerworks/cn/linux/l-async/figure1.gif" width=386> <br>
            <p>每个 I/O 模型都有自己的使用模式，它们对于特定的应用程序都有自己的优点。本节将简要对其一一进行介绍。</p>
            <p><a name=N10084><span class=smalltitle><strong><font face=Arial>同步阻塞 I/O </font></strong></span></a></p>
            <table cellSpacing=0 cellPadding=0 width="40%" align=right border=0>
                <tbody>
                    <tr>
                        <td width=10><strong><font face=Arial><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></font></strong></td>
                        <td>
                        <table cellSpacing=0 cellPadding=5 width="100%" border=1>
                            <tbody>
                                <tr>
                                    <td bgColor=#eeeeee><a name=N1008E><strong>I/O 密集型与 CPU 密集型进程的比较</strong></a><br>
                                    <p>I/O 密集型进程所执行的 I/O 操作比执行的处理操作更多。CPU 密集型的进程所执行的处理操作比 I/O 操作更多。Linux 2.6 的调度器实际上更加偏爱 I/O 密集型的进程，因为它们通常会发起一个 I/O 操作，然后进行阻塞，这就意味着其他工作都可以在两者之间有效地交错进行。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>最常用的一个模型是同步阻塞 I/O 模型。在这个模型中，用户空间的应用程序执行一个系统调用，这会导致应用程序阻塞。这意味着应用程序会一直阻塞，直到系统调用完成为止（数据传输完成或发生错误）。调用应用程序处于一种不再消费 CPU 而只是简单等待响应的状态，因此从处理的角度来看，这是非常有效的。</p>
            <p>图 2 给出了传统的阻塞 I/O 模型，这也是目前应用程序中最为常用的一种模型。其行为非常容易理解，其用法对于典型的应用程序来说都非常有效。在调用 <code>read</code> 系统调用时，应用程序会阻塞并对内核进行上下文切换。然后会触发读操作，当响应返回时（从我们正在从中读取的设备中返回），数据就被移动到用户空间的缓冲区中。然后应用程序就会解除阻塞（<code>read</code> 调用返回）。</p>
            <br><a name=fig2><strong>图 2. 同步阻塞 I/O 模型的典型流程</strong></a><br><img height=340 alt="同步阻塞 I/O 模型的典型流程" src="http://www.ibm.com/developerworks/cn/linux/l-async/figure2.gif" width=538> <br>
            <p>从应用程序的角度来说，<code>read</code> 调用会延续很长时间。实际上，在内核执行读操作和其他工作时，应用程序的确会被阻塞。</p>
            <p><a name=N100BB><span class=smalltitle><strong><font face=Arial>同步非阻塞 I/O </font></strong></span></a></p>
            <p>同步阻塞 I/O 的一种效率稍低的变种是同步非阻塞 I/O。在这种模型中，设备是以非阻塞的形式打开的。这意味着 I/O 操作不会立即完成，<code>read</code> 操作可能会返回一个错误代码，说明这个命令不能立即满足（<code>EAGAIN</code> 或 <code>EWOULDBLOCK</code>），如图 3 所示。</p>
            <br><a name=fig3><strong>图 3. 同步非阻塞 I/O 模型的典型流程</strong></a><br><img height=340 alt="同步非阻塞 I/O 模型的典型流程" src="http://www.ibm.com/developerworks/cn/linux/l-async/figure3.gif" width=474> <br>
            <p>非阻塞的实现是 I/O 命令可能并不会立即满足，需要应用程序调用许多次来等待操作完成。这可能效率不高，因为在很多情况下，当内核执行这个命令时，应用程序必须要进行忙碌等待，直到数据可用为止，或者试图执行其他工作。正如图 3 所示的一样，这个方法可以引入 I/O 操作的延时，因为数据在内核中变为可用到用户调用 <code>read</code> 返回数据之间存在一定的间隔，这会导致整体数据吞吐量的降低。</p>
            <p><a name=N100E7><span class=smalltitle><strong><font face=Arial>异步阻塞 I/O </font></strong></span></a></p>
            <p>另外一个阻塞解决方案是带有阻塞通知的非阻塞 I/O。在这种模型中，配置的是非阻塞 I/O，然后使用阻塞 <code>select</code> 系统调用来确定一个 I/O 描述符何时有操作。使 <code>select</code> 调用非常有趣的是它可以用来为多个描述符提供通知，而不仅仅为一个描述符提供通知。对于每个提示符来说，我们可以请求这个描述符可以写数据、有读数据可用以及是否发生错误的通知。</p>
            <br><a name=fig4><strong>图 4. 异步阻塞 I/O 模型的典型流程 (select)</strong></a><br><img height=340 alt="异步阻塞 I/O 模型的典型流程" src="http://www.ibm.com/developerworks/cn/linux/l-async/figure4.gif" width=541> <br>
            <p><code>select</code> 调用的主要问题是它的效率不是非常高。尽管这是异步通知使用的一种方便模型，但是对于高性能的 I/O 操作来说不建议使用。</p>
            <p><a name=N1010E><span class=smalltitle><strong><font face=Arial>异步非阻塞 I/O（AIO） </font></strong></span></a></p>
            <p>最后，异步非阻塞 I/O 模型是一种处理与 I/O 重叠进行的模型。读请求会立即返回，说明 <code>read</code> 请求已经成功发起了。在后台完成读操作时，应用程序然后会执行其他处理操作。当 <code>read</code> 的响应到达时，就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。</p>
            <br><a name=fig5><strong>图 5. 异步非阻塞 I/O 模型的典型流程</strong></a><br><img height=340 alt="异步非阻塞 I/O 模型的典型流程" src="http://www.ibm.com/developerworks/cn/linux/l-async/figure5.gif" width=481> <br>
            <p>在一个进程中为了执行多个 I/O 请求而对计算操作和 I/O 处理进行重叠处理的能力利用了处理速度与 I/O 速度之间的差异。当一个或多个 I/O 请求挂起时，CPU 可以执行其他任务；或者更为常见的是，在发起其他 I/O 的同时对已经完成的 I/O 进行操作。</p>
            <p>下一节将深入介绍这种模型，探索这种模型使用的 API，然后展示几个命令。</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-async/#main" cmImpressionSent="1"><strong><font color=#5c81a7>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10135><span class=atitle>异步 I/O 的动机 </span></a></p>
            <p>从前面 I/O 模型的分类中，我们可以看出 AIO 的动机。这种阻塞模型需要在 I/O 操作开始时阻塞应用程序。这意味着不可能同时重叠进行处理和 I/O 操作。同步非阻塞模型允许处理和 I/O 操作重叠进行，但是这需要应用程序根据重现的规则来检查 I/O 操作的状态。这样就剩下异步非阻塞 I/O 了，它允许处理和 I/O 操作重叠进行，包括 I/O 操作完成的通知。</p>
            <p>除了需要阻塞之外，<code>select</code> 函数所提供的功能（异步阻塞 I/O）与 AIO 类似。不过，它是对通知事件进行阻塞，而不是对 I/O 调用进行阻塞。</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-async/#main" cmImpressionSent="1"><strong><font color=#5c81a7>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10145><span class=atitle>Linux 上的 AIO 简介 </span></a></p>
            <p>本节将探索 Linux 的异步 I/O 模型，从而帮助我们理解如何在应用程序中使用这种技术。</p>
            <p>在传统的 I/O 模型中，有一个使用惟一句柄标识的 I/O 通道。在 UNIX&#174; 中，这些句柄是文件描述符（这对等同于文件、管道、套接字等等）。在阻塞 I/O 中，我们发起了一次传输操作，当传输操作完成或发生错误时，系统调用就会返回。</p>
            <table cellSpacing=0 cellPadding=0 width="40%" align=right border=0>
                <tbody>
                    <tr>
                        <td width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td>
                        <td>
                        <table cellSpacing=0 cellPadding=5 width="100%" border=1>
                            <tbody>
                                <tr>
                                    <td bgColor=#eeeeee><a name=N10157><strong>Linux 上的 AIO</strong></a><br>
                                    <p>AIO 在 2.5 版本的内核中首次出现，现在已经是 2.6 版本的产品内核的一个标准特性了。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>在异步非阻塞 I/O 中，我们可以同时发起多个传输操作。这需要每个传输操作都有惟一的上下文，这样我们才能在它们完成时区分到底是哪个传输操作完成了。在 AIO 中，这是一个 <code>aiocb</code>（AIO I/O Control Block）结构。这个结构包含了有关传输的所有信息，包括为数据准备的用户缓冲区。在产生 I/O （称为完成）通知时，<code>aiocb</code> 结构就被用来惟一标识所完成的 I/O 操作。这个 API 的展示显示了如何使用它。</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-async/#main" cmImpressionSent="1"><strong><font color=#5c81a7>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N1016B><span class=atitle>AIO API </span></a></p>
            <p>AIO 接口的 API 非常简单，但是它为数据传输提供了必需的功能，并给出了两个不同的通知模型。表 1 给出了 AIO 的接口函数，本节稍后会更详细进行介绍。</p>
            <br><a name=table1><strong>表 1. AIO 接口 API</strong></a><br>
            <table class=data-table-2 cellSpacing=0 cellPadding=0 width="100%" summary="AIO interface APIs" border=0>
                <tbody>
                    <tr>
                        <th>API 函数</th>
                        <th>说明</th>
                    </tr>
                    <tr>
                        <td class=tb-row><code>aio_read</code></td>
                        <td>请求异步读操作</td>
                    </tr>
                    <tr>
                        <td class=tb-row><code>aio_error</code></td>
                        <td>检查异步请求的状态</td>
                    </tr>
                    <tr>
                        <td class=tb-row><code>aio_return</code></td>
                        <td>获得完成的异步请求的返回状态</td>
                    </tr>
                    <tr>
                        <td class=tb-row><code>aio_write</code></td>
                        <td>请求异步写操作</td>
                    </tr>
                    <tr>
                        <td class=tb-row><code>aio_suspend</code></td>
                        <td>挂起调用进程，直到一个或多个异步请求已经完成（或失败）</td>
                    </tr>
                    <tr>
                        <td class=tb-row><code>aio_cancel</code></td>
                        <td>取消异步 I/O 请求</td>
                    </tr>
                    <tr>
                        <td class=tb-row><code>lio_listio</code></td>
                        <td>发起一系列 I/O 操作</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>每个 API 函数都使用 <code>aiocb</code> 结构开始或检查。这个结构有很多元素，但是清单 1 仅仅给出了需要（或可以）使用的元素。</p>
            <br><a name=listing1><strong>清单 1. aiocb 结构中相关的域 </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>
                        struct aiocb {
                        int aio_fildes;               // File Descriptor
                        int aio_lio_opcode;           // Valid only for lio_listio (r/w/nop)
                        volatile void *aio_buf;       // Data Buffer
                        size_t aio_nbytes;            // Number of Bytes in Data Buffer
                        struct sigevent aio_sigevent; // Notification Structure
                        /* Internal fields */
                        ...
                        };
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p><code>sigevent</code> 结构告诉 AIO 在 I/O 操作完成时应该执行什么操作。我们将在 AIO 的展示中对这个结构进行探索。现在我们将展示各个 AIO 的 API 函数是如何工作的，以及我们应该如何使用它们。</p>
            <p><a name=N101F8><span class=smalltitle><strong><font face=Arial>aio_read </font></strong></span></a></p>
            <p><code>aio_read</code> 函数请求对一个有效的文件描述符进行异步读操作。这个文件描述符可以表示一个文件、套接字甚至管道。<code>aio_read</code> 函数的原型如下：</p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>int <span class=boldcode><strong>aio_read</strong></span>( struct aiocb *aiocbp );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p><code>aio_read</code> 函数在请求进行排队之后会立即返回。如果执行成功，返回值就为 0；如果出现错误，返回值就为 -1，并设置 <code>errno</code> 的值。</p>
            <p>要执行读操作，应用程序必须对 <code>aiocb</code> 结构进行初始化。下面这个简短的例子就展示了如何填充 <code>aiocb</code> 请求结构，并使用 <code>aio_read</code> 来执行异步读请求（现在暂时忽略通知）操作。它还展示了 <code>aio_error</code> 的用法，不过我们将稍后再作解释。</p>
            <br><a name=listing2><strong>清单 2. 使用 aio_read 进行异步读操作的例子 </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>
                        #include &lt;aio.h&gt;
                        ...
                        int fd, ret;
                        struct aiocb my_aiocb;
                        fd = open( "file.txt", O_RDONLY );
                        if (fd &lt; 0) perror("open");
                        /* Zero out the aiocb structure (recommended) */
                        bzero( (char *)&amp;my_aiocb, sizeof(struct aiocb) );
                        /* Allocate a data buffer for the aiocb request */
                        my_aiocb.aio_buf = malloc(BUFSIZE+1);
                        if (!my_aiocb.aio_buf) perror("malloc");
                        /* Initialize the necessary fields in the aiocb */
                        my_aiocb.aio_fildes = fd;
                        my_aiocb.aio_nbytes = BUFSIZE;
                        my_aiocb.aio_offset = 0;
                        ret = <span class=boldcode><strong>aio_read</strong></span>( &amp;my_aiocb );
                        if (ret &lt; 0) perror("aio_read");
                        while ( <span class=boldcode><strong>aio_error</strong></span>( &amp;my_aiocb ) == EINPROGRESS ) ;
                        if ((ret = aio_return( &amp;my_iocb )) &gt; 0) {
                        /* got ret bytes on the read */
                        } else {
                        /* read failed, consult errno */
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>在清单 2 中，在打开要从中读取数据的文件之后，我们就清空了 <code>aiocb</code> 结构，然后分配一个数据缓冲区。并将对这个数据缓冲区的引用放到 <code>aio_buf</code> 中。然后，我们将 <code>aio_nbytes</code> 初始化成缓冲区的大小。并将 <code>aio_offset</code> 设置成 0（该文件中的第一个偏移量）。我们将 <code>aio_fildes</code> 设置为从中读取数据的文件描述符。在设置这些域之后，就调用 <code>aio_read</code> 请求进行读操作。我们然后可以调用 <code>aio_error</code> 来确定 <code>aio_read</code> 的状态。只要状态是 <code>EINPROGRESS</code>，就一直忙碌等待，直到状态发生变化为止。现在，请求可能成功，也可能失败。</p>
            <table cellSpacing=0 cellPadding=0 width="40%" align=right border=0>
                <tbody>
                    <tr>
                        <td width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td>
                        <td>
                        <table cellSpacing=0 cellPadding=5 width="100%" border=1>
                            <tbody>
                                <tr>
                                    <td bgColor=#eeeeee><a name=N10268><strong>使用 AIO 接口来编译程序</strong></a><br>
                                    <p>我们可以在 <code>aio.h</code> 头文件中找到函数原型和其他需要的符号。在编译使用这种接口的程序时，我们必须使用 POSIX 实时扩展库（<code>librt</code>）。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>注意使用这个 API 与标准的库函数从文件中读取内容是非常相似的。除了 <code>aio_read</code> 的一些异步特性之外，另外一个区别是读操作偏移量的设置。在传统的 <code>read</code> 调用中，偏移量是在文件描述符上下文中进行维护的。对于每个读操作来说，偏移量都需要进行更新，这样后续的读操作才能对下一块数据进行寻址。对于异步 I/O 操作来说这是不可能的，因为我们可以同时执行很多读请求，因此必须为每个特定的读请求都指定偏移量。</p>
            <p><a name=N10284><span class=smalltitle><strong><font face=Arial>aio_error </font></strong></span></a></p>
            <p><code>aio_error</code> 函数被用来确定请求的状态。其原型如下：</p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>int <span class=boldcode><strong>aio_error</strong></span>( struct aiocb *aiocbp );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>这个函数可以返回以下内容：</p>
            <ul>
                <li><code>EINPROGRESS</code>，说明请求尚未完成
                <li><code>ECANCELLED</code>，说明请求被应用程序取消了
                <li><code>-1</code>，说明发生了错误，具体错误原因可以查阅 <code>errno</code> </li>
            </ul>
            <p><a name=N102B4><span class=smalltitle><strong><font face=Arial>aio_return </font></strong></span></a></p>
            <p>异步 I/O 和标准块 I/O 之间的另外一个区别是我们不能立即访问这个函数的返回状态，因为我们并没有阻塞在 <code>read</code> 调用上。在标准的 <code>read</code> 调用中，返回状态是在该函数返回时提供的。但是在异步 I/O 中，我们要使用 <code>aio_return</code> 函数。这个函数的原型如下：</p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>ssize_t <span class=boldcode><strong>aio_return</strong></span>( struct aiocb *aiocbp );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>只有在 <code>aio_error</code> 调用确定请求已经完成（可能成功，也可能发生了错误）之后，才会调用这个函数。<code>aio_return</code> 的返回值就等价于同步情况中 <code>read</code> 或 <code>write</code> 系统调用的返回值（所传输的字节数，如果发生错误，返回值就为 <code>-1</code>）。</p>
            <p><a name=N102E9><span class=smalltitle><strong><font face=Arial>aio_write </font></strong></span></a></p>
            <p><code>aio_write</code> 函数用来请求一个异步写操作。其函数原型如下： </p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>int <span class=boldcode><strong>aio_write</strong></span>( struct aiocb *aiocbp );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p><code>aio_write</code> 函数会立即返回，说明请求已经进行排队（成功时返回值为 <code>0</code>，失败时返回值为 <code>-1</code>，并相应地设置 <code>errno</code>）。</p>
            <p>这与 <code>read</code> 系统调用类似，但是有一点不一样的行为需要注意。回想一下对于 <code>read</code> 调用来说，要使用的偏移量是非常重要的。然而，对于 <code>write</code> 来说，这个偏移量只有在没有设置 <code>O_APPEND</code> 选项的文件上下文中才会非常重要。如果设置了 <code>O_APPEND</code>，那么这个偏移量就会被忽略，数据都会被附加到文件的末尾。否则，<code>aio_offset</code> 域就确定了数据在要写入的文件中的偏移量。</p>
            <p><a name=N1032B><span class=smalltitle><strong><font face=Arial>aio_suspend </font></strong></span></a></p>
            <p>我们可以使用 <code>aio_suspend</code> 函数来挂起（或阻塞）调用进程，直到异步请求完成为止，此时会产生一个信号，或者发生其他超时操作。调用者提供了一个 <code>aiocb</code> 引用列表，其中任何一个完成都会导致 <code>aio_suspend</code> 返回。 <code>aio_suspend</code> 的函数原型如下：</p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>int <span class=boldcode><strong>aio_suspend</strong></span>( const struct aiocb *const cblist[],
                        int n, const struct timespec *timeout );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p><code>aio_suspend</code> 的使用非常简单。我们要提供一个 <code>aiocb</code> 引用列表。如果任何一个完成了，这个调用就会返回 <code>0</code>。否则就会返回 <code>-1</code>，说明发生了错误。请参看清单 3。</p>
            <br><a name=listing3><strong>清单 3. 使用 aio_suspend 函数阻塞异步 I/O </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>
                        struct aioct *cblist[MAX_LIST]
                        /* Clear the list. */
                        bzero( (char *)cblist, sizeof(cblist) );
                        /* Load one or more references into the list */
                        cblist[0] = &amp;my_aiocb;
                        ret = <span class=boldcode><strong>aio_read</strong></span>( &amp;my_aiocb );
                        ret = <span class=boldcode><strong>aio_suspend</strong></span>( cblist, MAX_LIST, NULL );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>注意，<code>aio_suspend</code> 的第二个参数是 <code>cblist</code> 中元素的个数，而不是 <code>aiocb</code> 引用的个数。<code>cblist</code> 中任何 <code>NULL</code> 元素都会被 <code>aio_suspend</code> 忽略。</p>
            <p>如果为 <code>aio_suspend</code> 提供了超时，而超时情况的确发生了，那么它就会返回 <code>-1</code>，<code>errno</code> 中会包含 <code>EAGAIN</code>。</p>
            <p><a name=N1039D><span class=smalltitle><strong><font face=Arial>aio_cancel </font></strong></span></a></p>
            <p><code>aio_cancel</code> 函数允许我们取消对某个文件描述符执行的一个或所有 I/O 请求。其原型如下：</p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>int <span class=boldcode><strong>aio_cancel</strong></span>( int fd, struct aiocb *aiocbp );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>要取消一个请求，我们需要提供文件描述符和 <code>aiocb</code> 引用。如果这个请求被成功取消了，那么这个函数就会返回 <code>AIO_CANCELED</code>。如果请求完成了，这个函数就会返回 <code>AIO_NOTCANCELED</code>。</p>
            <p>要取消对某个给定文件描述符的所有请求，我们需要提供这个文件的描述符，以及一个对 <code>aiocbp</code> 的 <code>NULL</code> 引用。如果所有的请求都取消了，这个函数就会返回 <code>AIO_CANCELED</code>；如果至少有一个请求没有被取消，那么这个函数就会返回 <code>AIO_NOT_CANCELED</code>；如果没有一个请求可以被取消，那么这个函数就会返回 <code>AIO_ALLDONE</code>。我们然后可以使用 <code>aio_error</code> 来验证每个 AIO 请求。如果这个请求已经被取消了，那么 <code>aio_error</code> 就会返回 <code>-1</code>，并且 <code>errno</code> 会被设置为 <code>ECANCELED</code>。</p>
            <p><a name=N103EC><span class=smalltitle><strong><font face=Arial>lio_listio </font></strong></span></a></p>
            <p>最后，AIO 提供了一种方法使用 <code>lio_listio</code> API 函数同时发起多个传输。这个函数非常重要，因为这意味着我们可以在一个系统调用（一次内核上下文切换）中启动大量的 I/O 操作。从性能的角度来看，这非常重要，因此值得我们花点时间探索一下。<code>lio_listio</code> API 函数的原型如下：</p>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>int <span class=boldcode><strong>lio_listio</strong></span>( int mode, struct aiocb *list[], int nent,
                        struct sigevent *sig );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p><code>mode</code> 参数可以是 <code>LIO_WAIT</code> 或 <code>LIO_NOWAIT</code>。<code>LIO_WAIT</code> 会阻塞这个调用，直到所有的 I/O 都完成为止。在操作进行排队之后，<code>LIO_NOWAIT</code> 就会返回。<code>list</code> 是一个 <code>aiocb</code> 引用的列表，最大元素的个数是由 <code>nent</code> 定义的。注意 <code>list</code> 的元素可以为 <code>NULL</code>，<code>lio_listio</code> 会将其忽略。<code>sigevent</code> 引用定义了在所有 I/O 操作都完成时产生信号的方法。</p>
            <p>对于 <code>lio_listio</code> 的请求与传统的 <code>read</code> 或 <code>write</code> 请求在必须指定的操作方面稍有不同，如清单 4 所示。</p>
            <br><a name=listing4><strong>清单 4. 使用 lio_listio 函数发起一系列请求 </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>
                        struct aiocb aiocb1, aiocb2;
                        struct aiocb *list[MAX_LIST];
                        ...
                        /* Prepare the first aiocb */
                        aiocb1.aio_fildes = fd;
                        aiocb1.aio_buf = malloc( BUFSIZE+1 );
                        aiocb1.aio_nbytes = BUFSIZE;
                        aiocb1.aio_offset = next_offset;
                        aiocb1.aio_lio_opcode = LIO_READ;
                        ...
                        bzero( (char *)list, sizeof(list) );
                        list[0] = &amp;aiocb1;
                        list[1] = &amp;aiocb2;
                        ret = <span class=boldcode><strong>lio_listio</strong></span>( LIO_WAIT, list, MAX_LIST, NULL );
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>对于读操作来说，<code>aio_lio_opcode</code> 域的值为 <code>LIO_READ</code>。对于写操作来说，我们要使用 <code>LIO_WRITE</code>，不过 <code>LIO_NOP</code> 对于不执行操作来说也是有效的。</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-async/#main" cmImpressionSent="1"><strong><font color=#5c81a7>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10467><span class=atitle>AIO 通知 </span></a></p>
            <p>现在我们已经看过了可用的 AIO 函数，本节将深入介绍对异步通知可以使用的方法。我们将通过信号和函数回调来探索异步函数的通知机制。</p>
            <p><a name=N10471><span class=smalltitle><strong><font face=Arial>使用信号进行异步通知 </font></strong></span></a></p>
            <p>使用信号进行进程间通信（IPC）是 UNIX 中的一种传统机制，AIO 也可以支持这种机制。在这种范例中，应用程序需要定义信号处理程序，在产生指定的信号时就会调用这个处理程序。应用程序然后配置一个异步请求将在请求完成时产生一个信号。作为信号上下文的一部分，特定的 <code>aiocb</code> 请求被提供用来记录多个可能会出现的请求。清单 5 展示了这种通知方法。</p>
            <br><a name=listing5><strong>清单 5. 使用信号作为 AIO 请求的通知 </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>
                        void setup_io( ... )
                        {
                        int fd;
                        struct sigaction sig_act;
                        struct aiocb my_aiocb;
                        ...
                        /* Set up the signal handler */
                        sigemptyset(&amp;sig_act.sa_mask);
                        sig_act.sa_flags = SA_SIGINFO;
                        sig_act.sa_sigaction = aio_completion_handler;
                        /* Set up the AIO request */
                        bzero( (char *)&amp;my_aiocb, sizeof(struct aiocb) );
                        my_aiocb.aio_fildes = fd;
                        my_aiocb.aio_buf = malloc(BUF_SIZE+1);
                        my_aiocb.aio_nbytes = BUF_SIZE;
                        my_aiocb.aio_offset = next_offset;
                        /* Link the AIO request with the Signal Handler */
                        my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
                        my_aiocb.aio_sigevent.sigev_signo = SIGIO;
                        my_aiocb.aio_sigevent.sigev_value.sival_ptr = &amp;my_aiocb;
                        /* Map the Signal to the Signal Handler */
                        ret = sigaction( SIGIO, &amp;sig_act, NULL );
                        ...
                        ret = <span class=boldcode><strong>aio_read</strong></span>( &amp;my_aiocb );
                        }
                        void aio_completion_handler( int signo, siginfo_t *info, void *context )
                        {
                        struct aiocb *req;
                        /* Ensure it's our signal */
                        if (info-&gt;si_signo == SIGIO) {
                        req = (struct aiocb *)info-&gt;si_value.sival_ptr;
                        /* Did the request complete? */
                        if (<span class=boldcode><strong>aio_error</strong></span>( req ) == 0) {
                        /* Request completed successfully, get the return status */
                        ret = <span class=boldcode><strong>aio_return</strong></span>( req );
                        }
                        }
                        return;
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>在清单 5 中，我们在 <code>aio_completion_handler</code> 函数中设置信号处理程序来捕获 <code>SIGIO</code> 信号。然后初始化 <code>aio_sigevent</code> 结构产生 <code>SIGIO</code> 信号来进行通知（这是通过 <code>sigev_notify</code> 中的 <code>SIGEV_SIGNAL</code> 定义来指定的）。当读操作完成时，信号处理程序就从该信号的 <code>si_value</code> 结构中提取出 <code>aiocb</code>，并检查错误状态和返回状态来确定 I/O 操作是否完成。</p>
            <p>对于性能来说，这个处理程序也是通过请求下一次异步传输而继续进行 I/O 操作的理想地方。采用这种方式，在一次数据传输完成时，我们就可以立即开始下一次数据传输操作。</p>
            <p><a name=N104B8><span class=smalltitle><strong><font face=Arial>使用回调函数进行异步通知 </font></strong></span></a></p>
            <p>另外一种通知方式是系统回调函数。这种机制不会为通知而产生一个信号，而是会调用用户空间的一个函数来实现通知功能。我们在 <code>sigevent</code> 结构中设置了对 <code>aiocb</code> 的引用，从而可以惟一标识正在完成的特定请求。请参看清单 6。</p>
            <br><a name=listing6><strong>清单 6. 对 AIO 请求使用线程回调通知 </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="60%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>
                        void setup_io( ... )
                        {
                        int fd;
                        struct aiocb my_aiocb;
                        ...
                        /* Set up the AIO request */
                        bzero( (char *)&amp;my_aiocb, sizeof(struct aiocb) );
                        my_aiocb.aio_fildes = fd;
                        my_aiocb.aio_buf = malloc(BUF_SIZE+1);
                        my_aiocb.aio_nbytes = BUF_SIZE;
                        my_aiocb.aio_offset = next_offset;
                        /* Link the AIO request with a thread callback */
                        my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
                        my_aiocb.aio_sigevent.notify_function = aio_completion_handler;
                        my_aiocb.aio_sigevent.notify_attributes = NULL;
                        my_aiocb.aio_sigevent.sigev_value.sival_ptr = &amp;my_aiocb;
                        ...
                        ret = <span class=boldcode><strong>aio_read</strong></span>( &amp;my_aiocb );
                        }
                        void aio_completion_handler( sigval_t sigval )
                        {
                        struct aiocb *req;
                        req = (struct aiocb *)sigval.sival_ptr;
                        /* Did the request complete? */
                        if (<span class=boldcode><strong>aio_error</strong></span>( req ) == 0) {
                        /* Request completed successfully, get the return status */
                        ret = <span class=boldcode><strong>aio_return</strong></span>( req );
                        }
                        return;
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>在清单 6 中，在创建自己的 <code>aiocb</code> 请求之后，我们使用 <code>SIGEV_THREAD</code> 请求了一个线程回调函数来作为通知方法。然后我们将指定特定的通知处理程序，并将要传输的上下文加载到处理程序中（在这种情况中，是个对 <code>aiocb</code> 请求自己的引用）。在这个处理程序中，我们简单地引用到达的 <code>sigval</code> 指针并使用 AIO 函数来验证请求已经完成。</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-async/#main" cmImpressionSent="1"><strong><font color=#5c81a7>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N104F0><span class=atitle>对 AIO 进行系统优化 </span></a></p>
            <p>proc 文件系统包含了两个虚拟文件，它们可以用来对异步 I/O 的性能进行优化：</p>
            <ul>
                <li>/proc/sys/fs/aio-nr 文件提供了系统范围异步 I/O 请求现在的数目。
                <li>/proc/sys/fs/aio-max-nr 文件是所允许的并发请求的最大个数。最大个数通常是 64KB，这对于大部分应用程序来说都已经足够了。 </li>
            </ul>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-async/#main" cmImpressionSent="1"><strong><font color=#5c81a7>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10502><span class=atitle>结束语 </span></a></p>
            <p>使用异步 I/O 可以帮助我们构建 I/O 速度更快、效率更高的应用程序。如果我们的应用程序可以对处理和 I/O 操作重叠进行，那么 AIO 就可以帮助我们构建可以更高效地使用可用 CPU 资源的应用程序。尽管这种 I/O 模型与在大部分 Linux 应用程序中使用的传统阻塞模式都不同，但是异步通知模型在概念上来说却非常简单，可以简化我们的设计。 </p>
            <br><br>
            <p><a name=resources><span class=atitle>参考资料 </span></a></p>
            <strong>学习</strong><br>
            <ul>
                <li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/linux/library/l-async/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" target=_blank cmImpressionSent="1"><font color=#5c81a7>英文原文</font></a> 。<br><br>
                <li><a href="http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html" cmImpressionSent="1"><font color=#5c81a7>POSIX.1b 实现</font></a> 从 GNU Library 的角度介绍了 AIO 的详细内幕。 <br><br>
                <li><a href="http://www.mnis.fr/en/support/doc/rtos/c1150.html" cmImpressionSent="1"><font color=#5c81a7>Realtime Support in Linux</font></a> 解释了更多有关 AIO 和很多实时扩展的信息，内容从调度、POSIX I/O 到 POSIX 线程和高分辨率的定时器（HRT）。 <br><br>
                <li>在为 2.5 版本内核集成而编写的 <a href="http://lse.sourceforge.net/io/aionotes.txt" cmImpressionSent="1"><font color=#5c81a7>Design Notes</font></a> 中，我们可以学习有关 Linux 中 AIO 的设计和实现的知识。 <br><br>
                <li>在 <a href="http://www.ibm.com/developerworks/cn/linux/" cmImpressionSent="1"><font color=#5c81a7>developerWorks Linux 专区</font></a> 中可以找到为 Linux 开发人员准备的更多资源。 <br><br>
                <li>随时关注 <a href="http://www.ibm.com/developerworks/offers/techbriefings/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" cmImpressionSent="1"><font color=#5c81a7>developerWorks 技术事件和网络广播</font></a>。 </li>
            </ul>
            <br><strong>获得产品和技术</strong><br>
            <ul>
                <li><a href="http://www.ibm.com/developerworks/offers/sek/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" cmImpressionSent="1"><font color=#5c81a7>订购免费的 SEK for Linux</font></a>，这有两张 DVD，包括最新的 IBM for Linux 的试用软件，包括 DB2&#174;、Lotus&#174;、Rational&#174;、Tivoli&#174; 和 WebSphere&#174;。 <br><br>
                <li>在您的下一个开发项目中采用 <a href="http://www.ibm.com/developerworks/downloads/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" cmImpressionSent="1"><font color=#5c81a7>IBM 试用软件</font></a>，这可以从 developerWorks 上直接下载。 <br><br></li>
            </ul>
            <br><strong>讨论</strong><br>
            <ul>
                <li>通过参与 <a href="http://www.ibm.com/developerworks/blogs/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" cmImpressionSent="1"><font color=#5c81a7>developerWorks blogs</font></a> 加入 developerWorks 社区。 <br><br></li>
            </ul>
            <br><br>
            <p><a name=author><span class=atitle>关于作者</span></a></p>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td colSpan=3><img height=5 alt="" src="http://www.ibm.com/i/c.gif" width="100%"></td>
                    </tr>
                    <tr vAlign=top align=left>
                        <td>
                        <p><img height=80 alt="M. Tim Jones" src="http://www.ibm.com/developerworks/i/p-mjones.jpg" width=64 align=left border=0 name="M. Tim Jones" valign="top"></p>
                        </td>
                        <td><img height=5 alt="" src="http://www.ibm.com/i/c.gif" width=4></td>
                        <td width="100%">
                        <p>Tim Jones 是一名嵌入式软件工程师，他是 <em>GNU/Linux Application Programming</em>、<em>AI Application Programming</em> 以及 <em>BSD Sockets Programming from a Multilanguage Perspective</em> 等书的作者。他的工程背景非常广泛，从同步宇宙飞船的内核开发到嵌入式架构设计，再到网络协</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/Bugs/aggbug/54038.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-06-19 17:53 <a href="http://www.cppblog.com/Bugs/archive/2008/06/19/54038.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初次使用linux下的异步I/O</title><link>http://www.cppblog.com/Bugs/archive/2008/06/19/54037.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Thu, 19 Jun 2008 09:50:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/06/19/54037.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/54037.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/06/19/54037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/54037.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/54037.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">aio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">errno.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[])<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img id=Codehighlighter1_110_897_Open_Image onclick="this.style.display='none'; Codehighlighter1_110_897_Open_Text.style.display='none'; Codehighlighter1_110_897_Closed_Image.style.display='inline'; Codehighlighter1_110_897_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_110_897_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_110_897_Closed_Text.style.display='none'; Codehighlighter1_110_897_Open_Image.style.display='inline'; Codehighlighter1_110_897_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_110_897_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_110_897_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd,&nbsp;ret;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;aiocb&nbsp;my_aiocb;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;fd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;open(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">file.txt</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;O_RDONLY&nbsp;);<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(fd&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">open</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img id=Codehighlighter1_224_271_Open_Image onclick="this.style.display='none'; Codehighlighter1_224_271_Open_Text.style.display='none'; Codehighlighter1_224_271_Closed_Image.style.display='inline'; Codehighlighter1_224_271_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_224_271_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_224_271_Closed_Text.style.display='none'; Codehighlighter1_224_271_Open_Image.style.display='inline'; Codehighlighter1_224_271_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_224_271_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_224_271_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Zero&nbsp;out&nbsp;the&nbsp;aiocb&nbsp;structure&nbsp;(recommended)&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;bzero(&nbsp;(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">my_aiocb,&nbsp;</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;aiocb)&nbsp;);<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img id=Codehighlighter1_328_377_Open_Image onclick="this.style.display='none'; Codehighlighter1_328_377_Open_Text.style.display='none'; Codehighlighter1_328_377_Closed_Image.style.display='inline'; Codehighlighter1_328_377_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_328_377_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_328_377_Closed_Text.style.display='none'; Codehighlighter1_328_377_Open_Image.style.display='inline'; Codehighlighter1_328_377_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_328_377_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_328_377_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Allocate&nbsp;a&nbsp;data&nbsp;buffer&nbsp;for&nbsp;the&nbsp;aiocb&nbsp;request&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;my_aiocb.aio_buf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;malloc(BUFSIZE</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">my_aiocb.aio_buf)&nbsp;perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">malloc</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img id=Codehighlighter1_465_514_Open_Image onclick="this.style.display='none'; Codehighlighter1_465_514_Open_Text.style.display='none'; Codehighlighter1_465_514_Closed_Image.style.display='inline'; Codehighlighter1_465_514_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_465_514_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_465_514_Closed_Text.style.display='none'; Codehighlighter1_465_514_Open_Image.style.display='inline'; Codehighlighter1_465_514_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_465_514_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_465_514_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Initialize&nbsp;the&nbsp;necessary&nbsp;fields&nbsp;in&nbsp;the&nbsp;aiocb&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;my_aiocb.aio_fildes&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;fd;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;my_aiocb.aio_nbytes&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;BUFSIZE;<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;my_aiocb.aio_offset&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;ret&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;aio_read(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">my_aiocb&nbsp;);<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(ret&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">aio_read</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(&nbsp;aio_error(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">my_aiocb&nbsp;)&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;EINPROGRESS&nbsp;)&nbsp;;<br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img id=Codehighlighter1_767_845_Open_Image onclick="this.style.display='none'; Codehighlighter1_767_845_Open_Text.style.display='none'; Codehighlighter1_767_845_Closed_Image.style.display='inline'; Codehighlighter1_767_845_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_767_845_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_767_845_Closed_Text.style.display='none'; Codehighlighter1_767_845_Open_Image.style.display='inline'; Codehighlighter1_767_845_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;((ret&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;aio_return(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">my_iocb&nbsp;))&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_767_845_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_767_845_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;my_aiocb.aio_buf);<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img id=Codehighlighter1_811_841_Open_Image onclick="this.style.display='none'; Codehighlighter1_811_841_Open_Text.style.display='none'; Codehighlighter1_811_841_Closed_Image.style.display='inline'; Codehighlighter1_811_841_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_811_841_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_811_841_Closed_Text.style.display='none'; Codehighlighter1_811_841_Open_Image.style.display='inline'; Codehighlighter1_811_841_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_811_841_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_811_841_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;got&nbsp;ret&nbsp;bytes&nbsp;on&nbsp;the&nbsp;read&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img id=Codehighlighter1_852_893_Open_Image onclick="this.style.display='none'; Codehighlighter1_852_893_Open_Text.style.display='none'; Codehighlighter1_852_893_Closed_Image.style.display='inline'; Codehighlighter1_852_893_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_852_893_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_852_893_Closed_Text.style.display='none'; Codehighlighter1_852_893_Open_Image.style.display='inline'; Codehighlighter1_852_893_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_852_893_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_852_893_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img id=Codehighlighter1_858_889_Open_Image onclick="this.style.display='none'; Codehighlighter1_858_889_Open_Text.style.display='none'; Codehighlighter1_858_889_Closed_Image.style.display='inline'; Codehighlighter1_858_889_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_858_889_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_858_889_Closed_Text.style.display='none'; Codehighlighter1_858_889_Open_Image.style.display='inline'; Codehighlighter1_858_889_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_858_889_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_858_889_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;read&nbsp;failed,&nbsp;consult&nbsp;errno&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><br>g++ test.cpp -lrt<br><br>
<img src ="http://www.cppblog.com/Bugs/aggbug/54037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-06-19 17:50 <a href="http://www.cppblog.com/Bugs/archive/2008/06/19/54037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>RamDisk好处！</title><link>http://www.cppblog.com/Bugs/archive/2008/06/16/53517.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Mon, 16 Jun 2008 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/06/16/53517.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/53517.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/06/16/53517.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/53517.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/53517.html</trackback:ping><description><![CDATA[<p>如果你有足够大的内存（4G），你可以采用RamDisk这个技术。<br><br>何谓RamDisk，就是内存映射成硬盘，<br>有什么好处呢？<br>访问速度快<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可用于频发存取，大吞吐量磁盘操作<br>掉电后即消失</p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;临时文件<br><br><br>linux下的/tmp就是ramdisk<br><br>windows下需要安装软件，推荐一个（gavotte ramdisk）<br>
<img src ="http://www.cppblog.com/Bugs/aggbug/53517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-06-16 11:37 <a href="http://www.cppblog.com/Bugs/archive/2008/06/16/53517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>配置文件类！</title><link>http://www.cppblog.com/Bugs/archive/2008/05/26/51146.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Mon, 26 May 2008 07:25:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/05/26/51146.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/51146.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/05/26/51146.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/51146.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/51146.html</trackback:ping><description><![CDATA[从台北出差回来，完成了Settings类，参考了词法分析和语言分析。<br><span style="BACKGROUND-COLOR: #c0c0c0">////////////////////////////<br>// file : test.conf<br>a = 1;<br><br>b = 1<br>2<br>3<br>;<br><br>c = hi you;<br><br>d = "hi you" boy 110;<br><br>e = "\\=\\ \"test\"";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;//&nbsp; \=\"test"<br><br>/* end */<br>////////////////////////////</span><br><br>其中：<br>// 和&nbsp;/* */是注释；<br>&nbsp;\\ 转义为\&nbsp;， \*转义为*；<br>每个值空格分隔，如果使用了引号"，则" "之间的就为值；<br>转义符，必须用在""形式的值中；<br>分号;为结束符号。<br><br>载入配置文件：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;Open(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">filename);</span></div>
<br><br>获取指定key的value：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">GetValue(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">key,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;idx</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);</span></div>
<br><br>下面是一个使用demo：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">../src/Common/Settings.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[])<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img id=Codehighlighter1_70_237_Open_Image onclick="this.style.display='none'; Codehighlighter1_70_237_Open_Text.style.display='none'; Codehighlighter1_70_237_Closed_Image.style.display='inline'; Codehighlighter1_70_237_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_70_237_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_70_237_Closed_Text.style.display='none'; Codehighlighter1_70_237_Open_Image.style.display='inline'; Codehighlighter1_70_237_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_70_237_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_70_237_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Settings&nbsp;s;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;s.Open(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test.conf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;)<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img id=Codehighlighter1_114_183_Open_Image onclick="this.style.display='none'; Codehighlighter1_114_183_Open_Text.style.display='none'; Codehighlighter1_114_183_Closed_Image.style.display='inline'; Codehighlighter1_114_183_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_114_183_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_114_183_Closed_Text.style.display='none'; Codehighlighter1_114_183_Open_Image.style.display='inline'; Codehighlighter1_114_183_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_114_183_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_114_183_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOGI(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">load&nbsp;file&nbsp;succed!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOGE(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;&nbsp;s.GetValue(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">)&nbsp;);<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img id=Codehighlighter1_192_224_Open_Image onclick="this.style.display='none'; Codehighlighter1_192_224_Open_Text.style.display='none'; Codehighlighter1_192_224_Closed_Image.style.display='inline'; Codehighlighter1_192_224_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_192_224_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_192_224_Closed_Text.style.display='none'; Codehighlighter1_192_224_Open_Image.style.display='inline'; Codehighlighter1_192_224_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_192_224_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_192_224_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOGE(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">load&nbsp;file&nbsp;failed!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>//<br>代码：<a href="http://code.google.com/p/bugs1111">http://code.google.com/p/bugs1111</a> 里面查找settgings.h settgings.cpp
<img src ="http://www.cppblog.com/Bugs/aggbug/51146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-05-26 15:25 <a href="http://www.cppblog.com/Bugs/archive/2008/05/26/51146.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络编程 心得2</title><link>http://www.cppblog.com/Bugs/archive/2008/04/24/48047.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Thu, 24 Apr 2008 10:33:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/04/24/48047.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/48047.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/04/24/48047.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/48047.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/48047.html</trackback:ping><description><![CDATA[如果客户端必须使用绑定端口，<br>那么在关闭的时候，会经历TIME_WAIT的过程，一般windows下是2分钟，这段时间，客户端connect的时候，会出错(WSAEADDRINUSE:10048)，<br>怎么不经历这个状态呢？<br>使用下面代码：<br><br>&nbsp;&nbsp;// 如果要已经处于连接状态的soket在调用closesocket后强制关闭，不经历TIME_WAIT的过程：<br>&nbsp;&nbsp;BOOL bDontLinger = FALSE;<br>&nbsp;&nbsp;if (setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&amp;bDontLinger,sizeof(BOOL))&lt; 0) {<br>&nbsp;&nbsp;&nbsp;wsaperror("setsockopt");<br>&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;}<br>
<img src ="http://www.cppblog.com/Bugs/aggbug/48047.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-04-24 18:33 <a href="http://www.cppblog.com/Bugs/archive/2008/04/24/48047.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络编程 心得1</title><link>http://www.cppblog.com/Bugs/archive/2008/04/08/46509.html</link><dc:creator>Bugs</dc:creator><author>Bugs</author><pubDate>Tue, 08 Apr 2008 06:43:00 GMT</pubDate><guid>http://www.cppblog.com/Bugs/archive/2008/04/08/46509.html</guid><wfw:comment>http://www.cppblog.com/Bugs/comments/46509.html</wfw:comment><comments>http://www.cppblog.com/Bugs/archive/2008/04/08/46509.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/Bugs/comments/commentRss/46509.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Bugs/services/trackbacks/46509.html</trackback:ping><description><![CDATA[<span><br><br>以前项目里发现一个这样的问题，当网络服务进程关掉的时候，在立即启动该服务，会有错误提示说port被占用了，监听失败。<br><br>最近在看《unix 网络编程》，在里面了解到了 链接时的三次握手 和 关闭时的四次握手，<br>在关闭时最后会有一个TIME_WAIT状态，这个状态时间是TCP里最长的，是二倍MSL时间，大约在1-4分钟。<br>至于为什么要保留这个状态和这么长的时间，请参考《unix 网络编程》第二章 2.7.<br><br>但这样的问题是可以解决的，使用<span>SO_REUSEADDR&nbsp;&nbsp;&nbsp; enables local address reuse，可以在TIME_WAIT状态下使用相同的PORT。</span><br><br>int reuser_addr = 1;<br>&nbsp;::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void*)&amp;reuse_addr, sizeof(reuse_addr));<br><br><span>SO_REUSEADDR&nbsp;的用途除了上面这种情况，还有三种分别是：<br>*)在多网卡的时候，多进程可以使用不同IP，相同PORT。<br>*)与上条差不多，在单进程使用使用不同IP，相同PORT。<br>*)在UDP广播的时候，可以在相同IP和PORT下使用，TCP则不行。</span></span>
<img src ="http://www.cppblog.com/Bugs/aggbug/46509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Bugs/" target="_blank">Bugs</a> 2008-04-08 14:43 <a href="http://www.cppblog.com/Bugs/archive/2008/04/08/46509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>