??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品欧美亚洲韩国日本久久,国产精品va久久久久久久,粉嫩小泬无遮挡久久久久久http://www.shnenglu.com/xushaohua/archive/2009/02/15/73861.htmlneterneterSun, 15 Feb 2009 04:58:00 GMThttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73861.htmlhttp://www.shnenglu.com/xushaohua/comments/73861.htmlhttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73861.html#Feedback0http://www.shnenglu.com/xushaohua/comments/commentRss/73861.htmlhttp://www.shnenglu.com/xushaohua/services/trackbacks/73861.html

LGPL是GPL的一个ؓ主要为类库用设计的开源协议。和GPL要求M使用/修改/衍生之GPLcd的的软g必须采用GPL协议不同。LGPL允许商业软g通过cd引用(link)方式使用LGPLcd而不需要开源商业Y件的代码。这使得采用LGPL协议的开源代码可以被商业软g作ؓcd引用q发布和销售?/p>

但是如果修改LGPL协议的代码或者衍生,则所有修改的代码Q涉及修攚w分的额外代码和衍生的代码都必采用LGPL协议。因此LGPL协议的开源代码很适合作ؓW三方类库被商业软g引用Q但不适合希望以LGPL协议代码为基Q通过修改和衍生的方式做二ơ开发的商业软g采用?/p>

GPL/LGPL都保障原作者的知识产权Q避免有人利用开源代码复制ƈ开发类似的产品



neter 2009-02-15 12:58 发表评论
]]>
开源协?-----GPLhttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73860.htmlneterneterSun, 15 Feb 2009 04:57:00 GMThttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73860.htmlhttp://www.shnenglu.com/xushaohua/comments/73860.htmlhttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73860.html#Feedback0http://www.shnenglu.com/xushaohua/comments/commentRss/73860.htmlhttp://www.shnenglu.com/xushaohua/services/trackbacks/73860.html


我们很熟悉的Linux是采用了GPL。GPL协议和BSD, Apache Licence{鼓׃码重用的许可很不一栗GPL的出发点是代码的开?免费使用和引?修改/衍生代码的开?免费使用Q但不允怿改后和衍生的代码做ؓ闭源的商业Y件发布和销售。这也就是ؓ什么我们能用免费的各种linuxQ包括商业公司的linux和linux上各U各L׃人,l织Q以及商业Y件公司开发的免费软g了?/p>

GPL协议的主要内Ҏ只要在一个Y件中使用(”使用”指类库引用,修改后的代码或者衍生代?GPL 协议的品,则该软g产品必须也采用GPL协议Q既必须也是开源和免费。这是所谓的”传染?#8221;。GPL协议的品作Z个单独的产品使用没有M问题Q还可以享受免费的优ѝ?/p>

׃GPL严格要求使用了GPLcd的Y件品必M用GPL协议Q对于用GPL协议的开源代码,商业软g或者对代码有保密要求的部门׃适合集成/采用作ؓcd和二ơ开发的基础?/p>

其它l节如再发布的时候需要伴随GPL协议{和BSD/Apache{类伹{?/p>

neter 2009-02-15 12:57 发表评论
]]>
开源协?-----Apache Licence 2.0http://www.shnenglu.com/xushaohua/archive/2009/02/15/73858.htmlneterneterSun, 15 Feb 2009 04:55:00 GMThttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73858.htmlhttp://www.shnenglu.com/xushaohua/comments/73858.htmlhttp://www.shnenglu.com/xushaohua/archive/2009/02/15/73858.html#Feedback0http://www.shnenglu.com/xushaohua/comments/commentRss/73858.htmlhttp://www.shnenglu.com/xushaohua/services/trackbacks/73858.htmlApache Licence是著名的非盈利开源组lApache采用的协议。该协议和BSDcMQ同样鼓׃码共享和重原作者的著作权,同样允许代码修改Q再发布Q作为开源或商业软gQ。需要满的条g也和BSDcMQ?/p>
  1. 需要给代码的用户一份Apache Licence
  2. 如果你修改了代码Q需要再被修改的文g中说明?
  3. 在g伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标Q专利声明和其他原来作者规定需要包含的说明?
  4. 如果再发布的产品中包含一个Notice文gQ则在Notice文g中需要带有Apache Licence。你可以在Notice中增加自q许可Q但不可以表Cؓ对Apache Licence构成更改?

Apache Licence也是对商业应用友好的许可。用者也可以在需要的时候修改代码来满需要ƈ作ؓ开源或商业产品发布/销售?/p>

neter 2009-02-15 12:55 发表评论
]]>
开源协?-----BSD开源协?/title><link>http://www.shnenglu.com/xushaohua/archive/2009/02/15/73857.html</link><dc:creator>neter</dc:creator><author>neter</author><pubDate>Sun, 15 Feb 2009 04:54:00 GMT</pubDate><guid>http://www.shnenglu.com/xushaohua/archive/2009/02/15/73857.html</guid><wfw:comment>http://www.shnenglu.com/xushaohua/comments/73857.html</wfw:comment><comments>http://www.shnenglu.com/xushaohua/archive/2009/02/15/73857.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/xushaohua/comments/commentRss/73857.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xushaohua/services/trackbacks/73857.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 12pt">BSD开源协议是一个给于用者很大自q协议。基本上使用者可?#8221;为所Ʋؓ”,可以自由的用,修改源代码,也可以将修改后的代码作ؓ开源或者专有Y件再发布?/p> <p style="FONT-SIZE: 12pt">?#8221;为所Ʋؓ”的前提当你发布用了BSD协议的代码,或则以BSD协议代码为基做二ơ开发自q产品Ӟ需要满三个条Ӟ</p> <ol> <li>如果再发布的产品中包含源代码Q则在源代码中必d有原来代码中的BSD协议? <li>如果再发布的只是二进制类?软gQ则需要在cd/软g的文档和版权声明中包含原来代码中的BSD协议? <li>不可以用开源代码的作?机构名字和原来品的名字做市场推qѝ?</li> </ol> <p style="FONT-SIZE: 12pt">BSD 代码鼓励代码׃nQ但需要尊重代码作者的著作权。BSD׃允许使用者修改和重新发布代码Q也允许使用或在BSD代码上开发商业Y件发布和销售,因此是对商业集成很友好的协议。而很多的公司企业在选用开源品的时候都首选BSD协议Q因为可以完全控制这些第三方的代码,在必要的时候可以修Ҏ者二ơ开发?/p> <img src ="http://www.shnenglu.com/xushaohua/aggbug/73857.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xushaohua/" target="_blank">neter</a> 2009-02-15 12:54 <a href="http://www.shnenglu.com/xushaohua/archive/2009/02/15/73857.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BCD?/title><link>http://www.shnenglu.com/xushaohua/archive/2007/12/24/39499.html</link><dc:creator>neter</dc:creator><author>neter</author><pubDate>Mon, 24 Dec 2007 04:34:00 GMT</pubDate><guid>http://www.shnenglu.com/xushaohua/archive/2007/12/24/39499.html</guid><wfw:comment>http://www.shnenglu.com/xushaohua/comments/39499.html</wfw:comment><comments>http://www.shnenglu.com/xushaohua/archive/2007/12/24/39499.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/xushaohua/comments/commentRss/39499.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xushaohua/services/trackbacks/39499.html</trackback:ping><description><![CDATA[即BCD代码。Binary-Coded Decimal‎Q简UBCDQ称BCD码或?十进制代码,亦称二进码十q数。是一U?a target=_blank><u><font color=#0000ff>二进?/font></u></a>的数字编码Ş式,用二q制~码?a target=_blank><u><font color=#0000ff>十进?/font></u></a>代码。这U编码Ş式利用了四个位元来储存一个十q制的数码,使二q制和十q制之间的{换得以快Lq行。这U编码技巧,最常用于会计系l的设计里,因ؓ会计制度l常需要对很长的数字串作准的计算。相对于一般的点式记数法Q采用BCD码,既可保存数值的_度,又可免却使电脑作点q算时所耗费的时间。此外,对于其他需要高_度的计算QBCD~码亦很常用?br><br>׃十进制数共有0???#8230;…?十个数码Q因此,臛_需?位二q制码来表示1位十q制数?位二q制码共?^4=16U码l,在这16U代码中Q可以Q?0U来表示10个十q制数码Q共有N=16Q?Q?6-10Q!U等?.9乘以10?0ơ方U方案。常用的BCD代码列于末?br><br><strong>常用BCD~码方式</strong><br>最常用的BCD~码Q就是?0"?9"q十个数值的二进码来表示。这U编码方式,在中国大陆称之ؓ“8421?#8221;。除此以外,对应不同需求,各h亦开发了不同的编码方法,以适应不同的需求。这些编码,大致可以分成有权码和无权码两U:<br><br>有权BCD码,如:8421(最常用)?421?421… <br>无权BCD码,如:?码、格L… <br><br>常用<span>BCD~码?/span> <div align=center> <table cellSpacing=0 cellPadding=0 width="74%" border=1> <tbody> <tr> <td> <div align=center> <table cellSpacing=0 cellPadding=0 width=410 border=0> <tbody> <tr> <td width=90> <p> </p> </td> <td width=67> <p align=center><span>8421?/span></p> </td> <td width=60> <p align=center><span>5421?/span></p> </td> <td width=66> <p align=center><span>2421?/span></p> </td> <td width=67> <p align=center><span>5211?/span></p> </td> <td width=60> <p align=center><span>?span>3?/span></span></p> </td> </tr> <tr> <td width=90> <p align=center><span>0</span></p> </td> <td width=67> <p align=center><span>0000</span></p> </td> <td width=60> <p align=center><span>0000</span></p> </td> <td width=66> <p align=center><span>0000</span></p> </td> <td width=67> <p align=center><span>0000</span></p> </td> <td width=60> <p align=center><span>0000</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>1</span></p> </td> <td width=67> <p align=center><span>0001</span></p> </td> <td width=60> <p align=center><span>0001</span></p> </td> <td width=66> <p align=center><span>0001</span></p> </td> <td width=67> <p align=center><span>0001</span></p> </td> <td width=60> <p align=center><span>0100</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>2</span></p> </td> <td width=67> <p align=center><span>0010</span></p> </td> <td width=60> <p align=center><span>0010</span></p> </td> <td width=66> <p align=center><span>0010</span></p> </td> <td width=67> <p align=center><span>0100</span></p> </td> <td width=60> <p align=center><span>0101</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>3</span></p> </td> <td width=67> <p align=center><span>0011</span></p> </td> <td width=60> <p align=center><span>0011</span></p> </td> <td width=66> <p align=center><span>0011</span></p> </td> <td width=67> <p align=center><span>0101</span></p> </td> <td width=60> <p align=center><span>0110</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>4</span></p> </td> <td width=67> <p align=center><span>0100</span></p> </td> <td width=60> <p align=center><span>0100</span></p> </td> <td width=66> <p align=center><span>0100</span></p> </td> <td width=67> <p align=center><span>0111</span></p> </td> <td width=60> <p align=center><span>0111</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>5</span></p> </td> <td width=67> <p align=center><span>0101</span></p> </td> <td width=60> <p align=center><span>1000</span></p> </td> <td width=66> <p align=center><span>0101</span></p> </td> <td width=67> <p align=center><span>1000</span></p> </td> <td width=60> <p align=center><span>1000</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>6</span></p> </td> <td width=67> <p align=center><span>0110</span></p> </td> <td width=60> <p align=center><span>1001</span></p> </td> <td width=66> <p align=center><span>0110</span></p> </td> <td width=67> <p align=center><span>1001</span></p> </td> <td width=60> <p align=center><span>1001</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>7</span></p> </td> <td width=67> <p align=center><span>0111</span></p> </td> <td width=60> <p align=center><span>1010</span></p> </td> <td width=66> <p align=center><span>0111</span></p> </td> <td width=67> <p align=center><span>1100</span></p> </td> <td width=60> <p align=center><span>1010</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>8</span></p> </td> <td width=67> <p align=center><span>1000</span></p> </td> <td width=60> <p align=center><span>1011</span></p> </td> <td width=66> <p align=center><span>1110</span></p> </td> <td width=67> <p align=center><span>1101</span></p> </td> <td width=60> <p align=center><span>1011</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>9</span></p> </td> <td width=67> <p align=center><span>1001</span></p> </td> <td width=60> <p align=center><span>1100</span></p> </td> <td width=66> <p align=center><span>1111</span></p> </td> <td width=67> <p align=center><span>1111</span></p> </td> <td width=60> <p align=center><span>1100</span></p> </td> </tr> <tr> <td width=90> <p align=center><span>?/span></p> </td> <td width=67> <p align=center><span>8421</span></p> </td> <td width=60> <p align=center><span>5421</span></p> </td> <td width=66> <p align=center><span>2421</span></p> </td> <td width=67> <p align=center><span>5211</span></p> </td> <td width=60> <p> </p> </td> </tr> </tbody> </table> </div> <p> </p> </td> </tr> </tbody> </table> </div> <span><font size=3>非压~式和压~式BCD?br>    BCD又分ZU,非压~式和压~式两种?br>    前面q种81存成 “08,01” 是非压羃式,而压~式会存?“81h” (直接以十六进制储?。非压羃的BCD码只有低四位有效Q而压~的BCD码则高四位也用上了Q就是说一个字节有两个BCD码。BCD是用0?表示十进Ӟ?000表示0Q?001表示1Q?010表示2。而压~的BCD是用00表示0Q?1表示1Q?0表示2Q?10表示3{?br>    例:<br>    1234表示成非压羃的BCD码是00000001000000100000001100000100Q也是0x01020304Q而压~BCD码则表示?001001000110100Q也是0x1234?br>    但压~的BCDq不固定Q可看情况而定Q所要的是用最的位数表示可能多的数?/font><br></span> <img src ="http://www.shnenglu.com/xushaohua/aggbug/39499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xushaohua/" target="_blank">neter</a> 2007-12-24 12:34 <a href="http://www.shnenglu.com/xushaohua/archive/2007/12/24/39499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]~写高效的数据库q接?/title><link>http://www.shnenglu.com/xushaohua/archive/2007/12/21/39172.html</link><dc:creator>neter</dc:creator><author>neter</author><pubDate>Thu, 20 Dec 2007 17:42:00 GMT</pubDate><guid>http://www.shnenglu.com/xushaohua/archive/2007/12/21/39172.html</guid><wfw:comment>http://www.shnenglu.com/xushaohua/comments/39172.html</wfw:comment><comments>http://www.shnenglu.com/xushaohua/archive/2007/12/21/39172.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/xushaohua/comments/commentRss/39172.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xushaohua/services/trackbacks/39172.html</trackback:ping><description><![CDATA[<p><font face="Times New Roman" size=2>相关技术:</font></p> <ul> <li><font face="Times New Roman" size=2>q接?/font> <li><font face="Times New Roman" size=2>引用记数</font> <li><font face="Times New Roman" size=2>多线E?/font> <li><font face="Times New Roman" size=2>Timerc运行基?/font> <li><font face="Times New Roman" size=2>C#.Net</font>   </li> </ul> <p><font face="Times New Roman" size=2>适宜人群</font></p> <ul> <li><font face="Times New Roman" size=2>数据库应用程序程序员</font> <li><font face="Times New Roman" size=2>pȝ分析?/font> <li><font face="Times New Roman" size=2>模块设计?/font> <li>有一定功底的E序?</li> </ul> <p>目录</p> <ul> <li><font size=2>引言</font> <ol> <li><font face="Times New Roman" size=2>数据库连接池QConnection PoolQ的工作原理</font> </li> </ol> <li><font face="Times New Roman" size=2>q接池关键问题分?/font> <ol> <li><font face="Times New Roman" size=2>q发问题</font> <li><font face="Times New Roman" size=2>事务处理</font> <li><font face="Times New Roman" size=2>q接池的分配与释?/font> <li><font face="Times New Roman" size=2>q接池的配置与维?/font> </li> </ol> <li> <div align=left><font face="Times New Roman" size=2>关键议题</font></div> <ol> <li> <div align=left><font face="Times New Roman" size=2>引用记数</font></div> <li> <div align=left>如何实现事务处理</div> <li> <div align=left> <div align=left> 理q接?/div> </div> </li> </ol> <li> <div align=left> <div align=left>l合代码说明</div> </div> <ol> <li> <div align=left>构造方?/div> <li> <div align=left><font size=2>启动服务StartService</font></div> <li> <div align=left><font size=2>停止服务StopService</font></div> <li> <div align=left><font size=2>甌 GetConnectionFormPool</font></div> <li> <div align=left><font size=2>释放DisposeConnection</font></div> <li> <div align=left><font size=2>如何更新属?/font></div> <li> <div align=left><font size=2>如何定q接是否失效</font></div> <li> <div align=left><font size=2>使用U程理q接?/font></div> <ol> <li> <div align=left><font size=2>threadCreate</font></div> <li> <div align=left><font size=2>threadCheck</font></div> </li> </ol> <li> <div align=left><font size=2></font> <p> <font size=2>其他</font></p> </div> </li> </ol> </li> </ul> <hr> <p><font color=#ff0000 size=3>引言</font></p> <p><font face="Times New Roman" size=2>一般的数据库应用程序大致都遵@下面的步?</font></p> <ol> <li><font face="Times New Roman"><font size=2><font color=#ff99cc>初始化程?/font> </font></font> <li><font face="Times New Roman"><font size=2><font color=#ff99cc>用户在UI上输入操?/font> </font></font> <li><font face="Times New Roman"><font size=2><font color=#ff99cc>qh作生数据库操作</font> </font></font> <li><font face="Times New Roman"><font size=2><font color=#ff99cc>数据库操作递交到数据库服务?/font> </font></font> <li><font face="Times New Roman"><font color=#ff99cc size=2>.... (重复2~4)</font></font> <li><font face="Times New Roman"><font size=2><font color=#ff99cc>关闭应用E序</font> </font></font></li> </ol> <p><font face="Times New Roman" size=2>  而本文则着重讲解上面第<font color=#ff0000>4</font>步骤.在着一步骤中我们经常是,打开数据库连接操作数据库,最后关闭数据库.<br></font><font face="Times New Roman" size=2>  在服务器端程序设计上与数据库的操作显得十分重?因ؓ你要处理的数据操作十分巨?如果频繁创徏数据库连接频J关闭数据库q接则会引v效率低下甚至引发E序崩溃.<br>  也许我们可以有另一U操作数据库的Ş?我们可以在程序运行时打开一个数据库q接,让这个连接永久存在直到程?M',那么q样做也有不安全隐患,我们知道一个对象存在时间越长或被用次数越多则它表现的不E_,着不稳定因素是׃对象内部可能存在的潜在设计问题?对于数据库连接对象道理也一?我们不能保证一个Connection对象里面能一炚w题不存在.所以我们也不敢长时间将它长旉占用内存.<br></font><font face="Times New Roman" size=2>  既然有这么多的问题由此我们需要一个能帮我们维护数据库q接的东?它就?font color=#ff0000>q接?/font>,|上有很多的q接池例?但是多数都是单的例子,或者介l比较复杂的q接池原?没有一个比较完整介l和实现q接池的例子.q里׃l你如何自己制作一个连接池.<br></font><font face="Times New Roman" size=2>  对于׃n资源Q有一个很著名的设计模式:资源池(Resource PoolQ。该模式正是Z解决资源的频J分配﹑释放所造成的问题。ؓ解决我们的问题,可以采用数据库连接池技术。数据库q接池的基本思想是为数据库q接建立一?#8220;~冲?#8221;。预先在~冲池中攑օ一定数量的q接Q当需要徏立数据库q接Ӟ只需?#8220;~冲?#8221;中取Z个,使用完毕之后再放回去。我们可以通过讑֮q接池最大连接数来防止系l无的与数据库q接。更为重要的是我们可以通过q接池的理机制监视数据库的q接的数量﹑使用情况Qؓpȝ开发﹑试及性能调整提供依据。连接池的基本工作原理见下图?/font></p> <p align=center><font face="Times New Roman" size=3>数据库连接池QConnection PoolQ的工作原理</font></p> <p align=center><font face="Times New Roman" size=2><img height=227 alt="" src="http://www.mx68.com/WebDeveloper/UploadFiles_5122/200601/2006118234027410.gif" width=563></font></p> <p align=left><font face="Times New Roman" size=2><font face=Arial color=#ff0000 size=3></font></font></p> <p><font color=#ff0000 size=3> q接池关键问题分?/font></p> <p align=left><font face="Times New Roman" size=2>  1、ƈ发问?/font></p> <p align=left><font face="Times New Roman" size=2>  Z使连接管理服务具有最大的通用性,必须考虑多线E环境,卛_ƈ发问题。这个问题相Ҏ较好解决Q因为各个语a自n提供了对q发理的支持像java,c#{等Q用synchronized(java)lock(C#)关键字即可确保线E是同步的。用方法可以参考,相关文献?/font></p> <p align=left><font face="Times New Roman" size=2>  Q、事务处?/font></p> <p align=left><font face="Times New Roman" size=2>  我们知道Q事务具有原子性,此时要求Ҏ据库的操作符?#8220;ALL-ALL-NOTHING”原则,卛_于一lSQL语句要么全做Q要么全不做?br></font><font face="Times New Roman" size=2>  我们知道当2个线E公用一个连接Connection对象Q而且各自都有自己的事务要处理时候,对于q接池是一个很头疼的问题,因ؓ即ConnectioncL供了相应的事务支持,可是我们仍然不能定那个数据库操作是对应那个事务的,q是׃我们有2个线E都在进行事务操作而引L。ؓ此我们可以?/font><font face="Times New Roman" size=2>每一个事务独占一个连接来实现Q虽然这U方法有Ҏ费连接池资源但是可以大大降低事务理的复杂性?/font></p> <p align=left><font face="Times New Roman" size=2>  Q、连接池的分配与释放</font></p> <p align=left><font face="Times New Roman" size=2>  q接池的分配与释放,对系l的性能有很大的影响。合理的分配与释放,可以提高q接的复用度Q从而降低徏立新q接的开销Q同时还可以加快用户的访问速度?br></font><font face="Times New Roman" size=2>  对于q接的管理可使用一个List。即把已l创建的q接都放入List中去l一理。每当用戯求一个连接时Q系l检查这个List中有没有可以分配的连接。如果有把那个最合适的q接分配l他<font color=#339966>Q如何能扑ֈ最合适的q接文章在关键议题中指?/font>Q;如果没有抛Z个异常给用户QList中连接是否可以被分配׃个线E来专门理捎后我会介绍q个U程的具体实现?</font></p> <p> <font face="Times New Roman" size=2>  Q、连接池的配|与l护</font></p> <p align=left><font face="Times New Roman" size=2>  q接池中到底应该攄多少q接Q才能ɾpȝ的性能最佻Ipȝ可采取设|最连接数QminConnectionQ和最大连接数QmaxConnectionQ等参数来控制连接池中的q接。比方说Q最连接数是系l启动时q接池所创徏的连接数。如果创多,则系l启动就慢,但创建后pȝ的响应速度会很快;如果创徏q少Q则pȝ启动的很快,响应h却慢。这P可以在开发时Q设|较的最连接数Q开发v来会快,而在pȝ实际使用时设|较大的Q因样对讉K客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体讄多少Q要看系l的讉K量,可通过软g需求上得到?br></font><font face="Times New Roman" size=2>  如何保q接池中的最连接数呢?有动态和静态两U策略。动态即每隔一定时间就对连接池q行,如果发现q接数量于最连接数Q则补充相应数量的新q接,以保证连接池的正常运转。静态是发现I闲q接不够时再L查?</font></p> <img src ="http://www.shnenglu.com/xushaohua/aggbug/39172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xushaohua/" target="_blank">neter</a> 2007-12-21 01:42 <a href="http://www.shnenglu.com/xushaohua/archive/2007/12/21/39172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[MSDN]使用q接?/title><link>http://www.shnenglu.com/xushaohua/archive/2007/12/21/39171.html</link><dc:creator>neter</dc:creator><author>neter</author><pubDate>Thu, 20 Dec 2007 17:33:00 GMT</pubDate><guid>http://www.shnenglu.com/xushaohua/archive/2007/12/21/39171.html</guid><wfw:comment>http://www.shnenglu.com/xushaohua/comments/39171.html</wfw:comment><comments>http://www.shnenglu.com/xushaohua/archive/2007/12/21/39171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/xushaohua/comments/commentRss/39171.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xushaohua/services/trackbacks/39171.html</trackback:ping><description><![CDATA[<div id="xhxftnp" class=title>使用q接?!----></div> <!--content type: DocStudio. Transform: devdiv2mtps.xslt.--> <div class="vrnvhhj" id=mainSection> <div class="fplrzbb" id=mainBody> <p> <p>q接到数据库服务器通常由几个需要很长时间的步骤l成。必d立物理通道Q例如套接字或命名管道)Q必M服务器进行初ơ握手,必须分析q接字符串信息,必须由服务器对连接进行n份验证,必须q行查以便在当前事务中登讎ͼ{等?</p> <p>实际上,大多数应用程序仅使用一个或几个不同的连接配|。这意味着在执行应用程序期_许多相同的连接将反复地打开和关闭。ؓ了打开的连接成本最低,ADO.NET 使用UCؓ<em>q接?/em>的优化方法?/p> <p>q接池减新q接需要打开的次数?em>池进E?/em>保持物理q接的所有权。通过为每个给定的q接配置保留一l活动连接来理q接。只要用户在q接上调?OpenQ池q程׃查池中是否有可用的连接。如果某个池q接可用Q会该q接q回l调用者,而不是打开新连接。应用程序在该连接上调用 Close Ӟ池进E会连接返回到zdq接池集中,而不是真正关闭连接。连接返回到池中之后Q即可在下一?Open 调用中重复用?/p> <p>只有配置相同的连接可以徏立池q接。ADO.NET 同时保留多个池,每个配置一个池。连接由q接字符串以?Windows 标识Q在使用集成的安全性时Q分为多个池?/p> <p>池连接可以大大提高应用程序的性能和可~放性。默认情况下QADO.NET 中启用连接池。除非显式禁用,否则Q连接在应用E序中打开和关闭时Q池q程对q接q行优化。还可以提供几个q接字符串修饰符来控制连接池的行为。有x多信息,请参见本主题后面?#8220;使用q接字符串关键字控制q接?#8221;?/p> <h1 class=heading>池的创徏和分?/h1> <div id="rtfhbzv" class=seeAlsoNoToggleSection id=sectionSection0> <p>在初ơ打开q接Ӟ根据完全匹配算法创接池Q该法池与连接中的连接字W串兌。每个连接池与不同的q接字符串关联。打开新连接时Q如果连接字W串q与现有池完全匚wQ将创徏一个新池。按q程、按应用E序域、按q接字符串以及(在用集成的安全性时Q按 Windows 标识来徏立池q接?/p> <p>在以?C# CZ中创Z三个新的 <a id=ctl00_rs1_mainContentContainer_ctl01 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl01',this);" tabIndex=0 ><u><font color=#0000ff>SqlConnection</font></u></a> 对象Q但是管理时只需要两个连接池。注意,Ҏ?<tt>Initial Catalog</tt> 分配的|W一个和W二个连接字W串有所不同?/p> <div id="vxdzbzz" class=code id=ctl00_rs1_mainContentContainer_ctl02_other> <pre class=code id=ctl00_rs1_mainContentContainer_ctl02other space="preserve">using (SqlConnection connection = new SqlConnection( "Integrated Security=SSPI;Initial Catalog=Northwind")) { connection.Open(); // Pool A is created. } using (SqlConnection connection = new SqlConnection( "Integrated Security=SSPI;Initial Catalog=pubs")) { connection.Open(); // Pool B is created because the connection strings differ. } using (SqlConnection connection = new SqlConnection( "Integrated Security=SSPI;Initial Catalog=Northwind")) { connection.Open(); // The connection string matches pool A. }</pre> </div> <p>如果 MinPoolSize 在连接字W串中未指定或指定ؓӞ池中的连接将在一D|间不zd后关闭。但是,如果指定?MinPoolSize 大于Ӟ?AppDomain 被卸载ƈ且进E结束之前,q接池不会被破坏。非zd或空池的l护只需要最的pȝ开销?/p> <div id="lffbbrp" class=alert> <table width="100%"> <tbody> <tr> <th align=left><img class=note alt=Note src="http://msdn2.microsoft.com/zh-cn/library/8xx3tyca.note(zh-cn,VS.80).gif">注意</th> </tr> <tr> <td> <p>如果发生致命错误Q例如故障{UL注册表中的别名更改)Q池自动清除?/p> </td> </tr> </tbody> </table> </div> </div> <h1 class=heading>dq接</h1> <div id="lnpzlbh" class=seeAlsoNoToggleSection id=sectionSection1> <p>q接池是为每个唯一的连接字W串创徏的。当创徏一个池后,创建多个连接对象ƈ其d到该池中Q以满最池大小的要求。连接根据需要添加到池中Q但是不能超q指定的最大池大小Q默认gؓ 100Q。连接在关闭或断开旉攑֛池中?</p> <p>在请?SqlConnection 对象Ӟ如果存在可用的连接,从池中获取该对象。连接要可用Q必L使用Q具有匹配的事务上下文或未与M事务上下文关联,q且h与服务器的有效链接?/p> <p>q接池进E通过在连接释攑֛池中旉新分配连接,来满些连接请求。如果已辑ֈ最大池大小且不存在可用的连接,则该h会排队。然后,池进E尝试重新徏立Q何连接,直到到达时旉Q默认gؓ 15 U)。如果池q程在连接超时之前无法满求,引发异常?</p> <div id="tdxbljp" class=alert> <table width="100%"> <tbody> <tr> <th align=left><img class=note alt="Caution note" src="http://msdn2.microsoft.com/zh-cn/library/8xx3tyca.Caution(zh-cn,VS.80).gif">警告</th> </tr> <tr> <td> <p>我们您在使用完连接时一定要关闭q接Q以便连接可以返回池。要关闭q接Q可以?Connection 对象?Close ?Dispose ҎQ也可以通过?C# ?using 语句中或?Visual Basic ?Using 语句中打开所有连接。不是显式关闭的q接可能不会d或返回到池中。例如,如果q接已超围但没有昑ּ关闭Q则仅当辑ֈ最大池大小而该q接仍然有效Ӟ该连接才会返回到q接池中。有x多信息,请参?Visual Basic ?a id=ctl00_rs1_mainContentContainer_ctl03 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl03',this);" tabIndex=0 ><u><font color=#0000ff>using 语句QC# 参考)</font></u></a>?a id=ctl00_rs1_mainContentContainer_ctl04 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl04',this);" tabIndex=0 ><u><font color=#0000ff>如何Q释攄l资?/font></u></a>?/p> </td> </tr> </tbody> </table> </div> <div id="lvpjdzz" class=alert> <table width="100%"> <tbody> <tr> <th align=left><img class=note alt=Note src="http://msdn2.microsoft.com/zh-cn/library/8xx3tyca.note(zh-cn,VS.80).gif">注意</th> </tr> <tr> <td> <p>不要在类?Finalize Ҏ中对 Connection、DataReader 或Q何其他托对象调?Close ?Dispose。在l结器中Q仅释放cȝ接拥有的非托资源。如果类不拥有Q何非托管资源Q则不要在类定义中包?Finalize Ҏ。有x多信息,请参?a id=ctl00_rs1_mainContentContainer_ctl05 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl05',this);" tabIndex=0 ><u><font color=#0000ff>垃圾回收</font></u></a>?/p> </td> </tr> </tbody> </table> </div> </div> <h1 class=heading>U除q接</h1> <div id="fjbnxvv" class=seeAlsoNoToggleSection id=sectionSection2> <p>q接池进E定期扫描连接池Q查找没有通过 Close ?Dispose 关闭的未用连接,q新徏立找到的q接。如果应用程序没有显式关闭或断开其连接,q接池进E可能需要很长时间才能重新徏立连接,所以,最好确保在q接中显式调?Close ?Dispose?/p> <p>如果q接长时间空Ԍ或池q程到与服务器的连接已断开Q连接池q程会将该连接从池中U除。注意,只有在尝试与服务器进行通信之后才能到断开的连接。如果发现某q接不再q接到服务器Q则会将其标Cؓ无效。无效连接只有在关闭或重新徏立后Q才会从q接池中U除?/p> <p>如果存在与已消失的服务器的连接,那么即ɘq接池管理程序未到已断开的连接ƈ其标记为无效,仍有可能此q接从池中取出。这U情冉|因ؓ查连接是否仍有效的系l开销造成与服务器的另一ơ往q,从而抵消了池进E的优势。发生此情况Ӟ初次试使用该连接将连接是否曾断开Qƈ引发异常?/p> </div> <h1 class=heading>清除?/h1> <div id="rllfrpd" class=seeAlsoNoToggleSection id=sectionSection3> <p>ADO.NET 2.0 引入了两U新的方法来清除池:<a id=ctl00_rs1_mainContentContainer_ctl06 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl06',this);" tabIndex=0 ><u><font color=#0000ff>ClearAllPools</font></u></a> ?<a id=ctl00_rs1_mainContentContainer_ctl07 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl07',this);" tabIndex=0 ><u><font color=#0000ff>ClearPool</font></u></a>。ClearAllPools 清除l定提供E序的连接池QClearPool 清除与特定连接关联的q接池。如果在调用时连接正在用,进行相应的标记。连接关闭时Q将被丢弃,而不是返回池中?/p> </div> <h1 class=heading>事务支持</h1> <div id="vfxbtbz" class=seeAlsoNoToggleSection id=sectionSection4> <p>q接是根据事务上下文来从池中取出q进行分配的。除非在q接字符串中指定?<tt>Enlist=false</tt>Q否则,q接池将保q接?<a id=ctl00_rs1_mainContentContainer_ctl08 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl08',this);" tabIndex=0 ><u><font color=#0000ff>Current</font></u></a> 上下文中登记。如果连接用登记的 System.Transactions 事务关闭q返回池中,q接保留在池中Q以便用相?System.Transactions 事务对该q接池的下一ơ请求将q回相同的连接。如果该事务没有可用q接Q在该连接打开Ӟ自动注册该q接?/p> <p>当连接关闭时Q它被释放回池中,q根据其事务上下文放入相应的子部分。因此,即分布式事务仍然挂P仍可以关闭该q接而不会生成错误。这P您就可以在随后提交或中止分布式事务?/p> </div> <h1 class=heading>使用q接字符串关键字控制q接?/h1> <div id="xpjbndl" class=seeAlsoNoToggleSection id=sectionSection5> <p>SqlConnection 对象?ConnectionString 属性支持连接字W串?值对Q可以用于调整连接池逻辑的行为。有x多信息,请参?<a id=ctl00_rs1_mainContentContainer_ctl09 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl09',this);" tabIndex=0 ><u><font color=#0000ff>ConnectionString</font></u></a>?/p> </div> <h1 class=heading>池碎?/h1> <div id="rldnpfn" class=seeAlsoNoToggleSection id=sectionSection6> <p>池碎片是许多 Web 应用E序中的一个常见问题,应用E序可能会创建大量在q程退出后才会释放的池。这P打开大量的连接,占用许多内存Q从而媄响性能?/p> <h3 class=subHeading>因ؓ集成安全性生的池碎?/h3> <div id="dfprbzh" class=subSection> <p>q接Ҏq接字符串以及用h识来建立池连接。因此,如果使用|站上的基本w䆾验证?Windows w䆾验证以及集成的安全登录,每个用户获得一个池。尽这样可以提高单个用L后箋数据库请求的性能Q但是该用户无法利用其他用户建立的连接。这栯使每个用戯生一个与数据库服务器的连接。这对特?Web 应用E序l构会生副作用Q因为开发h员需要衡量安全性和审计要求?/p> </div> <h3 class=subHeading>因ؓ许多数据库生的池碎?/h3> <div id="bdxhjpf" class=subSection> <p>许多 Internet 服务提供商在一台服务器上托多个网站。他们可能用单个数据库认H体w䆾验证dQ然后ؓ该用h用户l打开与特定数据库的连接。与w䆾验证数据库的q接徏立池q接Q供每个用户使用。但是,每个数据库的q接存在一个独立的池,因此增加了与服务器的q接数?/p> <p>q也会对应用E序设计产生副作用。但是,可以通过一个相对简单的方式避免此副作用Q而又不会影响q接 SQL Server 时的安全性。不是ؓ每个用户或组q接独立的数据库Q而是q接到服务器上的相同数据库,然后执行 Transact-SQL USE 语句来切换ؓ所需的数据库。以下代码段演示入如何创Z master 数据库的初始q接Q然后切换到 <tt>databaseName</tt> 字符串变量中指定的所需数据库?/p> <div id="bjdxbhv" class=code id=ctl00_rs1_mainContentContainer_ctl11_CSharp>C#:<br><span style="COLOR: green">// Assumes that command is a SqlCommand object.</span><br><span style="COLOR: blue">using</span> (SqlConnection connection = <span style="COLOR: blue">new</span> SqlConnection(<br>  <span style="COLOR: maroon">"Server=MSSQL1;uid=xxx;pwd=xxx;database=master"</span>))<br>  {<br>    connection.Open();<br>    command.ExecuteNonQuery(<span style="COLOR: maroon">"USE "</span> + databaseName);<br>  }<br></div> </div> </div> <h1 class=heading>应用E序角色和连接池</h1> <div id="nhzndbz" class=seeAlsoNoToggleSection id=sectionSection7> <p>通过调用 sp_setapprole pȝ存储q程ȀzM SQL Server 应用E序角色之后Q该q接的安全上下文无法重置。但是,如果启用了池Q连接将q回池,在重复用池q接时会出错?/p> <p>如果使用的是 SQL Server 应用E序角色Q我们徏议您在连接字W串中ؓ应用E序用q接池。有x多信息,请参见知识库文章“<a id=ctl00_rs1_mainContentContainer_ctl12 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl12',this);" tabIndex=0 ><u><font color=#0000ff>SQL application role errors with OLE DB resource pooling</font></u></a>”?/p> </div> </div> </div> <img src ="http://www.shnenglu.com/xushaohua/aggbug/39171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xushaohua/" target="_blank">neter</a> 2007-12-21 01:33 <a href="http://www.shnenglu.com/xushaohua/archive/2007/12/21/39171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]VC中基?Windows 的精定?/title><link>http://www.shnenglu.com/xushaohua/archive/2007/12/04/37817.html</link><dc:creator>neter</dc:creator><author>neter</author><pubDate>Tue, 04 Dec 2007 12:56:00 GMT</pubDate><guid>http://www.shnenglu.com/xushaohua/archive/2007/12/04/37817.html</guid><wfw:comment>http://www.shnenglu.com/xushaohua/comments/37817.html</wfw:comment><comments>http://www.shnenglu.com/xushaohua/archive/2007/12/04/37817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/xushaohua/comments/commentRss/37817.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xushaohua/services/trackbacks/37817.html</trackback:ping><description><![CDATA[中国U学院光甉|术研I所 <a href="mailto:yzyseal@126.com"><u><font color=#0000ff>游志?/font></u></a><br><br>在工业生产控制系l中Q有许多需要定时完成的操作Q如定时昄当前旉Q定时刷新屏q上的进度条Q上?wbr> 机定时向下位机发送命令和传送数据等。特别是在对控制性能要求较高的实时控制系l和数据采集pȝ中,更需要精定时操作?br>  众所周知QWindows 是基于消息机制的pȝQQ何事件的执行都是通过发送和接收消息来完成的?wbr> q样带来了一些问题,如一旦计机的CPU被某个进E占用,或系l资源紧张时Q发送到消息队列<wbr> 中的消息暂时被挂vQ得不到实时处理。因此,不能单地通过Windows消息引发一个对定时要求<wbr> 严格的事件。另外,׃在Windows中已l封装了计算机底层硬件的讉KQ所以,要想通过直接利用<wbr> 讉Kg来完成精定Ӟ也比较困难。所以在实际应用Ӟ应针对具体定时精度的要求Q采取相?应的定时Ҏ?br>  VC中提供了很多关于旉操作的函敎ͼ利用它们控制E序能够_地完成定时和计时操作。本文详l介l了<wbr> VC中基于Windows的精定时的七种方式Q如下图所C:<br><img height=419 alt="" src="http://www.shnenglu.com/images/cppblog_com/xushaohua/MultiTimerDemoimg.gif" width=639 border=0><br>图一 囑փ描述 <br><br>  方式一QVC中的WM_TIMER消息映射能进行简单的旉控制。首先调用函数SetTimer()讄定时<wbr> 间隔Q如SetTimer(0,200,NULL)即ؓ讄200ms的时间间隔。然后在应用E序中增加定时响应函?wbr> OnTimer()Qƈ在该函数中添加响应的处理语句Q用来完成到辑֮时时间的操作。这U定时方法非?wbr> 单,可以实现一定的定时功能Q但其定时功能如同Sleep()函数的g时功能一P_ֺ非常低,最?wbr> 计时_ֺ仅ؓ30msQCPU占用低,且定时器消息在多d操作pȝ中的优先U很低,不能得到及时?wbr> 应,往往不能满实时控制环境下的应用。只可以用来实现诸如位图的动态显C等对定时精度要求不高的情况。如CZ工程中的Timer1?<br>  方式二:VC中用sleep()函数实现延时Q它的单位是msQ如延时2U,用sleep(2000)。精度非?wbr> 低,最计时精度仅?0msQ用sleep函数的不利处在于延时期间不能处理其他的消息,如果旉?wbr> 长,好象死ZPCPU占用率非帔RQ只能用于要求不高的延时E序中。如CZ工程中的Timer2?br>  方式三:利用COleDateTimecdCOleDateTimeSpancȝ合WINDOWS的消息处理过E来实现U延时。如CZ工程中的Timer3和Timer3_1。以下是实现2U的延时代码Q?br>COleDateTime      start_time = COleDateTime::GetCurrentTime();<br>      COleDateTimeSpan  end_time= COleDateTime::GetCurrentTime()-start_time;<br>      while(end_time.GetTotalSeconds()< 2) //实现延时2U?br>     { <br>              MSG   msg;<br>              GetMessage(&msg,NULL,0,0);<br>              TranslateMessage(&msg); <br>              DispatchMessage(&msg);<br>              <br>             //以上四行是实现在延时或定时期间能处理其他的消息,<br>       //虽然q样可以降低CPU的占有率Q?br>             //但降低了延时或定时精度,实际应用中可以去掉?br>             end_time = COleDateTime::GetCurrentTime()-start_time;<br>      }//q样在g时的时候我们也能够处理其他的消息?nbsp;     <br>方式四:在精度要求较高的情况下,VC中可以利用GetTickCount()函数Q该函数的返回值是<wbr>  DWORD型,表示以ms为单位的计算机启动后l历的时间间隔。精度比WM_TIMER消息映射高,在较<wbr> 短的定时中其计时误差?5msQ在较长的定时中其计时误差较低,如果定时旉太长Q就好象L一PCPU占用率非帔RQ只能用于要求不高的延时E序中。如CZ工程中的Timer4和Timer4_1。下列代码可以实?0ms的精定Ӟ<br> <pre> DWORD dwStart = GetTickCount(); DWORD dwEnd = dwStart; do { dwEnd = GetTickCount()-dwStart; }while(dwEnd <50);</pre> ZGetTickCount()函数在g时或定时期间能处理其他的消息Q可以把代码改ؓQ?br> <pre> DWORD dwStart = GetTickCount(); DWORD dwEnd = dwStart; do { MSG msg; GetMessage(&msg,NULL,0,0); TranslateMessage(&msg); DispatchMessage(&msg); dwEnd = GetTickCount()-dwStart; }while(dwEnd <50);</pre> 虽然q样可以降低CPU的占有率Qƈ在g时或定时期间也能处理其他的消息,但降低了延时或定时精度?br>  方式五:与GetTickCount()函数cM的多媒体定时器函数DWORD timeGetTime(void)Q该函数定时_?wbr> 度ؓmsU,q回从Windows启动开始经q的毫秒数。微软公司在其多媒体Windows中提供了_定时器的?wbr> 层API持,利用多媒体定时器可以很精地dpȝ的当前时_q且能在非常_的时间间隔内完成一<wbr> 个事件、函数或q程的调用。不同之处在于调用DWORD timeGetTime(void) 函数之前必须?Winmm.lib <wbr> ?Mmsystem.h d到工E中Q否则在~译时提CDWORD timeGetTime(void)函数未定义。由于用该<wbr> 函数是通过查询的方式进行定时控制的Q所以,应该建立定时循环来进行定时事件的控制。如CZ工程中的Timer5和Timer5_1?br>  方式六:使用多媒体定时器timeSetEvent()函数Q该函数定时_ֺ为msU。利用该函数可以实现周期性的函数调用。如CZ工程中的Timer6和Timer6_1。函数的原型如下Q?<br> <pre> MMRESULT timeSetEventQ?UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent Q?/pre>   该函数设|一个定时回调事Ӟ此事件可以是一个一ơ性事件或周期性事件。事件一旦被Ȁz,便调用指定的回调函数Q?wbr> 成功后返回事件的标识W代码,否则q回NULL。函数的参数说明如下Q?br> <pre> uDelayQ以毫秒指定事g的周期? UresolutionQ以毫秒指定延时的精度,数D定时器事g分L率越高。缺省gؓ1ms? LpTimeProcQ指向一个回调函数? DwUserQ存攄h供的回调数据? FuEventQ指定定时器事gcdQ? TIME_ONESHOTQuDelay毫秒后只产生一ơ事? TIME_PERIODIC Q每隔uDelay毫秒周期性地产生事g? </pre>   具体应用Ӟ可以通过调用timeSetEvent()函数Q将需要周期性执行的d定义在LpTimeProc回调函数<wbr> ?如:定时采样、控制等)Q从而完成所需处理的事件。需要注意的是,d处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后,<wbr> 应及时调用timeKillEvent()之释放?<br>  方式七:对于_度要求更高的定时操作Q则应该使用QueryPerformanceFrequency()?wbr> QueryPerformanceCounter()函数。这两个函数是VC提供的仅供Windows 95及其后箋版本使用的精时间函敎ͼq要求计机从硬件上支持_定时器。如CZ工程中的Timer7、Timer7_1、Timer7_2、Timer7_3?br>QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下:<br> <pre> BOOL QueryPerformanceFrequency(LARGE_INTEGER QlpFrequency); BOOL QueryPerformanceCounter(LARGE_INTEGER QlpCount);</pre>   数据cdARGE_INTEGER既可以是一?字节长的整型敎ͼ也可以是两个4字节长的整型数的联合l构Q?wbr> 其具体用法根据编译器是否支持64位而定。该cd的定义如下:<br> <pre> typedef union _LARGE_INTEGER { struct { DWORD LowPart ;// 4字节整型? LONG HighPart;// 4字节整型? }; LONGLONG QuadPart ;// 8字节整型? }LARGE_INTEGER ;</pre>   在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的旉频率Q?wbr> 然后在需要严格定时的事g发生之前和发生之后分别调用QueryPerformanceCounter()函数Q利用两ơ获得的计数之差及时钟频率,计算Z件经<wbr> 历的_旉。下列代码实?ms的精定Ӟ<br> <pre> LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;// 获得计数器的旉频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;// 获得初始? do { QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得中止? dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq;// 获得对应的时间|单位为秒 }while(dfTim<0.001);</pre>   其定时误差不过1微秒Q精度与CPU{机器配|有兟?下面的程序用来测试函数Sleep(100)的精持l时_<br> <pre> LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;// 获得计数器的旉频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;// 获得初始? Sleep(100); QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得中止? dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq;// 获得对应的时间|单位为秒 </pre>   ׃Sleep()函数自n的误差,上述E序每次执行的结果都会有微小误差。下列代码实?微秒的精定Ӟ<br> <pre> LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; double dfMinus, dfFreq, dfTim; QueryPerformanceFrequency(&litmp); dfFreq = (double)litmp.QuadPart;// 获得计数器的旉频率 QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart;// 获得初始? do { QueryPerformanceCounter(&litmp); QPart2 = litmp.QuadPart;//获得中止? dfMinus = (double)(QPart2-QPart1); dfTim = dfMinus / dfFreq;// 获得对应的时间|单位为秒 }while(dfTim<0.000001);</pre> 其定时误差一般不过0.5微秒Q精度与CPU{机器配|有兟? <img src ="http://www.shnenglu.com/xushaohua/aggbug/37817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xushaohua/" target="_blank">neter</a> 2007-12-04 20:56 <a href="http://www.shnenglu.com/xushaohua/archive/2007/12/04/37817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Z Visual C++6.0 ?DLL ~程实现http://www.shnenglu.com/xushaohua/archive/2007/12/04/37783.htmlneterneterTue, 04 Dec 2007 05:44:00 GMThttp://www.shnenglu.com/xushaohua/archive/2007/12/04/37783.htmlhttp://www.shnenglu.com/xushaohua/comments/37783.htmlhttp://www.shnenglu.com/xushaohua/archive/2007/12/04/37783.html#Feedback1http://www.shnenglu.com/xushaohua/comments/commentRss/37783.htmlhttp://www.shnenglu.com/xushaohua/services/trackbacks/37783.html一、前a

  自从微Y推出 16 位的 Windows 操作pȝP此后每种版本?/span> Windows 操作pȝ都非怾赖于动态链接库 (DLL) 中的函数和数据,实际?/span> Windows 操作pȝ中几乎所有的内容都由 DLL 以一U或另外一UŞ式代表着Q例如显C的字体和图标存储在 GDI DLL 中、显C?/span> Windows 桌面和处理用L输入所需要的代码被存储在一?/span> User DLL 中?/span> Windows ~程所需要的大量?/span> API 函数也被包含?/span> Kernel DLL 中?/span>

  ?/span> Windows 操作pȝ中?/span> DLL 有很多优点,最主要的一Ҏ多个应用E序、甚x不同语言~写的应用程序可以共享一?/span> DLL 文gQ真正实C资源 " ׃n " Q大大羃了应用E序的执行代码,更加有效的利用了内存Q?/span> DLL 的另一个优Ҏ DLL 文g作ؓ一个单独的E序模块Q封装性、独立性好Q在软g需要升U的时候,开发h员只需要修改相应的 DLL 文g可以了Q而且Q当 DLL 中的函数改变后,只要不是参数的改?/span> , E序代码q不需要重新编译。这在编E时十分有用Q大大提高了软g开发和l护的效率?/span>

  既然 DLL 那么重要Q所以搞清楚什么是 DLL 、如何在 Windows 操作pȝ中开发?/span> DLL 是程序开发h员不得不解决的一个问题。本文针对这些问题,通过一个简单的例子Q即在一?/span> DLL 中实现比较最大、最整数这两个单函敎ͼ全面地解析了?/span> Visual C++ ~译环境下编E实?/span> DLL 的过E,文章中所用到的程序代码在 Windows98 pȝ?/span> Visual C++6.0 ~译环境下通过?/span>

  二?/strong> DLL 的概?/span>

   DLL 是徏立在客户 / 服务器通信的概念上Q包含若q函数、类或资源的库文Ӟ函数和数据被存储在一?/span> DLL Q服务器Q上q由一个或多个客户导出而用,q些客户可以是应用程序或者是其它?/span> DLL ?/span> DLL 库不同于静态库Q在静态库情况下,函数和数据被~译q一个二q制文gQ通常扩展名ؓ *.LIB Q, Visual C++ 的编译器在处理程序代码时从静态库中恢复这些函数和数据q把他们和应用程序中的其他模块组合在一L成可执行文g。这个过E称?/span> " 静态链?/span> " Q此时因为应用程序所需的全部内定w是从库中复制了出来,所以静态库本nq不需要与可执行文件一起发行?/span>

  在动态库的情况下Q有两个文gQ一个是引入库( .LIB Q文Ӟ一个是 DLL 文gQ引入库文g包含?/span> DLL 导出的函数的名称和位|, DLL 包含实际的函数和数据Q应用程序?/span> LIB 文g链接到所需要用的 DLL 文gQ库中的函数和数据ƈ不复制到可执行文件中Q因此在应用E序的可执行文g中,存放的不是被调用的函C码,而是 DLL 中所要调用的函数的内存地址Q这样当一个或多个应用E序q行是再把程序代码和被调用的函数代码链接hQ从而节省了内存资源。从上面的说明可以看出, DLL ?/span> .LIB 文g必须随应用程序一起发行,否则应用E序会产生错误?/span>

  微Y?/span> Visual C++ 支持三种 DLL Q它们分别是 Non-MFC Dll Q非 MFC 动态库Q?/span> Regular Dll Q常?/span> DLL Q?/span> Extension Dll Q扩?/span> DLL Q?/span> Non-MFC DLL 指的是不?/span> MFC 的类库结构,直接?/span> C 语言写的 DLL Q其导出的函数是标准?/span> C 接口Q能被非 MFC ?/span> MFC ~写的应用程序所调用?/span> Regular DLL: 和下q的 Extension Dlls 一P是用 MFC cd~写的,它的一个明昄特点是在源文仉有一个?/span> CWinApp 的类Q注意:此类 DLL 虽然?/span> CWinApp zQ但没有消息循环Q?/span> , 被导出的函数?/span> C 函数?/span> C++ cL?/span> C++ 成员函数Q注意不要把术语 C++ cM MFC 的微软基 C++ cȝhQ,调用常规 DLL 的应用程序不必是 MFC 应用E序Q只要是能调用类 C 函数的应用程序就可以Q它们可以是?/span> Visual C++ ?/span> Dephi ?/span> Visual Basic ?/span> Borland C {编译环境下利用 DLL 开发应用程序?/span>

  常规 DLL 又可l分成静态链接到 MFC 和动态链接到 MFC 上的Q这两种常规 DLL 的区别将在下面介l。与常规 DLL 相比Q用扩?/span> DLL 用于导出增强 MFC 基础cȝ函数或子c,用这U类型的动态链接库Q可以用来输Z个从 MFC 所l承下来的类?/span>

  扩展 DLL 是?/span> MFC 的动态链接版本所创徏的,q且它只被用 MFC cd所~写的应用程序所调用。例如你已经创徏了一个从 MFC ?/span> CtoolBar cȝzcȝ于创Z个新的工hQؓ了导个类Q你必须把它攑ֈ一?/span> MFC 扩展?/span> DLL 中。扩?/span> DLL 和常?/span> DLL 不一P它没有一个从 CWinApp l承而来的类的对象,所以,开发h员必d DLL 中的 DllMain 函数d初始化代码和l束代码?/span>

三、动态链接库的创?/font>

  ?/span> Visual C++6.0 开发环境下Q打开 FileNewProject 选项Q可以选择 Win32 Dynamic-Link Library ?/span> MFC AppWizard[dll] 来以不同的方式来创徏 Non-MFC Dll ?/span> Regular Dll ?/span> Extension Dll {不同种cȝ动态链接库?/span>

   1 Q?/span> Win32 Dynamic-Link Library 方式创徏 Non-MFC DLL 动态链接库

  每一?/span> DLL 必须有一个入口点Q这p我们?/span> C ~写的应用程序一P必须有一?/span> WINMAIN 函数一栗在 Non-MFC DLL ?/span> DllMain 是一个缺省的入口函数Q你不需要编写自q DLL 入口函数Q用q个~省的入口函数就能动态链接库被调用时得到正确的初始化。如果应用程序的 DLL 需要分配额外的内存或资源时Q或者说需要对每个q程或线E初始化和清除操作时Q需要在相应?/span> DLL 工程?/span> .CPP 文g中对 DllMain() 函数按照下面的格式书写?/span>
 

 

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
.......
case DLL_THREAD_ATTACH:
.......
case DLL_THREAD_DETACH:
.......
case DLL_PROCESS_DETACH:
.......
}
return TRUE;
}

  参数中, hMoudle 是动态库被调用时所传递来的一个指向自q句柄 ( 实际上,它是指向 _DGROUP D늚一个选择W?/span> ) Q?/span> ul_reason_for_call 是一个说明动态库被调原因的标志,当进E或U程装入或卸载动态链接库的时候,操作pȝ调用入口函数Qƈ说明动态链接库被调用的原因Q它所有的可能gؓQ?/span> DLL_PROCESS_ATTACH: q程被调用?/span> DLL_THREAD_ATTACH: U程被调用?/span> DLL_PROCESS_DETACH: q程被停止?/span> DLL_THREAD_DETACH: U程被停止; lpReserved Z留参数。到此ؓ止, DLL 的入口函数已l写了,剩下部分的实C不难Q你可以?/span> DLL 工程中加入你所惌输出的函数或变量了?/span>

  我们已经知道 DLL 是包含若q个函数的库文gQ应用程序?/span> DLL 中的函数之前Q应该先导出q些函数Q以便供l应用程序用。要导出q些函数有两U方法,一是在定义函数时用导出关键字 _declspec(dllexport) Q另外一U方法是在创?/span> DLL 文g时用模块定义文?/span> .Def 。需要读者注意的是在使用W一U方法的时候,不能使用 DEF 文g。下面通过两个例子来说明如何用这两种Ҏ创徏 DLL 文g?/span>

   1 Q用导出函数关键字 _declspec(dllexport) 创徏 MyDll.dll Q该动态链接库中有两个函数Q分别用来实现得C个数的最大和最数。在 MyDll.h ?/span> MyDLL.cpp 文g中分别输入如下原代码Q?/span>
 

//MyDLL.h
extern "C" _declspec(dllexport) int Max(int a, int b);
extern "C" _declspec(dllexport) int Min(int a, int b);
//MyDll.cpp
Qi nclude
Qi nclude"MyDll.h"
int Max(int a, int b)
{
if(a>=b)return a;
else
return b;
}
int Min(int a, int b)
{
if(a>=b)return b;
else
return a;
}

  该动态链接库~译成功后,打开 MyDll 工程中的 debug 目录Q可以看?/span> MyDll.dll ?/span> MyDll.lib 两个文g?/span> LIB 文g中包?/span> DLL 文g名和 DLL 文g中的函数名等Q该 LIB 文g只是对应?/span> DLL 文g?/span> " 映像文g " Q与 DLL 文g中, LIB 文g的长度要的多,在进行隐式链?/span> DLL 时要用到它。读者可能已l注意到?/span> MyDll.h 中有关键?/span> "extern C" Q它可以使其他编E语a讉K你编写的 DLL 中的函数?/span>

   2 Q用 .def 文g创徏工程 MyDll

  Z?/span> .def 文g创徏 DLL Q请先删除上个例子创建的工程中的 MyDll.h 文gQ保?/span> MyDll.cpp q在该文件头删除 Qi nclude MyDll.h 语句Q同时往该工E中加入一个文本文Ӟ命名?/span> MyDll.def Q再在该文g中加入如下代码:


LIBRARY MyDll
EXPORTS
Max
Min

  其中 LIBRARY 语句说明?/span> def 文g是属于相?/span> DLL 的, EXPORTS 语句下列导出的函数名U。我们可以在 .def 文g中的导出函数后加 @n Q如 Max@1 Q?/span> Min@2 Q表C导出的函数顺序号Q在q行昑ּq时可以用到它。该 DLL ~译成功后,打开工程中的 Debug 目录Q同样也会看?/span> MyDll.dll ?/span> MyDll.lib 文g?/span>

   2 Q?/span> MFC AppWizard[dll] 方式生成常规 / 扩展 DLL

  ?/span> MFC AppWizard[dll] 下生?/span> DLL 文g又有三种方式Q在创徏 DLL 是,要根据实际情况选择创徏 DLL 的方式。一U是常规 DLL 静态链接到 MFC Q另一U是常规 DLL 动态链接到 MFC 。两者的区别是:前者用的?/span> MFC 的静态链接库Q生成的 DLL 文g长度大,一般不使用q种方式Q后者?/span> MFC 的动态链接库Q生成的 DLL 文g长度;动态链接到 MFC 的规?/span> DLL 所有输出的函数应该以如下语句开始:

 

AFX_MANAGE_STATE(AfxGetStaticModuleState( )) // 此语句用来正地切换 MFC 模块状?/span>

  最后一U是 MFC 扩展 DLL Q这U?/span> DLL 特点是用来徏?/span> MFC 的派生类Q?/span> Dll 只被?/span> MFC cd所~写的应用程序所调用。前面我们已l介l过Q?/span> Extension DLLs ?/span> Regular DLLs 不一P它没有一个从 CWinApp l承而来的类的对象,~译器默认了一?/span> DLL 入口函数 DLLMain() 作ؓ?/span> DLL 的初始化Q你可以在此函数中实现初始化 , 代码如下Q?/span>
 

BOOL WINAPI APIENTRY DLLMain(HINSTANCE hinstDll Q?/span> DWORD reason Q?/span> LPVOID flmpload)
{
switch(reason)
{
……………//
初始化代码;

}
return true;
}

  参数 hinstDll 存放 DLL 的句柄,参数 reason 指明调用函数的原因, lpReserved 是一个被pȝ所保留的参数。对于隐式链接是一个非零|对于昑ּ链接值是零?/span>

  ?/span> MFC 下徏?/span> DLL 文gQ会自动生成 def 文g框架Q其它与建立传统?/span> Non-MFC DLL 没有什么区别,只要在相应的头文件写入关键字 _declspec(dllexport) 函数cd和函数名{,或在生成?/span> def 文g?/span> EXPORTS 下输入函数名可以了。需要注意的是在向其它开发h员分?/span> MFC 扩展 DLL Ӟ不要忘记提供描述 DLL 中类的头文g以及相应?/span> .LIB 文g?/span> DLL 本nQ此后开发h员就能充分利用你开发的扩展 DLL 了?br>
 应用E序使用DLL可以采用两种方式Q一U是隐式链接Q另一U是昑ּ链接。在使用DLL之前首先要知?/span>DLL中函数的l构信息?/span>Visual C++6.0?/span>VCin目录下提供了一个名?/span>Dumpbin.exe的小E序Q用它可以查?/span>DLL文g中的函数l构。另外,Windowspȝ遵循下面的搜烦序来定?/span>DLLQ?/span> 1Q包?/span>EXE文g的目录,2Q进E的当前工作目录Q?/span> 3Q?/span>Windowspȝ目录Q?/span> 4Q?/span>Windows目录Q?/span>5Q列?/span>Path环境变量中的一pd目录?/span>

  1Q隐式链?/span>

  隐式链接是在程序开始执行时将DLL文g加蝲到应用程序当中。实现隐式链接很ҎQ只要将导入函数关键?/span>_declspec(dllimport)函数名等写到应用E序相应的头文g中就可以了。下面的例子通过隐式链接调用MyDll.dll库中?/span>Min函数。首先生成一个项目ؓTestDllQ在DllTest.h?/span>DllTest.cpp文g中分别输入如下代码:
 

 

 

//Dlltest.h
#pragma comment(lib
Q?/span> "MyDll.lib")
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
//TestDll.cpp
Qi nclude
Qi nclude"Dlltest.h"
void main()
{int a;
a=min(8,10)
printf("
比较的结果ؓ %d " Q?/span> a);
}
 

  在创?/span> DllTest.exe 文g之前Q要先将 MyDll.dll ?/span> MyDll.lib 拯到当前工E所在的目录下面Q也可以拯?/span> windows ?/span> System 目录下。如?/span> DLL 使用的是 def 文gQ要删除 TestDll.h 文g中关键字 extern "C" ?/span> TestDll.h 文g中的关键?/span> Progam commit 是要 Visual C+ 的编译器?/span> link Ӟ链接?/span> MyDll.lib 文gQ当Ӟ开发h员也可以不?/span> #pragma comment(lib Q?/span> "MyDll.lib") 语句Q而直接在工程?/span> Setting->Link Object/Moduls 栏填?/span> MyDll.lib 既可?/span>

   2 Q显式链?/span>

  昑ּ链接是应用程序在执行q程中随时可以加?/span> DLL 文gQ也可以随时卸蝲 DLL 文gQ这是隐式链接所无法作到的,所以显式链接具有更好的灉|性,对于解释性语a更ؓ合适。不q实现显式链接要ȝ一些。在应用E序中用 LoadLibrary ?/span> MFC 提供?/span> AfxLoadLibrary 昑ּ的将自己所做的动态链接库调进来,动态链接库的文件名x上述两个函数的参敎ͼ此后再用 GetProcAddress() 获取惌引入的函数。自此,你就可以象用如同在应用E序自定义的函数一h调用此引入函C。在应用E序退Z前,应该?/span> FreeLibrary ?/span> MFC 提供?/span> AfxFreeLibrary 释放动态链接库。下面是通过昑ּ链接调用 DLL 中的 Max 函数的例子?/span>
 

 

Qi nclude
Qi nclude
void main(void)
{
typedef int(*pMax)(int a,int b);
typedef int(*pMin)(int a,int b);
HINSTANCE hDLL;
PMax Max
HDLL=LoadLibrary("MyDll.dll");//
加蝲动态链接库 MyDll.dll 文gQ?/span>
Max=(pMax)GetProcAddress(hDLL,"Max");
A=Max(5,8);
Printf("
比较的结果ؓ %d " Q?/span> a);
FreeLibrary(hDLL);//
卸蝲 MyDll.dll 文gQ?/span>
}

  在上例中使用cd定义关键?/span> typedef Q定义指向和 DLL 中相同的函数原型指针Q然后通过 LoadLibray() ?/span> DLL 加蝲到当前的应用E序中ƈq回当前 DLL 文g的句柄,然后通过 GetProcAddress() 函数获取导入到应用程序中的函数指针,函数调用完毕后,使用 FreeLibrary() 卸蝲 DLL 文g。在~译E序之前Q首先要?/span> DLL 文g拯到工E所在的目录?/span> Windows pȝ目录下?/span>

  使用昑ּ链接应用E序~译时不需要用相应的 Lib 文g。另外,使用 GetProcAddress() 函数Ӟ可以利用 MAKEINTRESOURCE() 函数直接使用 DLL 中函数出现的序P如将 GetProcAddress(hDLL,"Min") 改ؓ GetProcAddress(hDLL, MAKEINTRESOURCE(2)) Q函?/span> Min() ?/span> DLL 中的序h 2 Q,q样调用 DLL 中的函数速度很快Q但是要C函数的用序P否则会发生错误?/span> 



neter 2007-12-04 13:44 发表评论
]]>
ŷ˾þۺ| ҹavþþþ| ƷɫۺϾþ| ҹƷƬþӰ| ޹ƷȾþ| þҹɫƷ| þþƷĻ| ƷŮͬһþ| ۺ޾þһƷ| þù׾Ʒǿ| þ99Ʒþþôѧ| Ʒþþþþþþ| ԾþþӰԺ| ˾Ʒþ޸岻 | þɫۺ| Ʒþþþþþþþ| AVպAVþ| ֻƬþøպ| ƷŮٸaѾþ| ŷ޾Ʒ˾þ| þþ޹| þþøƵ| 99þҹɫƷվ| þþþŮ˾ƷëƬ| ŷ޾þþþƷ| þùһƬѹۿ| 9391ƷۺϾþ㽶| þAV| ޾ƷŮþ777777| þþۺϾɫۺϾ| һƷþ| ƷѸþ| þAV| ƷۺϾþþþþ97| ƷۺϾþ| þþƷȫۿ| þþþƷþþþӰԺ| ŷ˾þۺ| һþöۺ| ҹƵþþþһ | ŷպƷþþþ|