﻿<?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++博客-网络服务器软件开发/中间件开发，关注ACE/TAO/ICE-随笔分类-ACE</title><link>http://www.cppblog.com/true/category/3800.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 12 Jan 2011 18:03:53 GMT</lastBuildDate><pubDate>Wed, 12 Jan 2011 18:03:53 GMT</pubDate><ttl>60</ttl><item><title>Buffer类就应该简单，直观</title><link>http://www.cppblog.com/true/archive/2011/01/13/138422.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Wed, 12 Jan 2011 16:51:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2011/01/13/138422.html</guid><wfw:comment>http://www.cppblog.com/true/comments/138422.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2011/01/13/138422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/138422.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/138422.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最近几天一直在思考一个问题：我们需要什么样的网络基础开发包？libevent，asio，ace，还是自己封装？Buffer类，内存池&nbsp;&nbsp;<a href='http://www.cppblog.com/true/archive/2011/01/13/138422.html'>阅读全文</a><img src ="http://www.cppblog.com/true/aggbug/138422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2011-01-13 00:51 <a href="http://www.cppblog.com/true/archive/2011/01/13/138422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE中简易的序列化机制：ACE_OutputCDR/ACE_InputCDR</title><link>http://www.cppblog.com/true/archive/2010/12/26/137484.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Sun, 26 Dec 2010 01:52:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2010/12/26/137484.html</guid><wfw:comment>http://www.cppblog.com/true/comments/137484.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2010/12/26/137484.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/137484.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/137484.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CDR可以提供对基本数据类型如int，short，double，string等的序列化机制，简单包装后即可担当RPC中的序列化角色。<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ace</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">OS.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ace</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">String_Base.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ace</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">CDR_Stream.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#pragma&nbsp;comment(lib,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">aced</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></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">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_198_1238_Open_Image onclick="this.style.display='none'; Codehighlighter1_198_1238_Open_Text.style.display='none'; Codehighlighter1_198_1238_Closed_Image.style.display='inline'; Codehighlighter1_198_1238_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_198_1238_Closed_Image onclick="this.style.display='none'; Codehighlighter1_198_1238_Closed_Text.style.display='none'; Codehighlighter1_198_1238_Open_Image.style.display='inline'; Codehighlighter1_198_1238_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_198_1238_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_198_1238_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ACE&nbsp;CDR&nbsp;demo</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_CString&nbsp;sAppName&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">CDRDemo</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,sAppName2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_CDR::Long&nbsp;nUID&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">123456</span><span style="COLOR: #000000">,nUID2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_CDR::Float&nbsp;nfPosX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">120.51</span><span style="COLOR: #000000">,nfPosX2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_CDR::Double&nbsp;ndScore&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">120.51</span><span style="COLOR: #000000">,ndScore2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_CString&nbsp;sDummy&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">another&nbsp;string</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,sDummy2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_CDR::Short&nbsp;&nbsp;nsLength&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,nsLength2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_OutputCDR&nbsp;outCDR(ACE_DEFAULT_CDR_BUFSIZE);&nbsp;&nbsp;&nbsp;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;outCDR&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;nUID;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;outCDR&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;nfPosX;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;outCDR&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;ndScore;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;outCDR&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;sAppName;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">写字符串时，先写入字符串的长度</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;outCDR&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;sDummy;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;outCDR&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;nsLength;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">OutputCDR&nbsp;size&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;outCDR.length()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">可以通过socket发送出去,而在服务端进行下面的解析<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">1.ACE_Message_Block&nbsp;*ACE_OutputCDR::begin&nbsp;(void)<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">2.通过ACE_SOCK_Stream发送出去&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_InputCDR&nbsp;inCDR(outCDR);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;inCDR&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;nUID2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;inCDR&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;nfPosX2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;inCDR&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;ndScore2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;inCDR&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;sAppName2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;inCDR&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;sDummy2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;inCDR&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;nsLength2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_ASSERT(nUID&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;nUID2);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_ASSERT(nfPosX&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;nfPosX2);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_ASSERT(ndScore&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;ndScore2);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_ASSERT(sAppName&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;sAppName2);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_ASSERT(sDummy&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;sDummy2);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;ACE_ASSERT(nsLength&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;nsLength2);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test&nbsp;ok.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&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><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span></div>
<br>假若有如下的demo.idl,内容如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct user_info<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int user_id;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string user_name;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>利用idl_gen生成代码时：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)如果是侵入式的方案，则生成user_info类时，自动添加成员OutputCDR和InputCDR成员，并添加pack(ACE_Message_Block &amp;* msg)和parse(ACE_Message_Block * msg)成员函数，在pack和parse里面，调到对于的CDR类，按照类中数据成员的声明顺序依次序列化，反序列化<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)如果是非侵入式方案，则生成user_info类时，生成独立函数的pack(user_info&amp; info, ACE_Message_Block &amp;* msg)和parse(user_info&amp; info,ACE_Message_Block * msg),pack和parse的函数实现同上<br>
<img src ="http://www.cppblog.com/true/aggbug/137484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2010-12-26 09:52 <a href="http://www.cppblog.com/true/archive/2010/12/26/137484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE_Get_Opt解析命令行参数</title><link>http://www.cppblog.com/true/archive/2010/11/09/133131.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Tue, 09 Nov 2010 15:53:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2010/11/09/133131.html</guid><wfw:comment>http://www.cppblog.com/true/comments/133131.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2010/11/09/133131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/133131.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/133131.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ACE ACE_Get_Opt 命令行&nbsp;&nbsp;<a href='http://www.cppblog.com/true/archive/2010/11/09/133131.html'>阅读全文</a><img src ="http://www.cppblog.com/true/aggbug/133131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2010-11-09 23:53 <a href="http://www.cppblog.com/true/archive/2010/11/09/133131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE_Thread_Mutex一个不跨平台的地方</title><link>http://www.cppblog.com/true/archive/2010/10/23/131009.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Sat, 23 Oct 2010 13:44:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2010/10/23/131009.html</guid><wfw:comment>http://www.cppblog.com/true/comments/131009.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2010/10/23/131009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/131009.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/131009.html</trackback:ping><description><![CDATA[<p>ACE_Thread_Mutex的成员， int acquire (ACE_Time_Value *tv);在windows下是不支持的，有些出人意料，之前一直没用过这个参数，今天造轮子，参考ace发现的。</p>
<img src ="http://www.cppblog.com/true/aggbug/131009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2010-10-23 21:44 <a href="http://www.cppblog.com/true/archive/2010/10/23/131009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>仿照system v消息队列的内存消息队列</title><link>http://www.cppblog.com/true/archive/2010/09/19/127031.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Sat, 18 Sep 2010 17:01:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2010/09/19/127031.html</guid><wfw:comment>http://www.cppblog.com/true/comments/127031.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2010/09/19/127031.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/127031.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/127031.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 内存消息队列是服务器端常用的基础组件，他使得符合生产者-消费者模型的两个线程或两组线程之间的通讯看起来更加清晰&nbsp;&nbsp;<a href='http://www.cppblog.com/true/archive/2010/09/19/127031.html'>阅读全文</a><img src ="http://www.cppblog.com/true/aggbug/127031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2010-09-19 01:01 <a href="http://www.cppblog.com/true/archive/2010/09/19/127031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ace中常用类的使用举例（不断补充）</title><link>http://www.cppblog.com/true/archive/2008/04/13/46983.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Sun, 13 Apr 2008 08:32:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2008/04/13/46983.html</guid><wfw:comment>http://www.cppblog.com/true/comments/46983.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2008/04/13/46983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/46983.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/46983.html</trackback:ping><description><![CDATA[<p>#include "ace/Task.h"<br>#include &lt;ace/Manual_Event.h&gt;<br>#include &lt;ace/Auto_Event.h&gt;<br>#include "ace/OS.h"<br>#include &lt;ace/Date_Time.h&gt;<br>#include &lt;iostream&gt;</p>
<p>using namespace std;<br>#pragma comment(lib,"aced")</p>
<p>/**<br>* if MANUAL reset<br>*&nbsp;&nbsp;&nbsp; sleep till the event becomes signaled<br>*&nbsp;&nbsp;&nbsp; event remains signaled after wait() completes.<br>* else AUTO reset<br>*&nbsp;&nbsp;&nbsp; sleep till the event becomes signaled<br>*&nbsp;&nbsp;&nbsp; event resets wait() completes.<br>*/<br>//ACE_Manual_Event mevent;<br>ACE_Auto_Event&nbsp;&nbsp; auto_event;<br>class TaskTest : public ACE_Task_Base<br>{<br>public:<br>&nbsp;int svc()<br>&nbsp;{<br>&nbsp;&nbsp;cout &lt;&lt; "task base test" &lt;&lt; endl;<br>&nbsp;&nbsp;ACE_Date_Time dt;<br>&nbsp;&nbsp;cout &lt;&lt; "y = " &lt;&lt; dt.year() &lt;&lt; endl;<br>&nbsp;&nbsp;cout &lt;&lt; "m = " &lt;&lt; dt.month() &lt;&lt; endl;<br>&nbsp;&nbsp;cout &lt;&lt; "s = " &lt;&lt; dt.second() &lt;&lt; endl;<br>&nbsp;&nbsp;ACE_OS::sleep(2);<br>&nbsp;&nbsp;//mevent.signal();<br>&nbsp;&nbsp;auto_event.signal();<br>&nbsp;&nbsp;return 0;<br>&nbsp;}<br>protected:<br>private:<br>};<br>int main(int argc, char* argv[])<br>{<br>&nbsp;TaskTest tt;<br>&nbsp;tt.activate();<br>&nbsp;//mevent.wait();<br>&nbsp;auto_event.wait();<br>&nbsp;tt.wait();<br>&nbsp;return 0;<br>}<br></p>
<img src ="http://www.cppblog.com/true/aggbug/46983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2008-04-13 16:32 <a href="http://www.cppblog.com/true/archive/2008/04/13/46983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE在Linux环境下的编译安装[转]</title><link>http://www.cppblog.com/true/archive/2007/07/15/28065.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Sun, 15 Jul 2007 05:06:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2007/07/15/28065.html</guid><wfw:comment>http://www.cppblog.com/true/comments/28065.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2007/07/15/28065.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/28065.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/28065.html</trackback:ping><description><![CDATA[ACE在Linux环境下的编译安装<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Author by Jet Yan in April 4,2005]<br><br>第一步 设置ACE_ROOT环境变量<br>（1）export ACE_ROOT=/home/jet/ACE_wrappers<br>export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH<br><br>（2）或者直接在用户目录下编辑.bashrc文件，内容如下：<br>ACE_ROOT=/home/jet/ACE_wrappers<br>export ACE_ROOT<br>LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH<br>export LD_LIBRARY_PATH<br>然后重新登陆<br><br>（3）另一种方法是修改系统的/etc/profile文件（不过这样还是以用户变量为<br>优先设置，即如果已经按照上面的两种方法进行了设置，那么以下的设置将不<br>会被系统采用。）<br>&#8220;vi /etc/profile&#8221;<br>在其中加入4行<br>ACE_ROOT=/opt/ACE<br>export ACE_ROOT<br>LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH<br>export LD_LIBRARY_PATH<br>我是加在&#8220;export PATH USER&#8230;.&#8221;后的。完成后将/etc/profile执行一次，命令：<br>&#8220;chmod 555 /etc/profile&#8221;<br>&#8220;/etc/profile&#8221;<br>这样我们的ACE_ROOT就设置好了，可以用如下命令查看ACE_ROOT是否设置好了：<br>&#8220;echo $ACE_ROOT&#8221;<br>这个时候最好reboot启动一次linux。<br>-------------------------------------------------------------------<br><br>第二步 解压出ACE-install.sh文件并修改<br>（1）在/home/jet下建立子目录ACEInstall，将ACE.tar.gz上传至该目录<br><br>（2）从ACE.tar.gz解压出单个文件ACE-install.sh：<br>tar &#8211;zxvf ACE.tar.gz ACE_wrappers/ACE-install.sh<br><br>（3）ACE-install.sh放在哪个目录下无所谓，因为安装目录是由刚才设定的$ACE_ROOT决定的。<br><br>（4）vi ACE-install.sh <br>我们可以看到缺省的，这个文件是用来在UNIX下做安装的。所以我们要将其中的有<br>关UNIX的部分换成linux即可。<br>&#8220;MY_ACEDIR=${HOME}/aceconfig&#8221; --&gt;&gt; &#8220;MY_ACEDIR=/home/my/ACE&#8221;<br>&#8220;MY_ACE_CONFIG=config-sunos5.4-sunc++-4.x.h&#8221; --&gt;&gt; &#8220;MY_ACE_CONFIG=config-linux.h&#8221;<br>&#8220;MY_ACE_GNU_MACROS=platform_sunos5_sunc++.GNU&#8221; --&gt;&gt; &#8220;MY_ACE_GNU_MACROS=platform_linux.GNU&#8221;<br>好了，文件修改完毕，保存退出&#8220;:wq&#8221;。<br>-------------------------------------------------------------------<br><br>第三步 运行ACE-install.sh（shell脚本）安装ACE<br>（1）当前目录/home/jet/ACEInstall/ACE_wrappers<br><br>（2）修改ACE-install.sh的属性，使其可执行<br>chmod 777 ACE-install.sh<br><br>（3）执行：<br>./ACE-install.sh<br>此后将是较长时间的解包、编译等待时间。这个过程将不会出现任何错误，因为安装脚本<br>将为我们做很多事情，如：生成config.h，生成platform_macros.GNU。（即使出现删除<br>文件的错误，对结果应该没有影响，遇到这种情况要具体分析一下。）<br>因此就不需要按ACE-install.html中说的那样手工做如下改动：<br>&nbsp; 在$ACE_ROOT/ace目录下:<br>&nbsp; ln -s config-linux.h config.h<br>&nbsp; 在$ACE_ROOT/include/makeinclude/目录下:<br>&nbsp; ln -s platform_linux.GNU platform_macros.GNU<br>（Windows中没有文件连接这一说，所以要自己生成一个config.h文件，再在它的里面加一<br>句话&#8220;#include "ace/config-win32.h"&#8221;。）<br><br>（4）如果编译中出现错误，如&#8220;../apps/gperf&#8221;等，请编辑$ACE_ROOT/apps下的Makefile，<br>将其中的有关&#8220;gperf&#8221;的部分注释掉，这个东西只是一个例子，可以不去编译它。<br>强调一下，用ACE-install.sh来安装，会编译ACE、tests、apps等。<br>最后会生成libACE.so及tests、apps下也会出来很多经过编译的文件。<br>当然如果你只是下载了ACE.tar.gz这样的单个包来安装，你可以手工改文件，再make，<br>因为只编译ACE，工作就少了很多，手工做还可以接受。<br><br>（5）编译过程日志放在/tmp/myacemaker.err<br>-------------------------------------------------------------------<br><br>第四步 直接测试ACE提供的例子<br>（1）在$ACE_ROOT/examples/Synch中，修改proc_sema.cpp文件如下：<br>#include "ace/OS_NS_stdio.h"<br>在main函数中<br>ACE_OS::printf("Hello,World! \n");<br><br>（2）执行make，OK后运行。<br><br>（3）如果运行时装在不到share object，可能是lib路径问题，因为.so文件是程序运行过程中<br>装载的，不是在编译的时候，因此要设置LD_LIBRARY_PATH：<br>[jet@S]$ export LD_LIBRARY_PATH=/home/jet/ACE_wrappers/lib:$LD_LIBRARY_PATH<br>-------------------------------------------------------------------<br><br>第五步 写一个简单的程序测试一下ACE<br>（1）在/home/jet/下新建ACETest子目录，写好程序如client.cpp，上传到该目录<br><br>（2）拷贝第四步的那个Makefile文件到该目录，并做如下修改<br>修改其中输出文件名&#8220;BIN = hello&#8221;，并修改&#8220;<br>.obj/proc_sema.o .obj/proc_sema.so .shobj/proc_sema.o .shobj/proc_sema.so: proc_sema.cpp \&#8221;<br>中后面的&#8220;proc_sema.cpp&#8221;成&#8220;client.cpp&#8221;。<br>好，我们可以编译一个我们自己的ACE程序了，make即可。应该能通过，生成执行文件client，<br>大小大约为112Kb。运行之，&#8220;./client&#8221;。<br>-------------------------------------------------------------------<br><br>=================================================<br>另一种更为直接的安装方法：<br><br>步骤1：设置环境变量<br>export ACE_ROOT=/home/jet/ACE_wrappers<br>export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH<br>也可以直接修改.bashrc文件，以免退出后设置的这些变量消失<br><br>[env][echo $ACE_ROOT]<br><br>步骤2：<br>针对不同版本创建两个文件链接:<br>&nbsp; 在$ACE_ROOT/ace目录下:<br>&nbsp; ln -s config-linux.h config.h<br>&nbsp; 在$ACE_ROOT/include/makeinclude/目录下:<br>&nbsp; ln -s platform_linux.GNU platform_macros.GNU<br><br>步骤3：<br>在$ACE_ROOT目录下，新建一个目录，用以执行configure的结果<br>&nbsp; mkdir aaa<br>&nbsp; cd aaa<br>在$ACE_ROOT/aaa中运行<br>&nbsp; ../configure<br>在确认结果无误后，执行 <br>&nbsp; make<br>OK！<br><br><br><br>[rm -f -r *]删除目录下所有的文件和子目录-f是强制force删除，-r是代表目录也删除<br><br>[ldd 可执行文件] 显示该文件运行时候需要的动态链接库<br><br>[ipcs] 显示系统的共享内存、信号量、消息队列的情况 ipc show<br>[ipcrm &lt;shm| msg| sem&gt; id]<br><br>
<img src ="http://www.cppblog.com/true/aggbug/28065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2007-07-15 13:06 <a href="http://www.cppblog.com/true/archive/2007/07/15/28065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE关于文件的操作</title><link>http://www.cppblog.com/true/archive/2007/06/09/25911.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Sat, 09 Jun 2007 10:30:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2007/06/09/25911.html</guid><wfw:comment>http://www.cppblog.com/true/comments/25911.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2007/06/09/25911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/25911.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/25911.html</trackback:ping><description><![CDATA[&nbsp;ACE_FILE_Addr file_addr;<br>&nbsp;file_addr.set("log.txt");<br>&nbsp;ACE_FILE_IO file;<br>&nbsp;ACE_FILE_Connector file_connector;<br>&nbsp;if (file_connector.connect(file,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file_addr,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_Addr::sap_any,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;O_RDWR|O_CREAT|O_APPEND<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) == -1)<br>&nbsp;{<br>&nbsp;&nbsp;cout &lt;&lt; "error" &lt;&lt; endl;<br>&nbsp;}
<img src ="http://www.cppblog.com/true/aggbug/25911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2007-06-09 18:30 <a href="http://www.cppblog.com/true/archive/2007/06/09/25911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE_NT_Service（WINDOWS</title><link>http://www.cppblog.com/true/archive/2007/04/24/22741.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Tue, 24 Apr 2007 09:55:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2007/04/24/22741.html</guid><wfw:comment>http://www.cppblog.com/true/comments/22741.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2007/04/24/22741.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/22741.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/22741.html</trackback:ping><description><![CDATA[<p><strong><font style="BACKGROUND-COLOR: #ffff66">ACE_NT_Service</font></strong>（WINDOWS）<br>本人的观点，SERVICE就是WINDOWS版的DAEMON。<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>通过包装一整套WINDOWS提供的SERVICE API定义了一个控制NT SERVICE的接口。应用程序继承该接口就可以实现和UNIX上DAEMON相似的功能。下面先简单描述WINDOWSSERVICE程序框架，再详细描述类<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>对WINDOWS SERVICE程序框架的包装。<br><br>WINDOWS SERVICE<br>一个完整的NT SERVICE程序应该包含以下四部分：<br>1.控制台应用程序的main函数<br>2.SERVICE入口函数ServiceMain<br>3.SERVICE CONTROL HANDLER，SCM利用该函数和SERVICE通信并控制程序的起停。<br>4.SERVICE安装和卸载器<br><br>ServiceMain和Service Control Handler<br>首先我们来讨论ServiceMain和Service Control Handler。WINDOWS规定每个SERVICE都拥有自己独立的ServiceMain以及Service Control Handler函数。主程序调用StartServiceCtrlDispatcher时，WINDOWS为每个SERVICE创建一个线程，并且在新线程中运行ServiceMain函数。SCM利用Service Control Handler函数和SERVICE程序通信，用户执行start，stop，pause以及continue等操作时，SCM通过Service Control Handler函数来控制SERVICE的行为。Service Control Handler函数基本上会包含一个switch语句来处理每种情况。<br><br>安装/卸载SERVICE<br>WINDOWS提供一些API来安装/卸载SERVICE，这样我们就可以不使用注册函数就能在系统中注册这些节点。这些API分别是CreateService和DeleteService。要安装SERVICE，需要先利用函数OpenSCManager打开SCM数据库，接着利用SERVICE的二进制文件路径调用CreateService，在调用CreateService时需要为SERVICE指定名称，原因是使用DeleteService删除服务时需要利用该标识。<br><br><strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong><br>查看ACE源码，其中和类 <strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>实现密切相关的的文件有NT_Service.cpp、NT_Service.h、NT_Service.i。<br><br><strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>中的ServiceMain和Service Control Handler<br>ServiceMain和Service Control Handler定义具有固定模式，<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>提供宏#define <strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_SERVICE</strong>_DEFINE(SVCNAME, SVCCLASS, SVCDESC)用于简化定义。具体的宏定义可以参考ACE代码，这里不再列出，这里只分析相关的类<strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>的成员函数handle_control,init,open,wait和fini。函数handle_control被用于响应SERVICE DISPATCHER请求,其必须和SVC函数交互以影响请求控制操作。缺省实现包括SERVICE_CONTROL_STOP，SERVICE_CONTROL_PAUSE，SERVICE_CONTROL_CONTINUE，SERVICE_CONTROL_INTERROGATE，SERVICE_CONTROL_SHUTDOWN。<br><br>函数handle_control的部分关键代码解析<br>/* 调用stop_requested响应关闭操作 */<br>case SERVICE_CONTROL_SHUTDOWN:<br>case SERVICE_CONTROL_STOP:<br>this-&gt;stop_requested (control_code);<br>break;<br>/* 调用pause_requested响应挂起操作 */<br>case SERVICE_CONTROL_PAUSE:<br>this-&gt;pause_requested (control_code);<br>break;<br>/* 调用continue_requested响应挂起后启动操作 */<br>case SERVICE_CONTROL_CONTINUE:<br>this-&gt;continue_requested (control_code);<br>break;<br>/* 调用interrogate_requested报告当前状态*/<br>case SERVICE_CONTROL_INTERROGATE:<br>this-&gt;interrogate_requested (control_code);<br>break;<br><br>函数open 的部分关键代码解析<br>/* 报告状态 */<br>this-&gt;report_status (SERVICE_START_PENDING, 0);<br>/* 执行用户代码 */<br>int svc_return = this-&gt;svc ();<br><br>函数fini 的部分关键代码解析<br>/* 报告状态 */<br>return this-&gt;report_status (SERVICE_STOPPED, 0);<br><br>函数stop_requested的部分关键代码解析<br>/* 报告状态 */<br>this-&gt;report_status (SERVICE_STOP_PENDING);<br><br>函数pause_requested的部分关键代码解析<br>/* 报告状态 */<br>this-&gt;report_status (SERVICE_PAUSE_PENDING);<br>/* 挂起*/<br>this-&gt;suspend ();<br>/* 报告状态 */<br>this-&gt;report_status (SERVICE_PAUSED);<br><br>函数continue_requested的部分关键代码解析<br>/* 报告状态 */<br>this-&gt;report_status (SERVICE_CONTINUE_PENDING);<br>/* 恢复*/<br>this-&gt;resume ();<br>/* 报告状态 */<br>this-&gt;report_status (SERVICE_RUNNING);<br><br>函数interrogate_requested的部分关键代码解析<br>/* 报告状态 */<br>this-&gt;report_status (0);<br>安装/卸载SERVICE<br><strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>定义两个成员函数Insert，remove来安装（卸载）SERVICE。它们分别在内部调用WINDOWS API——CreateService以及DeleteService。 <br><br>Insert函数的部分关键代码解析<br><br>/* 打开和host()上SCManager的通信 */<br>SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this-&gt;host ()，&#8230;&#8230;);<br>/* 以名称name() 创建服务 */<br>SC_HANDLE sh = ACE_TEXT_CreateService (sc_mgr,this-&gt;name (),this-&gt;desc (),<br>SERVICE_ALL_ACCESS,this-&gt;svc_status_.dwServiceType,start_type,<br>error_control,exe_path,&#8230;&#8230;);<br>/* 关闭和SCManager的通信 */<br>CloseServiceHandle (sc_mgr);<br>/* 关闭服务句柄，重新写入新句柄 */<br>if (this-&gt;svc_sc_handle_ != 0)<br>CloseServiceHandle (this-&gt;svc_sc_handle_);<br>this-&gt;svc_sc_handle_ = sh;<br><br>Remove函数部分关键代码解析<br><br>/* 从SCM中删除insert创建的服务句柄 */<br>if (DeleteService (this-&gt;svc_sc_handle()) == 0<br>&amp;&amp; GetLastError () != ERROR_SERVICE_MARKED_FOR_DELETE)<br>控制SERVICE<br><strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">ACE_NT_Service</strong>定义成员函数start_svc, stop_svc, pause_svc, continue_svc分别用于启动、停止、挂起和继续服务。<br>start_svc函数的部分关键代码解析<br><br>/* 启动服务 */<br>if (!ACE_TEXT_StartService (svc, argc, argv))<br>this-&gt;wait_for_service_state (SERVICE_RUNNING, wait_time);<br><br>stop_svc函数的部分关键代码解析<br><br>/* 关闭服务 */<br>if (!ControlService (svc, SERVICE_CONTROL_STOP, &amp;this-&gt;svc_status_))<br>this-&gt;wait_for_service_state (SERVICE_STOPPED, wait_time);<br><br>pause_svc函数的部分关键代码解析<br><br>/* 吊起服务 */<br>if (!ControlService (svc, SERVICE_CONTROL_PAUSE,&amp;this-&gt;svc_status_))<br>this-&gt;wait_for_service_state (SERVICE_PAUSED,wait_time);<br><br>continue_svc函数的部分关键代码解析<br><br>/* 将挂起业务重新启动 */<br>if (!ControlService (svc,SERVICE_CONTROL_CONTINUE,&amp;this-&gt;svc_status_))<br>this-&gt;wait_for_service_state (SERVICE_RUNNING,wait_time);<br><br>一些辅助函数<br>svc_sc_handle部份关键代码解析<br><br>/* 打开SCM */<br>SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this-&gt;host (),&#8230;&#8230;)<br>if (sc_mgr != 0)<br>{<br>/* 获取服务句柄 */<br>this-&gt;svc_sc_handle_ = ACE_TEXT_OpenService (sc_mgr,&#8230;&#8230;)<br>/* 关闭SCM */<br>CloseServiceHandle (sc_mgr);<br>}<br>/* 返回获取到的服务句柄 */<br>return this-&gt;svc_sc_handle_;<br><br>wait_for_service_state部份关键代码解析<br><br>/* 获取当前时间 */<br>ACE_Time_Value time_out = ACE_OS::gettimeofday ();<br>/* 加上等待时间 */<br>if (wait_time != 0) time_out += *wait_time;<br>// Poll until the service reaches the desired state.<br>for (;<img alt="" src="http://www.huihoo.org/forum/images/smilies/wink.gif" border=0 twffan="done"> <br>{<br>/* 查询当前状态 */<br>service_ok = 0 != QueryServiceStatus (this-&gt;svc_sc_handle_, &amp;this-&gt;svc_status_);<br>/* 如果已经到达指定状态，退出循环 */<br>if (desired_state == this-&gt;svc_status_.dwCurrentState) break;<br>/* 如果超出指定时间，退出循环 */<br>if (wait_time != 0 &amp;&amp; ACE_OS::gettimeofday () &gt; time_out )<br>{ &#8230;&#8230;<br>break;<br>}<br>/* 睡眠等待 */<br>::Sleep (this-&gt;svc_status_.dwWaitHint);<br>}<br><br>report_status部份关键代码解析<br>/* 告诉系统服务新的状态 */<br>SetServiceStatus (this-&gt;svc_handle_,&amp;this-&gt;svc_status_) ? 0 : -1;<br></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<br><br>
<p id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=748930</p>
<img src ="http://www.cppblog.com/true/aggbug/22741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2007-04-24 17:55 <a href="http://www.cppblog.com/true/archive/2007/04/24/22741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C10k[转]</title><link>http://www.cppblog.com/true/archive/2007/04/05/21283.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Thu, 05 Apr 2007 01:00:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2007/04/05/21283.html</guid><wfw:comment>http://www.cppblog.com/true/comments/21283.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2007/04/05/21283.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/21283.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/21283.html</trackback:ping><description><![CDATA[<div class=postText twffan="done">摘要 <br><br><br>编写连接数巨大的高负载服务器程序时，经典的多线程模式和select模式都不再适用。 <br>应当抛弃它们，采用epoll/kqueue/dev_poll来捕获I/O事件。最后简要介绍了AIO。 <br><br><br>由来 <br><br><br>网络服务在处理数以万计的客户端连接时，往往出现效率低下甚至完全瘫痪，这被称为 <br>C10K问题。随着互联网的迅速发展，越来越多的网络服务开始面临C10K问题，作为大型 <br>网站的开发人员有必要对C10K问题有一定的了解。本文的主要参考文献是 <br>&lt;<a href="http://www.kegel.com/c10k.html" target=_blank><u><font color=#800080>http://www.kegel.com/c10k.html</font></u></a>&gt;&nbsp;<a href="http://www.kegel.com/c10k.htmls" target=_blank><u><font color=#0000ff>http://www.kegel.com/c10k.htmls</font></u></a>。 <br><br>C10K问题的最大特点是：设计不够良好的程序，其性能和连接数及机器性能的关系往往 <br>是非线性的。举个例子：如果没有考虑过C10K问题，一个经典的基于select的程序能在 <br>旧服务器上很好处理1000并发的吞吐量，它在2倍性能新服务器上往往处理不了并发 <br>2000的吞吐量。 <br><br>这是因为在策略不当时，大量操作的消耗和当前连接数n成线性相关。会导致单个任务 <br>的资源消耗和当前连接数的关系会是O(n)。而服务程序需要同时对数以万计的socket进 <br>行I/O处理，积累下来的资源消耗会相当可观，这显然会导致系统吞吐量不能和机器性 <br>能匹配。为解决这个问题，必须改变对连接提供服务的策略。 <br><br><br>基本策略 <br><br><br>主要有两方面的策略：1.应用软件以何种方式和操作系统合作，获取I/O事件并调度多 <br>个socket上的I/O操作；2.&nbsp;应用软件以何种方式处理任务和线程/进程的关系。前者主 <br>要有阻塞I/O、非阻塞I/O、异步I/O这3种方案，后者主要有每任务1进程、每任务1线 <br>程、单线程、多任务共享线程池以及一些更复杂的变种方案。常用的经典策略如下： <br><br>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serve&nbsp;one&nbsp;client&nbsp;with&nbsp;each&nbsp;thread/process,&nbsp;and&nbsp;use&nbsp;blocking&nbsp;I/O <br>这是小程序和java常用的策略，对于交互式的长连接应用也是常见的选择(比如BBS)。 <br>这种策略很能难足高性能程序的需求，好处是实现极其简单，容易嵌入复杂的交互逻 <br>辑。Apache、ftpd等都是这种工作模式。 <br><br>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serve&nbsp;many&nbsp;clients&nbsp;with&nbsp;single&nbsp;thread,&nbsp;and&nbsp;use&nbsp;nonblocking&nbsp;I/O <br>and&nbsp;readiness&nbsp;notification <br>这是经典模型，datapipe等程序都是如此实现的。优点在于实现较简单，方便移植，也 <br>能提供足够的性能；缺点在于无法充分利用多CPU的机器。尤其是程序本身没有复杂的 <br>业务逻辑时。 <br><br>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serve&nbsp;many&nbsp;clients&nbsp;with&nbsp;each&nbsp;thread,&nbsp;and&nbsp;use&nbsp;nonblocking&nbsp;I/O&nbsp;and <br>readiness&nbsp;notification <br>对经典模型2的简单改进，缺点是容易在多线程并发上出bug，甚至某些OS不支持多线程 <br>操作readiness&nbsp;notification。 <br><br>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serve&nbsp;many&nbsp;clients&nbsp;with&nbsp;each&nbsp;thread,&nbsp;and&nbsp;use&nbsp;asynchronous&nbsp;I/O <br>在有AI/O支持的OS上，能提供相当高的性能。不过AI/O编程模型和经典模型差别相当 <br>大，基本上很难写出一个框架同时支持AI/O和经典模型，降低了程序的可移植性。在 <br>Windows上，这基本上是唯一的可选方案。 <br><br>本文主要讨论模型2的细节，也就是在模型2下应用软件如何处理Socket&nbsp;I/O。 <br><br><br>select&nbsp;与&nbsp;poll <br><br><br>最原始的同步阻塞&nbsp;I/O&nbsp;模型的典型流程如下： <br><br>同步阻塞&nbsp;I/O&nbsp;模型的典型流程 <br><br>从应用程序的角度来说，read&nbsp;调用会延续很长时间，应用程序需要相当多线程来解决 <br>并发访问问题。同步非阻塞I/O对此有所改进： <br><br>经典的单线程服务器程序结构往往如下： <br><br><br>do&nbsp;{ <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get&nbsp;Readiness&nbsp;Notification&nbsp;of&nbsp;all&nbsp;sockets <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch&nbsp;ready&nbsp;handles&nbsp;to&nbsp;corresponding&nbsp;handlers <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;(readable)&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read&nbsp;the&nbsp;socket <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;(read&nbsp;done) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handler&nbsp;process&nbsp;the&nbsp;request <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(writable) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write&nbsp;response <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(nothing&nbsp;to&nbsp;do) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close&nbsp;socket <br><br>}&nbsp;while(True) <br><br>非阻塞&nbsp;I/O&nbsp;模型的典型流程: <br><br>异步阻塞&nbsp;I/O&nbsp;模型的典型流程 <br><br>其中关键的部分是readiness&nbsp;notification，找出哪一个socket上面发生了I/O事件。 <br>一般从教科书和例子程序中首先学到的是用select来实现。Select定义如下： <br><br><br>int&nbsp;select(int&nbsp;n,&nbsp;fd_set&nbsp;*rd_fds,&nbsp;fd_set&nbsp;*wr_fds,&nbsp;fd_set&nbsp;*ex_fds,&nbsp;struct <br>timeval&nbsp;*timeout); <br><br><strong><font color=#0000ff>Select用到了fd_set结构，从man&nbsp;page里可以知道fd_set能容纳的句柄和FD_SETSIZE相 <br>关。实际上fd_set在*nix下是一个bit标志数组，每个bit表示对应下标的fd是不是在 <br>fd_set中。fd_set只能容纳编号小于&nbsp;FD_SETSIZE的那些句柄。 <br><br>FD_SETSIZE默认是1024，如果向fd_set里放入过大的句柄，数组越界以后程序就会垮 <br>掉。系统默认限制了一个进程最大的句柄号不超过1024，但是可以通过ulimit&nbsp;-n命令 <br>/setrlimit函数来扩大这一限制。如果不幸一个程序在FD_SETSIZE=1024的环境下编 <br>译，运行时又遇到ulimit&nbsp;&#8211;n&nbsp;&gt;&nbsp;1024的，那就只有祈求上帝保佑不会垮掉了。</font></strong> <br><br>在ACE环境中，ACE_Select_Reactor针对这一点特别作了保护措施，但是还是有recv_n <br>这样的函数间接的使用了select，这需要大家注意。 <br><br>针对fd_set的问题，*nix提供了poll函数作为select的一个替代品。Poll的接口如下： <br><br><br>int&nbsp;poll(struct&nbsp;pollfd&nbsp;*ufds,&nbsp;unsigned&nbsp;int&nbsp;nfds,&nbsp;int&nbsp;timeout); <br><br>第1个参数ufds是用户提供的一个pollfd数组，数组大小由用户自行决定，因此避免了 <br>FD_SETSIZE带来的麻烦。Ufds是fd_set的一个完全替代品，从select到poll的移植很方 <br>便。到此为止，至少我们面对C10K，可以写出一个能work的程序了。 <br><br>然而Select和Poll在连接数增加时，性能急剧下降。这有两方面的原因：首先操作系统 <br>面对每次的select/poll操作，都需要重新建立一个当前线程的关心事件列表，并把线 <br>程挂在这个复杂的等待队列上，这是相当耗时的。其次，应用软件在select/poll返回 <br>后也需要对传入的句柄列表做一次扫描来dispatch，这也是很耗时的。这两件事都是和 <br>并发数相关，而I/O事件的密度也和并发数相关，导致CPU占用率和并发数近似成O(n2) <br>的关系。 <br><br><br>epoll,&nbsp;kqueue,&nbsp;/dev/poll <br><br><br>因为以上的原因，*nix的hacker们开发了epoll,&nbsp;kqueue,&nbsp;/dev/poll这3套利器来帮助 <br>大家，让我们跪拜三分钟来感谢这些大神。其中epoll是linux的方案，kqueue是 <br>freebsd的方案，/dev/poll是最古老的Solaris的方案，使用难度依次递增。 <br><br>简单的说，这些api做了两件事：1.避免了每次调用select/poll时kernel分析参数建立 <br>事件等待结构的开销，kernel维护一个长期的事件关注列表，应用程序通过句柄修改这 <br>个列表和捕获I/O事件。2.避免了select/poll返回后，应用程序扫描整个句柄表的开 <br>销，Kernel直接返回具体的事件列表给应用程序。 <br><br>在接触具体api之前，先了解一下边缘触发(edge&nbsp;trigger)和条件触发(level&nbsp;trigger) <br>的概念。边缘触发是指每当状态变化时发生一个io事件，条件触发是只要满足条件就发 <br>生一个io事件。举个读socket的例子，假定经过长时间的沉默后，现在来了100个字 <br>节，这时无论边缘触发和条件触发都会产生一个read&nbsp;ready&nbsp;notification通知应用程 <br>序可读。应用程序读了50个字节，然后重新调用api等待io事件。这时条件触发的api会 <br>因为还有50个字节可读从而立即返回用户一个read&nbsp;ready&nbsp;notification。而边缘触发 <br>的api会因为可读这个状态没有发生变化而陷入长期等待。 <br><br>因此在使用边缘触发的api时，要注意每次都要读到socket返回EWOULDBLOCK为止，否则 <br>这个socket就算废了。而使用条件触发的api时，如果应用程序不需要写就不要关注 <br>socket可写的事件，否则就会无限次的立即返回一个write&nbsp;ready&nbsp;notification。大家 <br>常用的select就是属于条件触发这一类，以前本人就犯过长期关注socket写事件从而 <br>CPU&nbsp;100%的毛病。 <br><br>epoll的相关调用如下： <br><br><br>int&nbsp;epoll_create(int&nbsp;size) <br><br><br>int&nbsp;epoll_ctl(int&nbsp;epfd,&nbsp;int&nbsp;op,&nbsp;int&nbsp;fd,&nbsp;struct&nbsp;epoll_event&nbsp;*event) <br><br><br>int&nbsp;epoll_wait(int&nbsp;epfd,&nbsp;struct&nbsp;epoll_event&nbsp;*&nbsp;events,&nbsp;int&nbsp;maxevents,&nbsp;int <br>timeout) <br><br>epoll_create创建kernel中的关注事件表，相当于创建fd_set。 <br><br>epoll_ctl修改这个表，相当于FD_SET等操作 <br><br>epoll_wait等待I/O事件发生，相当于select/poll函数 <br><br>epoll完全是select/poll的升级版，支持的事件完全一致。并且epoll同时支持边缘触 <br>发和条件触发，一般来讲边缘触发的性能要好一些。这里有个简单的例子： <br><br><br>struct&nbsp;epoll_event&nbsp;ev,&nbsp;*events; <br><br>int&nbsp;kdpfd&nbsp;=&nbsp;epoll_create(100); <br><br>ev.events&nbsp;=&nbsp;EPOLLIN&nbsp;|&nbsp;EPOLLET;&nbsp;&nbsp;//&nbsp;注意这个EPOLLET，指定了边缘触发 <br><br>ev.data.fd&nbsp;=listener; <br><br>epoll_ctl(kdpfd,&nbsp;EPOLL_CTL_ADD,&nbsp;listener,&nbsp;&amp;ev); <br><br>for(;;)&nbsp;{ <br><br>&nbsp;&nbsp;&nbsp;nfds&nbsp;=&nbsp;epoll_wait(kdpfd,&nbsp;events,&nbsp;maxevents,&nbsp;-1); <br><br>&nbsp; <br><br>&nbsp;&nbsp;&nbsp;for(n&nbsp;=&nbsp;0;&nbsp;n&nbsp;&lt;&nbsp;nfds;&nbsp;++n)&nbsp;{ <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(events[n].data.fd&nbsp;==&nbsp;listener)&nbsp;{ <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client&nbsp;=&nbsp;accept(listener,&nbsp;(struct&nbsp;sockaddr&nbsp;*)&nbsp;&amp;local, <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;addrlen); <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(client&nbsp;&lt;&nbsp;0){ <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("accept"); <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setnonblocking(client); <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.events&nbsp;=&nbsp;EPOLLIN&nbsp;|&nbsp;EPOLLET; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ev.data.fd&nbsp;=&nbsp;client; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(epoll_ctl(kdpfd,&nbsp;EPOLL_CTL_ADD,&nbsp;client,&nbsp;&amp;ev)&nbsp;&lt;&nbsp;0)&nbsp;{ <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;"epoll&nbsp;set&nbsp;insertion&nbsp;error:&nbsp;fd=%d0, <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client); <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_use_fd(events[n].data.fd); <br><br>&nbsp;&nbsp;&nbsp;} <br><br>} <br><br>简单介绍一下kqueue和/dev/poll <br><br>kqueue是freebsd的宠儿，kqueue实际上是一个功能相当丰富的kernel事件队列，它不 <br>仅仅是select/poll的升级，而且可以处理signal、目录结构变化、进程等多种事件。 <br>Kqueue是边缘触发的 <br><br>/dev/poll是Solaris的产物，是这一系列高性能API中最早出现的。Kernel提供一个特 <br>殊的设备文件/dev/poll。应用程序打开这个文件得到操纵fd_set的句柄，通过写入 <br>pollfd来修改它，一个特殊ioctl调用用来替换select。由于出现的年代比较早，所以 <br>/dev/poll的接口现在看上去比较笨拙可笑。 <br><br>C++开发：ACE&nbsp;5.5以上版本提供了ACE_Dev_Poll_Reactor封装了epoll和/dev/poll两种 <br>api，需要分别在config.h中定义ACE_HAS_EPOLL和ACE_HAS_DEV_POLL来启用。 <br><br>Java开发：&nbsp;JDK&nbsp;1.6的Selector提供了对epoll的支持，JDK1.4提供了对/dev/poll的支 <br>持。只要选择足够高的JDK版本就行了。 <br><br><br>异步I/O以及Windows <br><br><br>和经典模型不同，异步I/O提供了另一种思路。和传统的同步I/O不同，异步I/O允许进 <br>程发起很多&nbsp;I/O&nbsp;操作，而不用阻塞或等待任何操作完成。稍后或在接收到&nbsp;I/O&nbsp;操作完 <br>成的通知时，进程就可以检索&nbsp;I/O&nbsp;操作的结果。 <br><br>异步非阻塞&nbsp;I/O&nbsp;模型是一种处理与&nbsp;I/O&nbsp;重叠进行的模型。读请求会立即返回，说明 <br>read&nbsp;请求已经成功发起了。在后台完成读操作时，应用程序然后会执行其他处理操 <br>作。当&nbsp;read&nbsp;的响应到达时，就会产生一个信号或执行一个基于线程的回调函数来完成 <br>这次&nbsp;I/O&nbsp;处理过程。异步I/O&nbsp;模型的典型流程： <br><br>异步非阻塞&nbsp;I/O&nbsp;模型的典型流程 <br><br>对于文件操作而言，AIO有一个附带的好处：应用程序将多个细碎的磁盘请求并发的提 <br>交给操作系统后，操作系统有机会对这些请求进行合并和重新排序，这对同步调用而言 <br>是不可能的——除非创建和请求数目同样多的线程。 <br><br>Linux&nbsp;Kernel&nbsp;2.6提供了对AIO的有限支持——仅支持文件系统。libc也许能通过来线 <br>程来模拟socket的AIO，不过这对性能没意义。总的来说Linux的aio还不成熟 <br><br>Windows对AIO的支持很好，有IOCP队列和IPCP回调两种方式，甚至提供了用户级异步调 <br>用APC功能。Windows下AIO是唯一可用的高性能方案，详情请参考MSDN&nbsp;<br><br>
<p id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1537545</p>
<br></div>
<img src ="http://www.cppblog.com/true/aggbug/21283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2007-04-05 09:00 <a href="http://www.cppblog.com/true/archive/2007/04/05/21283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在ACE中使用epoll[zhuan]</title><link>http://www.cppblog.com/true/archive/2007/04/05/21281.html</link><dc:creator>true</dc:creator><author>true</author><pubDate>Thu, 05 Apr 2007 00:32:00 GMT</pubDate><guid>http://www.cppblog.com/true/archive/2007/04/05/21281.html</guid><wfw:comment>http://www.cppblog.com/true/comments/21281.html</wfw:comment><comments>http://www.cppblog.com/true/archive/2007/04/05/21281.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/true/comments/commentRss/21281.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/true/services/trackbacks/21281.html</trackback:ping><description><![CDATA[<div class=tit twffan="done">在ACE中使用epoll</div>
<div class=date twffan="done">2007-01-18 15:56</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt twffan="done">
            <h3><small>星期四,&nbsp;六月&nbsp;8th,&nbsp;2006</small>&nbsp;</h3>
            <div class=entry twffan="done">
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;很显然，文章的标题决定了我们是在linux下使用ACE。我们知道ACE在linux下缺省是用select来实现Reactor的，epoll相对于select的好处这里就不再啰嗦了，我们直接讲操作步骤:<br>&nbsp;&nbsp;&nbsp;&nbsp;第一：重新编译ACE库<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE库中通过ACE_Dev_Poll_Reactor类来支持epoll,但是ACE库缺省的安装是没有编译这个类的，我们要做的就是将ACE_Dev_Poll_Reactor编译连接到ACE库中(faint,又要重新编译ACE，在我那台破服务器上编译一次需要一个多小时).我的操作系统是Redhat&nbsp;linux&nbsp;AS4.0,ACE的版本是5.4.10。根据ACE压缩包中的ACE-INSTALL.html，我是用&#8221;<a name=unix_autoconf></a><strong>Building&nbsp;ACE&nbsp;with&nbsp;GNU&nbsp;Autoconf</strong>&#8220;这种方式来安装的，安装步骤如下(很简单,就不翻译了):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;cd&nbsp;to&nbsp;the&nbsp;top-level&nbsp;ACE_wrappers&nbsp;directory.</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.Create&nbsp;a&nbsp;subdirectory&nbsp;to&nbsp;hold&nbsp;your&nbsp;build&#8217;s&nbsp;configuration&nbsp;and&nbsp;built&nbsp;ACE&nbsp;version,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;&nbsp;&nbsp;then&nbsp;change&nbsp;to&nbsp;the&nbsp;new&nbsp;directory:</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mkdir&nbsp;build</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cd&nbsp;build</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.Note&nbsp;that&nbsp;you&nbsp;do&nbsp;not&nbsp;run&nbsp;the&nbsp;create_ace_build.pl&nbsp;utility&nbsp;mentioned&nbsp;in&nbsp;the&nbsp;Cloning&nbsp;the&nbsp;Source&nbsp;Tree&nbsp;section.&nbsp;The&nbsp;configure&nbsp;script&nbsp;takes&nbsp;care&nbsp;of&nbsp;creating&nbsp;all&nbsp;files&nbsp;and&nbsp;links&nbsp;that&nbsp;are&nbsp;needed.</p>
            <p>Configure&nbsp;ACE&nbsp;for&nbsp;your&nbsp;platform&nbsp;by&nbsp;issuing&nbsp;the&nbsp;following&nbsp;command:&nbsp;c</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;../configure&nbsp;[options]</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.Build&nbsp;ACE&nbsp;by&nbsp;typing&nbsp;make.</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.&nbsp;Install&nbsp;ACE&nbsp;by&nbsp;typing&nbsp;make&nbsp;install.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;好，现在终于可以讲如何将ACE_Dev_Poll_Reactor编译到ACE库中去了。在上述的第一步和第二步之间修改ACE_wrappers/ace/config-linux.h,增加一行：#define&nbsp;ACE_HAS_EVENT_POLL，然后执行第2、3步，第3步../configure执行完之后，build目录下会生成一些文件和目录，打开ACE_wrappers/build/ace/config.h,增加一行：#define&nbsp;ACE_HAS_EVENT_POLL。然后执行第4步make和第5步make&nbsp;install.OK，在漫长的编译以后，支持epoll的ACE库总算完成了。</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第二：修改应用程序<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;应用程序修改很简单，两行代码搞掂,在应用程序初始化时(必须是在第一次使用ACE_Reactor::instance()之间)加入:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pDevPollReactor=new&nbsp;ACE_Dev_Poll_Reactor;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_Reactor::instance(new&nbsp;ACE_Reactor(m_pDevPollReactor));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;那么在后续的对ACE_Reactor::instance()的调用就是使用ACE_Dev_Poll_Reactor的实现了。<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;第三：重新编译应用程序<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在应用程序的makefile中加入&nbsp;-DACE_HAS_EVENT_POLL,重新make应用程序。OK,打完收工。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/true/aggbug/21281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/true/" target="_blank">true</a> 2007-04-05 08:32 <a href="http://www.cppblog.com/true/archive/2007/04/05/21281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>