<?xml version="1.0" encoding="UTF-8" ?>
  <rss version="2.0">
    <channel>

<title>Kenneth's Blog</title>
      <link>http://kenneth.ycool.com/</link>
      <description><![CDATA[]]></description>
      <pubDate>Sun, 26 Apr 2009 14:04:22 GMT</pubDate>
      <lastBuildDate>Sun, 26 Apr 2009 14:04:22 GMT</lastBuildDate>
      <image>
        <url>http://sta.yculblog.com/images/logo/general-88x31.gif</url>
        <title>Kenneth's Blog</title>
        <link>http://kenneth.ycool.com/</link>
      </image>
<item>
        <title>C#DateTime日期格式转换</title>
        <link>http://kenneth.ycool.com/post.2963369.html</link>
        <description><![CDATA[<p>1.绑定时格式化日期方法: <br />
&lt;ASP:BOUNDCOLUMN DATAFIELD= &quot;JoinTime &quot; DATAFORMATSTRING= &quot;{0:yyyy-MM-dd} &quot; &gt; <br />
&lt;ITEMSTYLE WIDTH= &quot;18% &quot; &gt; &lt;/ITEMSTYLE &gt; <br />
&lt;/ASP:BOUNDCOLUMN &gt; </p>
<p>2.数据控件如DataGrid/DataList等的件格式化日期方法: <br />
e.Item.Cell[0].Text = Convert.ToDateTime(e.Item.Cell[0].Text).ToShortDateString(); </p>
<p>3.用String类转换日期显示格式: <br />
String.Format( &quot;yyyy-MM-dd &quot;,yourDateTime); </p>
<p>4.用Convert方法转换日期显示格式: <br />
Convert.ToDateTime(&quot;2005-8-23&quot;).ToString </p>
<p>(&quot;yyMMdd&quot;,System.Globalization.DateTimeFormatInfo.InvariantInfo); //支持繁体数据库 </p>
<p>5.直接用ToString方法转换日期显示格式: <br />
DateTime.Now.ToString(&quot;yyyyMMddhhmmss&quot;); <br />
DateTime.Now.ToString(&quot;yyyy/MM/dd hh:mm:ss&quot;) </p>
<p>6.只显示年月 <br />
DataBinder.Eval(Container.DataItem,&quot;starttime&quot;,&quot;{0:yyyy-M}&quot;) </p>
<p>7.显示时间所有部分，包括：年月日时分秒 <br />
&lt;asp:BoundColumn DataField=&quot;收款时间&quot; HeaderText=&quot;收款时间&quot; <br />
DataFormatString=&quot;{0:yyyy-MM-dd HH24:mm:ss}&quot;&gt; <br />
&lt;/asp:BoundColumn&gt;&nbsp;</p>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2963369.html</guid>
        <pubDate>Fri, 12 Sep 2008 09:09:16 GMT</pubDate>

      </item>

      <item>
        <title>如何在Vista下用Regsvr32注册dll, ocx等COM组件</title>
        <link>http://kenneth.ycool.com/post.2906782.html</link>
        <description><![CDATA[<div class="cnt" id="blog_text">最近用户反映程序无法在vista正常运行，经过调试发现是由于dll组件库未能成功注册导致， 在微软网站查找相关内容，发现N多人有同样的问题， 这里有两个办法可以解决问题 <br />
A. <br />
<br />
1.- 运行&quot;secpol.msc&quot; 或者打开&ldquo;本地安全策略&rdquo; <br />
<br />
2.- 展开 &quot;本地策略&quot; <br />
<br />
3.- 点击 &quot;安全选项&quot; <br />
<br />
4.- 在右边的面板中选择所有名称为&ldquo;用户帐户控制&rdquo;的项，设置为&ldquo;禁用&rdquo; <br />
<br />
5.- 重新启动 <br />
<br />
B. <br />
在开始菜单-&gt;所有程序-&gt;附件 找到&ldquo;命令提示符&rdquo;右键选择 &ldquo;以管理员身份运行&rdquo;打开cmd终端控制台， 在次输入 Regsvr32 dllname即可完成注册 <br />
<br />
遗憾的是到现在没有找到方法实现程序自动注册，Vista版本的Regsvr32.exe 的参数有所变化， 需要找DllInstall 入口函数， 没有试过，或许是要实现DllInstall入口函数才能像以往一样注册</div>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2906782.html</guid>
        <pubDate>Thu, 12 Jun 2008 23:06:11 GMT</pubDate>

      </item>

      <item>
        <title>Java串口通信详解</title>
        <link>http://kenneth.ycool.com/post.2901572.html</link>
        <description><![CDATA[<div style="LAYOUT-GRID:  15.6pt none">
<div style="MARGIN: 23.4pt 0cm 15.6pt">序言</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">说到开源，恐怕很少有人不挑大指称赞。学生通过开源代码学到了知识，程序员通过开源类库获得了别人的成功经验及能够按时完成手头的工程，商家通过开源软件赚到了钱&hellip;&hellip;，总之是皆大欢喜。然而开源软件或类库的首要缺点就是大多缺乏详细的说明文档和使用的例子，或者就是软件代码随便你用，就是文档，例子和后期服务收钱。这也难怪，毕竟就像某个著名NBA球员说的那样：&ldquo;我还要养家，所以千万美元以下的合同别找我谈，否则我宁可待业&rdquo;。是啊，支持开源的人也要养家，收点钱也不过分。要想既不花钱又学到知识就只能借助网络和了，我只是想抛砖引玉，为开源事业做出点微薄共献，能为你的工程解决哪怕一个小问题，也就足够了。</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">虽然我的这个系列介绍的东西不是什么Web框架，也不是什么开源服务器，但是我相信，作为一个程序员，什么样的问题都会遇到。有时候越是简单的问题反而越棘手；越是小的地方就越是找不到称手的家伙。只要你不是整天只与&ldquo;架构&rdquo;、&ldquo;构件&rdquo;、&ldquo;框架&rdquo;打交道的话，相信我所说的东西你一定会用到。</div>
</div>
<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%"><br clear="all" />
</span>
<div style="LAYOUT-GRID:  15.6pt none">
<div style="MARGIN: 7.8pt 0cm 15.6pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151864">1<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口通信简介</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">1</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151865">1.1<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>常见的</span>Java<span>串口<span>包</span></span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">1</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151866">1.2<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口包的安装（</span>Windows<span>下）</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">1</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151867">2<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口</span>API<span>概览</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">2</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151868">2.1<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>javax.comm.CommPort<span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">2</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151869">2.2<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>javax.comm.CommPortIdentifier<span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">3</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151870">2.3<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>javax.comm.SerialPort<span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">3</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151871">2.4<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口</span>API<span>实例</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">3</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 42pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151872">2.4.1<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>列举出本机所有可用串口</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">3</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 42pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151873">2.4.2<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口参数的配置</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">4</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 42pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151874">2.4.3<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口的读写</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">4</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151875">3<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口通信的通用模式及其问题</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">5</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151876">3.1<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>事件监听模型</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">5</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151877">3.2<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>串口读数据的线程模型</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">6</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 21pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151878">3.3<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>第三种方法</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">7</span></span></a></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt"><span><a href="http://writeblog.csdn.net/Editor/FCKeditor/editor/fckeditor.html?InstanceName=ctl00_ContentPlaceHolder1_EntryEditor1_richTextEditor_richTextEditor&amp;Toolbar=Default#_Toc137151879">4<span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>结束语</span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">... </span><span style="DISPLAY: none; COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">9</span></span></a></span></div>
</div>
<span style="FONT-SIZE: 12pt; LETTER-SPACING: 0.4pt"><br clear="all" />
</span>
<div style="LAYOUT-GRID:  15.6pt none">
<div><a name="_Toc137151864"><span>1<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </span></span>串口通信简介</a></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">嵌入式系统或传感器网络的很多应用和测试都需要通过PC机与嵌入式设备或传感器节点进行通信。其中，最常用的接口就是RS-232串口和并口（鉴于USB接口的复杂性以及不需要很大的数据传输量，USB接口用在这里还是显得过于奢侈，况且目前除了SUN有一个支持USB的包之外，我还没有看到其他直接支持USB的Java类库）。SUN的CommAPI分别提供了对常用的RS232串行端口和IEEE1284并行端口通讯的支持。RS-232-C(又称EIA RS-232-C，以下简称RS232)是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。RS232是一个全双工的通讯协议，它可以同时进行数据接收和发送的工作。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151865"><span>1.1&nbsp;</span>常见的Java</a><span>串口包</span></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt">目前，常见的Java串口包有SUN在1998年发布的串口通信API：comm2.0.jar（Windows下）、comm3.0.jar（Linux/Solaris）；IBM的串口通信API以及一个开源的实现。鉴于在Windows下SUN的API比较常用以及IBM的实现和SUN的在API层面都是一样的，那个开源的实现又不像两家大厂的产品那样让人放心，这里就只介绍SUN的串口通信API在Windows平台下的使用。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151866"><span>1.2&nbsp;</span>串口包的安装（Windows</a><span>下）</span></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt">到SUN的网站下载<span>javacomm20-win32.zip</span><span>，包含的东西如下所示：</span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt" align="center"><span><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/5840ccf9083347aab0632a9b79bfde3f.png" /></span></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">按照其使用说明（Readme.html）的说法，要想使用串口包进行串口通信，除了设置好环境变量之外，还要将win32com.dll复制到&lt;JDK&gt;\bin目录下；将comm.jar复制到&lt;JDK&gt;\lib；把javax.comm.properties也同样拷贝到&lt;JDK&gt;\lib目录下。然而在真正运行使用串口包的时候，仅作这些是不够的。因为通常当运行&ldquo;java MyApp&rdquo;的时候，是由JRE下的虚拟机启动MyApp的。而我们只复制上述文件到JDK相应目录下，所以应用程序将会提示找不到串口。解决这个问题的方法很简单，我们只须将上面提到的文件放到JRE相应的目录下就可以了。</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">值得注意的是，在网络应用程序中使用串口API的时候，还会遇到其他更复杂问题。有兴趣的话，你可以查看CSDN社区中&ldquo;<strong><span style="FONT-SIZE: 10pt; COLOR: #666600; LINE-HEIGHT: 150%">关于网页上</span></strong><strong><span style="FONT-SIZE: 10pt; COLOR: #666600; LINE-HEIGHT: 150%">Applet</span></strong><strong><span style="FONT-SIZE: 10pt; COLOR: #666600; LINE-HEIGHT: 150%">用</span></strong><strong><span style="FONT-SIZE: 10pt; COLOR: #666600; LINE-HEIGHT: 150%">javacomm20</span></strong><strong><span style="FONT-SIZE: 10pt; COLOR: #666600; LINE-HEIGHT: 150%">读取客户端串口的问题</span></strong>&rdquo;的帖子。</div>
<div><a name="_Toc137151867"><span>2<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </span></span>串口API</a><span>概览</span></div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151868"><span>2.1<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>javax.comm.CommPort</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 9.95pt">这是用于描述一个被底层系统支持的端口的抽象类。它包含一些高层的IO控制方法，这些方法对于所有不同的通讯端口来说是通用的。SerialPort 和ParallelPort都是它的子类，前者用于控制串行端口而后者用于控这并口，二者对于各自底层的物理端口都有不同的控制方法。这里我们只关心SerialPort。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151869"><span>2.2<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>javax.comm.CommPortIdentifier</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt">这个类主要用于对串口进行管理和设置，是对串口进行访问控制的核心类。主要包括以下方法</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 19.85pt; TEXT-INDENT: 1.15pt"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>确定是否有可用的通信端口</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 19.85pt; TEXT-INDENT: 1.15pt"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>为IO操作打开通信端口</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 19.85pt; TEXT-INDENT: 1.15pt"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>决定端口的所有权</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 19.85pt; TEXT-INDENT: 1.15pt"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>处理端口所有权的争用</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 19.85pt; TEXT-INDENT: 1.15pt"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>管理端口所有权变化引发的事件（Event）</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151870"><span>2.3<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>javax.comm.SerialPort</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">这个类用于描述一个RS-232串行通信端口的底层接口，它定义了串口通信所需的最小功能集。通过它，用户可以直接对串口进行读、写及设置工作。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151871"><span>2.4&nbsp;</span>串口API</a><span>实例</span></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">大段的文字怎么也不如一个小例子来的清晰，下面我们就一起看一下串口包自带的例子---SerialDemo中的一小段代码来加深对串口API核心类的使用方法的认识。</div>
<div style="MARGIN-TOP: 7.8pt"><strong><font size="3"><a name="_Toc137151872"><span>2.4.1<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp; </span></span>列举出本机所有可用串口</a></font></strong></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">void listPortChoices() {</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CommPortIdentifier portId;</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enumeration en = CommPortIdentifier.getPortIdentifiers();</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // iterate through the ports.</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (en.hasMoreElements()) {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; portId = (CommPortIdentifier) en.nextElement();</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(portId.getName());</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; portChoice.select(parameters.getPortName());</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">以上代码可以列举出当前系统所有可用的串口名称，我的机器上输出的结果是COM1和COM3。</div>
<div style="MARGIN-TOP: 7.8pt"><strong><font size="3"><a name="_Toc137151873"><span>2.4.2<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp; </span></span>串口参数的配置</a></font></strong></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">串口一般有如下参数可以在该串口打开以前配置进行配置：</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/09f3fe07829f44059cf7334cb5f1bc60.png" /></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">包括波特率，输入/输出流控制，数据位数，停止位和齐偶校验。</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">SerialPort sPort;</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal">try {</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sPort.setSerialPortParams(BaudRate,Databits,Stopbits,Parity);</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span>设置输入/输出控制流</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sPort.setFlowControlMode(FlowControlIn | FlowControlOut);</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (UnsupportedCommOperationException e) {}</span></div>
<div style="MARGIN-TOP: 7.8pt"><strong><font size="3"><a name="_Toc137151874"><span>2.4.3<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp; </span></span>串口的读写</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">对串口读写之前需要先打开一个串口：</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(<span style="COLOR: #ff6600">PortName);</span></div>
<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal">try {</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SerialPort &nbsp;sPort = (SerialPort) portId.open(&quot;</span>串口所有者名称&quot;, 超时等待时间);</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (PortInUseException e) {//</span>如果端口被占用就抛出这个异常</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new SerialConnectionException(e.getMessage());</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">//用于对串口写数据</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">OutputStream os = new BufferedOutputStream(sPort.getOutputStream());</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">os.write(int data);</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">//用于从串口读数据</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">InputStream is = new BufferedInputStream(sPort.getInputStream());</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">int receivedData = is.read();</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">读出来的是int型，你可以把它转换成需要的其他类型。</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">这里要注意的是，由于Java语言没有无符号类型，即所有的类型都是带符号的，在由byte到int的时候应该尤其注意。因为如果byte的最高位是1，则转成int类型时将用1来占位。这样，原本是10000000的byte类型的数变成int型就成了1111111110000000，这是很严重的问题，应该注意避免。</div>
<div><a name="_Toc137151875"><span>3<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </span></span>串口通信的通用模式及其问题</a></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">终于唠叨完我最讨厌的基础知识了，下面开始我们本次的重点--串口应用的研究。由于向串口写数据很简单，所以这里我们只关注于从串口读数据的情况。通常，串口通信应用程序有两种模式，一种是实现SerialPortEventListener接口，监听各种串口事件并作相应处理；另一种就是建立一个独立的接收线程专门负责数据的接收。由于这两种方法在某些情况下存在很严重的问题（至于什么问题这里先卖个关子<span>J</span>），所以我的实现是采用第三种方法来解决这个问题。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151876"><span>3.1&nbsp;</span>事件监听模型</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">现在我们来看看事件监听模型是如何运作的</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">：</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt 40.85pt; TEXT-INDENT: -19.85pt"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>首先需要在你的端口控制类（例如SManager）加上&ldquo;implements SerialPortEventListener&rdquo;</div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: -19.85pt; LINE-HEIGHT: normal"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>在初始化时加入如下代码：</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal">try {</div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SerialPort sPort.addEventListener(SManager);</span></div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (TooManyListenersException e) {</span></div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sPort.close();</span></div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;throw new SerialConnectionException(&quot;too many listeners added&quot;);</span></div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="MARGIN: 0cm 0cm 0pt 40.8pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sPort.notifyOnDataAvailable(true);</span></div>
<div style="MARGIN: 0cm 0cm 0pt 40.85pt; TEXT-INDENT: -19.85pt; LINE-HEIGHT: normal"><span>l<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>覆写public void serialEvent(SerialPortEvent e)方法，在其中对如下事件进行判断：</div>
<div style="MARGIN: 0cm 0cm 0pt 19.85pt; TEXT-INDENT: 21pt" align="left">BI -通讯中断.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　CD -载波检测.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　CTS -清除发送.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　DATA_AVAILABLE -有数据到达.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　DSR -数据设备准备好.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　FE -帧错误.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　OE -溢位错误.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　OUTPUT_BUFFER_EMPTY -输出缓冲区已清空.</div>
<div style="TEXT-INDENT: 21pt" align="left">　　PE -奇偶校验错.</div>
<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal">RI -　振铃指示.</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">一般最常用的就是DATA_AVAILABLE--串口有数据到达事件。也就是说当串口有数据到达时，你可以在serialEvent中接收并处理所收到的数据。然而在我的实践中，遇到了一个十分严重的问题。</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">首先描述一下我的实验：我的应用程序需要接收传感器节点从串口发回的查询数据，并将结果以图标的形式显示出来。串口设定的波特率是115200，川口每隔128毫秒返回一组数据（大约是30字节左右），周期（即持续时间）为31秒。实测的时候在一个周期内应该返回4900多个字节，而用事件监听模型我最多只能收到不到1500字节，不知道这些字节都跑哪里去了，也不清楚到底丢失的是那部分数据。值得注意的是，这是我将serialEvent()中所有处理代码都注掉，只剩下打印代码所得的结果。数据丢失的如此严重是我所不能忍受的，于是我决定采用其他方法。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151877"><span>3.2&nbsp;</span>串口读数据的线程模型</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">这个模型顾名思义，就是将接收数据的操作写成一个线程的形式:</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">public void startReadingDataThread() {</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread readDataProcess = new Thread(new Runnable() {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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; while (newData != -1) {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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;&nbsp;&nbsp;&nbsp;&nbsp; newData = is.read();</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(newData);</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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;&nbsp;&nbsp;&nbsp;&nbsp; //</span>其他的处理过程</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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;&nbsp;&nbsp;&nbsp; &hellip;&hellip;&hellip;.</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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; } catch (IOException ex) {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println(ex);</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readDataProcess.start();</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">}</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">在我的应用程序中，我将收到的数据打包放到一个缓存中，然后启动另一个线程从缓存中获取并处理数据。两个线程以生产者&mdash;消费者模式协同工作，数据的流向如下图所示：</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">&nbsp;<span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"> </v:shapetype></span></v:shapetype></span></div>
<p style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt" align="center"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/serial%20data%20flow.JPG" /></p>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"></v:shapetype></span></v:shapetype></span>这样，我就圆满解决了丢数据问题。然而，没高兴多久我就又发现了一个同样严重的问题：虽然这回不再丢数据了，可是原本一个周期（31秒）之后，传感器节电已经停止传送数据了，但我的串口线程依然在努力的执行读串口操作，在控制台也可以看见收到的数据仍在不断的打印。原来，由于传感器节点发送的数据过快，而我的接收线程处理不过来，所以InputStream就先把已到达却还没处理的字节缓存起来，于是就导致了明明传感器节点已经不再发数据了，而控制台却还能看见数据不断打印这一奇怪的现象。唯一值得庆幸的是最后收到数据确实是4900左右字节，没出现丢失现象。然而当处理完最后一个数据的时候已经快1分半钟了，这个时间远远大于节点运行周期。这一延迟对于一个实时的显示系统来说简直是灾难！</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">后来我想，是不是由于两个线程之间的同步和通信导致了数据接收缓慢呢？于是我在接收线程的代码中去掉了所有处理代码，仅保留打印收到数据的语句，结果依然如故。看来并不是线程间的通信阻碍了数据的接收速度，而是用线程模型导致了对于发送端数据发送速率过快的情况下的数据接收延迟。这里申明一点，就是对于数据发送速率不是如此快的情况下前面者两种模型应该还是好用的，只是特殊情况还是应该特殊处理。</div>
<div style="MARGIN: 23.4pt 0cm 15.6pt 49.6pt"><strong><font size="4"><a name="_Toc137151878"><span>3.3&nbsp;</span>第三种方法</a></font></strong></div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">痛苦了许久（Boss天天催我<span>L</span>）之后，偶然的机会，我听说TinyOS中（又是开源的）有一部分是和我的应用程序类似的串口通信部分，于是我下载了它的1.x版的Java代码部分，参考了它的处理方法。解决问题的方法说穿了其实很简单，就是从根源入手。根源不就是接收线程导致的吗，那好，我就干脆取消接收线程和作为中介的共享缓存，而直接在处理线程中调用串口读数据的方法来解决问题（什么，为什么不把处理线程也一并取消？----都取消应用程序界面不就锁死了吗？所以必须保留）于是程序变成了这样：</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal">public byte[] getPack(){</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true) {</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;// PacketLength</span>为数据包长度</div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] msgPack = new byte[PacketLength];</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; PacketLength; i++){</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( (newData = is.read()) != -1){ </span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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; msgPack[i] = (byte) newData;</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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; System.out.println(msgPack[i]);</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return msgPack;</span></div>
<div style="TEXT-INDENT: 21pt; LINE-HEIGHT: normal"><span>&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; }</span></div>
<div style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; LINE-HEIGHT: normal">}</div>
<div style="MARGIN: 7.8pt 0cm 15.6pt; TEXT-INDENT: 21pt">在处理线程中调用这个方法返回所需要的数据序列并处理之，这样不但没有丢失数据的现象行出现，也没有数据接收延迟了。这里唯一需要注意的就是当串口停止发送数据或没有数据的时候is.read()一直都返回-1，如果一旦在开始接收数据的时候发现-1就不要理它，继续接收，直到收到真正的数据为止。</div>
</div>
<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%"><br clear="all" />
</span>
<div style="MARGIN: 18pt 0cm 12pt 21.25pt"><a name="_Toc127120974"><span><span>4<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </span></span>结束语</span></a></div>
<span style="FONT-SIZE: 10.5pt">本文介绍了串口通信的基本知识，以及常用的几种模式。通过实践，提出了一些问题，并在最后加以解决。值得注意的是对于第一种方法，我曾将传感器发送的时间由</span><span style="FONT-SIZE: 10.5pt">128</span><span style="FONT-SIZE: 10.5pt">毫秒增加到</span><span style="FONT-SIZE: 10.5pt">512</span><span style="FONT-SIZE: 10.5pt">毫秒，仍然有很严重的数据丢失现象发生，所以如果你的应用程序需要很精密的结果，传输数据的速率又很快的话，就最好不要用第一种方法。对于第二种方法，由于是线程导致的问题，所以对于不同的机器应该会有不同的表现，对于那些处理多线程比较好的机器来说，应该会好一些。但是我的机器是</span><span style="FONT-SIZE: 10.5pt">Inter </span><span style="FONT-SIZE: 10.5pt">奔四</span><span style="FONT-SIZE: 10.5pt">3.0</span><span style="FONT-SIZE: 10.5pt">双核</span><span style="FONT-SIZE: 10.5pt">CPU+512DDR</span><span style="FONT-SIZE: 10.5pt">内存，这样都延迟这么厉害，还得多强的</span><span style="FONT-SIZE: 10.5pt">CPU</span><span style="FONT-SIZE: 10.5pt">才行啊？所以对于数据量比较大的传输来说，还是用第三种方法吧。不过这个世界问题是很多的，而且未知的问题比已知的问题多的多，说不定还有什么其他问题存在，欢迎你通过下面的联系方式和我一起研究。</span>&nbsp;...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2901572.html</guid>
        <pubDate>Wed, 04 Jun 2008 09:06:51 GMT</pubDate>

      </item>

      <item>
        <title>适应多种智能电表通信规约的无线抄表解决方案</title>
        <link>http://kenneth.ycool.com/post.2901364.html</link>
        <description><![CDATA[摘 要： 阐述了一种适应多种智能电表通信规约的无线数传模块，可嵌入多功能电表和电力负控装置，完成远程无线抄表和远动控制的解决方案。射频模块采用深圳市友讯达通讯设备有限公司的FC-201/E，该模块采用窄带调频方式，数据调制采用FFSK(MSK)。数据双向传输可靠，误码率低，有效地保证了电能表等智能仪表的数据传输。可广泛应用于远程抄表和其它智能仪表集抄领域。<br />
关键词： 远程无线抄表 无线数传模块 电能表通信规约<br />
<br />
无线抄表在发达国家和地区早已盛行，抄表车在用户电表附近行走一遍，电表的各种数据就抄入抄表车电脑中。然而无线抄表在国内才刚起步，在集抄过程中数据传输的通讯规约，也是多种多样。虽然电力部在1998年发布了其行业标准--多功能电能表通信规约，但由于种种历史原因，到目前普及仍不理想。怎样更好地实现无线数传的包容性和开放透明，是应用人员及各生产厂家最为关心的。<br />
本文介绍一套能包容多种通信规约的数传体制，它符合我国电力远端无线数据传输实情的嵌入式无线抄表方案，已成功用于多家电表厂，取得了较好的社会效益。<br />
<br />
1 我国电能表数据通信规约介绍<br />
<br />
在我国运行的众多电能表通信规约，就其根本来说，是从VAN_COMM规约演变而来。VAN_COMM规约是美国FERRANTI公司开发的信息变换标准，适用于&quot;主从式&quot;或&quot;问答式&quot;处理环境，主站(通常一个)主动向子站(多个)询问，子站只被动回答。以下分别介绍我国有代表性的两种通信规约。<br />
1.1 多功能电能表通信规约(国家电力行业标准)<br />
该规约为主－从结构的半双工通信方式，手持单元或其它数据终端为主站，费率装置为从站，每个费率装置均有各自的地址编码。通信网络的建立和解除均由主站发出的信息帧来控制。每帧由帧起始符、从站地址域、控制码、数据长度、数据域、帧信息纵向校验及帧结束符等7个域组成，每部分由若干字节组成。<br />
a、 字节格式：采用RS-232的规约<br />
每字节含8位2进制码，传输时加上一个起始位(0)，一个偶校验位和一个停止位(1)，共11位，其传输序列如下图<br />
<div align="center"><img height="55" width="300" alt="" src="http://www.weeqoo.com/UploadFile/2007/10/19/200710191215153105.jpg" /><br />
</div>
<div align="left"><img height="236" width="208" alt="" src="http://www.weeqoo.com/UploadFile/2007/10/19/200710191215156618.jpg" /><br />
其中： L&le;200<br />
<br />
1.2 &quot;湖南&quot;通信规约<br />
&quot;湖南&quot;通信规约是指湖南威胜电表厂的通信规约，该规约的主要特征如下：<br />
通信接口：标准异步RS-232/RS-485<br />
字格式：1位起始位、8位起始位、偶校验、一位停止位；<br />
波特率：300bps/600bps/1200bps/4800bps、默认1200bps；<br />
帧格式： </div>
<p>址域 1byte<br />
命令标志 1byte<br />
标志地址域 2byte<br />
数据长度L 1byte<br />
数据域 <br />
累加校验和 1byte<br />
结束码 0DH<br />
<br />
其中：L&le;255<br />
以上介绍的两种规约是国内电能表的最具有代表性的通信规约。从以上的规约中，可总结以下共同点：<br />
&middot; 通信接口为RS-232/RS-485接口；<br />
&middot; 帧长度：&le;256byte；<br />
&middot; 波特率：300～9600bps可变；<br />
&middot; 双向半双工通信方式；<br />
&middot; 帧长度不确定。<br />
<br />
2 FC-201/E无线抄表解决方案<br />
<br />
2.1 FC-201/E无线数传模块的工作原理<br />
FC-201/无线数传模块是一种模组式结构的小型双向数传电台，内置高性能单片机，信号调制解调器，VHF/UHF频段射频模块及RS-232标准通讯接口。将RS-232接口输入的数据进行FFSK(MSK)调制，经射频模块调频后发射出去；接收端射频模块接收到射频信号后，经过接收机数字信号处理后还原为数据，回送给用户系统，以此完成两个用户之间的双向数据无线传输。其原理如图1所示。<br />
</p>
<div align="left"><img height="188" width="369" alt="" src="http://www.weeqoo.com/UploadFile/2007/10/19/200710191215152605.jpg" /><br />
数据的收发过程如下：<br />
(1)数据发送如图2所示。 <br />
(2)数据接收如图3所示。<br />
<div align="center"><img height="306" width="229" alt="" src="http://www.weeqoo.com/UploadFile/2007/10/19/200710191215159347.jpg" /></div>
<div align="left"><img height="335" width="177" alt="" src="http://www.weeqoo.com/UploadFile/2007/10/19/200710191215157089.jpg" /><br />
2.2 FC-201/E无线抄表解决方案<br />
FC-201/E无线抄表解决方案的基本设计思想是在现有的各种多功能电表基本不变的情况下，用无线的方式来实现集抄中心或手抄器，对各种表计的无线数据集抄。FC-201/E无线抄表解决方案的系统构成图如图4所示。<br />
<br />
</div>
<div align="left"><img height="235" width="303" alt="" src="http://www.weeqoo.com/UploadFile/2007/10/19/200710191215158061.jpg" /><br />
其工作原理如下：<br />
由集抄中心(手抄器或集抄器)根据各个电表的通信协议，对各电表进行查询和呼叫，各电表的地址分配与定义由多功能电表的协议确定。集抄中心的集抄内容及过程可通过上层软件download。当集抄中心要获取某一块多功能电表的数据时，将带该表地址码的数据以RS-232的方式传送给FC-201/E，中心站的FC-201/E在收到RS-232的信息后，即转换为无线信号发射出去。外围站的无线多功能电表在常态都处于接收状态(即listen)，当收到本身的地址信息后，即执行集抄中心的指令，并将中心需求的数据发送给中心。<br />
2.3用FC-201/E实现无线抄表系统的技术关键点 <br />
用FC-201/E实现无线抄表必须解决以下几个问题：<br />
(1)数据传输的可靠性<br />
由于多功能电表的安装环境参差不齐，而且电磁环境也各不相同，为实现无线数据的可靠性传输FC-201/E采用了以下措施：<br />
&middot;采用窄带的通信方案<br />
通信带宽为25kHz，接收及发射的带外抑制比&ge;60dB，由此使得干扰信号落入带内的概率大大降低。<br />
&middot;采用调频的通信体制<br />
FC-201/E采用调频的通信体制，在通信过程中基带信号的特性在无线的传输过程中体现在无线信号的领域特性上。因此在传输过程中，接收点的信号特性不会因为接收点信号强度的变化而变化，大大地提高了抗多径能力，同时也可适应多种安装环境。<br />
&middot;采用了纠错、检错措施<br />
<br />
(2)数据协议的包容性<br />
由前面的介绍可知，我国多功能电表的通信协议同出一辙，但其具体内容却各具特色。大多数厂家在以前的设计过程中，多以有线或红外的通信方式为基础，作为无线数传。要实现数据的可靠传输，应以帧结构方式进行传输，然而采用传统的定帧传输已很难适应要求。为了提高数据传输的包容性，在FC-201/E的设计中采用了以下的包容性设计方案：<br />
&middot;空中数据动态组帧；<br />
&middot;接口速率自适应；<br />
&middot;用户数据全透明。<br />
由此设计的FC-201/E已完全抛开了各种电能表通信规约本身的内涵，而实现了表与集抄器之间各种通信规约的全透明传输。<br />
(3)数据传输的时效性 <br />
在FC-201/E无线抄表解决方案中，数据传输的时效性是一个非常关键的参数，该参数直接关系到系统的容量。为了提高FC-201/E数据传输的时效性，首先在调制方式上采用了FFSK(MSK)的调制方式，从而支持了2400bps的传输速率，同时在硬件上采用发射机的快速启动技术，保证了发射机的开启时间&le;25ms。<br />
<br />
<p>FS-201/E的接收灵敏度高达0.25&mu;V，发射功率为50～100mW，这样即可实现500～800m的有效距离传输。FC-201/E的体积为46mm&times;72mm&times;14mm，因此可以方便地嵌入到电表中。<br />
FC-201/E可适应多种通信规约，各种智能电表只需将其RS-232/RS-485或UART与FC-201/E的通信接口相联，即可方便地实现无线电表集抄。<br />
随着现代计算机技术和无线通讯技术的迅猛发展，全面实现用电管理和集中抄表的现代化已成为必然趋势。尤其是在电力线载波抄表，IC卡预付费电表以及红外抄表在实用中遇到不少问题的情况下，坚信FC-201/E会给无线远程抄表开创一个新的局面。</p>
</div>
</div>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2901364.html</guid>
        <pubDate>Wed, 04 Jun 2008 01:06:29 GMT</pubDate>

      </item>

      <item>
        <title>公交非接触IC卡读写器的应用设计</title>
        <link>http://kenneth.ycool.com/post.2901353.html</link>
        <description><![CDATA[<p><font face="Courier">摘 要：采用PHILIPS公司的Mifare卡作IC卡，设计以射频技术为核心，以单片机为控制器的IC卡读写器在公交自动收费系统中的应用。制作的IC卡读写器可以实现制卡、售卡、自动收费等功能，具有安全、实用、方便、快捷、可靠性高的特点，解决了城市公共交通服务行业既频繁又琐碎的收费管理问题，有广泛的应用前景。</font></p>
<p><font face="Courier">关键词：单片机 非接触式IC卡 读写器</font></p>
<p><font face="Courier">一、IC卡读写器概述</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 目前经常接触到的IC卡有两种：接触式的和非接触式的IC卡。接触式的IC卡通过机械触点从读写器获取能量和交换数据；非接触式IC卡通过线圈射频感应从读写器获取能量和交换数据，所以又称射频卡。目前在社会上常见的是接触式IC卡。它具有存储量大（以兆为单位），保密功能强（有多重密码设置和认证功能），可实现一卡多用。但是，这类卡的读写操作速度较慢，操作也不方便，每次读写时必须把卡正确地插入到读写器的口槽才能完成数据交换，这样，在公交、考勤等需要频繁读写卡的场合就很不方便，而且读写器的触点和卡片上IC卡的触脚暴露在外,容易损坏和搞脏而造成接触不良。</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 非接触式IC卡是根据射频电磁感应原理产生的。它的读写操作只需将卡片放在读写器附近一定的距离之内就能实现数据交换，无需任何接触，使用中非常方便、快捷，不易损坏。因此，在公交、门禁、校园、企事业等人事管理、娱乐场所等方面有广泛的应用前景。目前我国引进的射频 IC卡主要有PHILIPS公司的Mifare和ATMEL公司的Temic卡。下面以PHILIPS公司的Mifare卡为主、介绍城市公交自动售票IC卡读写器的实现方法。</font></p>
<p><font face="Courier">二、工作原理</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 非接触式IC 卡读写器以射频识别技术为核心，读写器内主要使用了1片Mifare卡专用的读写处理芯片--MMM微模块。它是一个小型的最大操作距离达20～30mm的Mifare读/写设备的核心器件，其功能包括调制、解调、产生射频信号、安全管理和防碰撞机制。内部结构分为射频区和接口区：射频区内含调制解调器和电源供电电路，直接与天线连接；接口区有与单片机相连的端口，还具有与射频区相连的收/发器、16字节的数据缓冲器、存放64对传输密钥的ROM、存放3套密钥的只写存储器以及进行三次证实和数据加密的密码机、防碰撞处理的防碰撞模块和控制单元。这是与射频卡实现无线通信的核心模块，也是读写器读写Mifare卡的关键接口芯片。读写器工作时，不断地向外发出一组固定频率的电磁波（13.6MHz），当有卡靠近时，卡片内有一个LG串联谐振电路，其频率与读写器的发射频率相同，这样在电磁波的激励下，LG谐振电路产生共振，从而使电容充电有了电荷。在这个电容另一端，接有一个单向导电的电子泵，将电容内的电荷送到另一个电容内存储。当电容器充电达到2V时，此电容就作为电源为卡片上的其他电路提供工作电压，将卡内数据发射出去或接收读写器发出的数据与保存。</font></p>
<p><font face="Courier">三、硬件组成</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 公交收费系统结构复杂，环节较多，因此，公交非接触IC 卡的读写器至少应包括公交售卡机、公交车载机和公交制卡机三个读写器。除了售卡机要求有键盘外，其余的硬件组成大体相同。图1为非接触IC卡及其读写器硬件电路原理图，主要由MMM微模块、单片机、键盘、显示、存储器、天线和监控电路以及与PC机通信的TC232串行通信接口电路等部分组成。</font></p>
<p align="center"><font face="Courier"><img border="0" alt="" src="http://img.hc360.com/ec/Info/images/200522561.jpg" /></font></p>
<p><font face="Courier">（1）单片机系统</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 单片机采用89C52。它片内有8KB的ROM，256字节的RAM以及有32个I/O口。P1口与串行器件24C64和显示、报警电路连接；P0口与MMM微模块相连，用作数据线；P2口用作4&times;4键盘；P3口用于读写控制和中断。</font></p>
<p><font face="Courier">（2）键盘电路</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 键盘接口电路用P2口接成4&times;4结构，共16个键。其中数字键10个，功能键2个，退格键和回车键各1个，有2个键暂时未用。 功能键有查询和通信两键。</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 查询键：售卡员可以通过此键查询售卡金额和售卡记录数。&nbsp;&nbsp;&nbsp;&nbsp; 通信键：由于读写器的存储量有限，因此读写器每售卡一段时间，应将读写器中的数据通过RS-232串行接口与PC机通信，以便回放和清空读写器中的数据。数据回放到PC机中后，通过分析处理，形成各种报表，以便公交公司及时掌握售卡情况。</font></p>
<p><font face="Courier">（3）显示电路</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 显示部分采用数码显示，利用串行输入BCD码--十进制译码驱动显示器件MC14499来完成与单片机系统的显示接口，以显示读写器工作状态、输入的数据或读出IC卡中所剩余以及出错信息等。此器件主要有1个20位移位寄存器、1个锁存器、1个多路输出器。多路输出器输出的BCD码经段译码器译码后，换成七段码（abcdefg）和小数点DP送到段驱动器输出。</font></p>
<p><font face="Courier">（4）存储器</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 读写器中设计了存储器。存储器选用24CXX系列的串行E2PROM。在售卡机中主要存放卡号、售卡员号、售卡金额、售卡日期、售卡总金额和售卡总记录数；在车载机中主要存放乘客IC卡号、司机号和刷卡总数等信息。显示用MC14499驱动4位共阴数码管。正常工作后，每隔一段时间要把读写器拿到公交管理中心将读写器储存的信息回放到PC机中保存处理。读写器中存储器可采用24C64，其存储量为8KB，如有需要也可用容量更大的存储器如24C128或24C256等。</font></p>
<p><font face="Courier">（5）监控电路&nbsp;&nbsp;&nbsp;&nbsp; 监控电路采用DS1232L芯片。它是个看门狗定时器，其功能是：上电和掉电时给89C52产生RESET信号；看门狗对系统进行监控，防止死机。</font></p>
<p><font face="Courier">（6）非接触式IC卡</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 非接触式IC卡选用Mifare卡。其工作频率为 13.6MHz，存储量为1KB分16区，每区2套密码，每个区的存储区域相互独立，因此每区可用作一种用途（第0区一般不用）以实现一卡多用。由于Mifare卡密码验证机制严密，保存的信息比较可靠安全，可以擦写几万次。</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; Mifare卡的16个区，每区又分4块，每块16字节。在售卡机中用第1区作用户储值块，其中第0块存放身份号，第1~2块存放价值，第3块存放两套6字节密码和4字节读写访问条件。<br />
</font><font face="Courier">四、程序设计</font></p>
<p align="center"><img border="0" alt="" src="http://img.hc360.com/ec/Info/images/200522562.jpg" /></p>
<p>&nbsp;</p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 下面以售卡机为主介绍软件设计方法。</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 考虑到售卡金额的安全管理，公交公司事先必须制作好两种IC票卡：一种是用户IC票卡，另一种是售卡员的售票IC卡。这两种卡可使用相同区号，但密码和访问条件完全不同，不会混淆。售卡员要进行售卡时，必须先到公交公司办理一张售票IC卡，才有售卡的资格。售票IC卡内存放了售卡员身份号、允许售卡的最大金额、两套6字节密码和4字节读写访问条件。售卡员售卡时，每充值一张卡必须从自己的售票IC卡中减去售卡金额，加到用户IC卡中。当售票IC卡金额减到零后，要到公交公司结账，并再对售票IC卡充值记账。这样，可使公交公司的售卡网点分布得多而不乱，又可方便用户充值加卡，可有效地防止售票人员账目不清而造成的资金流失。程序主要包括IC卡读写操作程序、键盘扫描程序、显示程序、存储器读写程序和通信程序。</font></p>
<p><font face="Courier">1.主程序</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 主程序主要完成系统变量的初始化，循环扫描键盘，检测操作IC卡，将操作结果存储和显示。在售卡机中使用了8KB的24C64作存储器，主要存储的内容有：售卡机机号（1字节）、售卡总金额（3字节）和总记录（2字节）。售出的每张卡的记录包含：用户卡身份号（4字节）、售卡日期（2字节）、加卡金额（1字节）和售卡人编号（1字节）。因此最大能存储1023张售卡记录。主程序流程如图2所示，读写器对IC卡的操作流程如图3所示。</font></p>
<p align="center"><font face="Courier"><img border="0" alt="" src="http://img.hc360.com/ec/Info/images/200522563.jpg" /></font></p>
<p><font face="Courier">2.键盘扫描程序</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 键盘扫描采用反转法读键：先从P2口的高4位输出零电平，从P2口的低4位读取键盘状态；再从P2口的低4位输出零电平，从P2口的高4位读取键盘状态，将两次读取的结果组合起来就可以得到当前按键的特征码（见程序中TABLE表）。有了这张表就可以编程，将它们转换成顺序码。用当前读得的特征码来顺序查表，用一单元记录查找次数。当在表中查到有该特征码时，它的位置（即查找次数）就是对应的顺序码。对应的键盘查键程序如下： KEY: MOV P2,#0FH ；用反转法查键<br />
MOV A,P2<br />
ANL A,#0FH<br />
MOV B,A<br />
MOV P2,#0F0H<br />
MOV A,P2<br />
ANL A,#0F0H<br />
ORL A,B<br />
CJNE A,#0FFH,KEY1<br />
RET ；无键按下<br />
KEY1: MOV B,A ；有键按下，存键码<br />
MOV DPTR,#TABLE<br />
MOV R3,#0FFH ；存顺序码单元初始化<br />
KEY2: INC R3<br />
MOV A,R3<br />
MOVC A,@A+DPTR<br />
CJNE A,B,KEY3 ；判键码，求顺序码<br />
MOV A,R3 ；若找到键码，存顺序码<br />
RET<br />
KEY3: CJNE A,#0FFH,KEY2；判是否查完<br />
RET ；已查完，键码未找到，以无按键处理<br />
TABLE: DB 77H,7BH,0BBH ；按键特征码表<br />
DB 0DBH,7DH,0BDH<br />
DB 0DDH,7EH,0BEH<br />
DB 0DEH,0B7H,0D7H<br />
DB 0EEH,0EDH,0EBH<br />
DB 0E7H,0C7H,0FFH</font></p>
<p><font face="Courier">3.显示程序</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 根据图1，在显示电路中，用P1口的3根I/O口线（P1.0、P1.1、P1.2）分别提供时钟信号（CLK）、串行数据（DA）和使能信号（EN）。MC14499每一次可接收20位串行输入数据，前4位用于控制数码管的小数点显示，后16位是4个数码管的BCD码输入数据。在每帧数据传送之前，必须将EN置0；然后传送20位数据，数据传送完后，再将EN置1。显示程序如下：</font></p>
<p><font face="Courier">DISP: CLR P1.0 ； 清CLK<br />
CLR P1.2 ；清EN<br />
MOV R2,#04 ；置传送位数<br />
MOV A,#00<br />
LCALL W14499 ；调送数显示<br />
MOV A,@R1 ；读要显示的数<br />
MOV R2,#08 ；置传送位数<br />
LCALL W14499<br />
INC R1<br />
MOV A,@R1<br />
MOV R2,#08 ； 置传送位数<br />
LCALL W14499<br />
SETB P1.2 ；置EN位<br />
RET<br />
W14499: SETB P1.0 ； 清CLK<br />
RLC A ；准备逐位送数显示<br />
MOV P1.1,C ； 将数移入DA<br />
CLR P1.0 ； 清CLK<br />
DJNZ R2,W14499<br />
RET</font></p>
<p><font face="Courier">4.串行E2PROM读写程序</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 24C64为I2C总线的E2PROM。SCL为400kHz时钟线，SDA为双向数据线，A2、A1、A0三位为片选地址，即I2C总线上最多可并联8个串行E2PROM芯片。对E2PROM的操作方式由读写控制命令字决定，如图4所示。其中&quot;1010&quot;为4位读写控制码，R/W为读写控制位：&quot;0&quot;为写操作，&quot;1&quot;为读操作。所以结合图1可知A2H为写控制命令字，A3H为读控制命令字。</font></p>
<p align="center"><font face="Courier"><img border="0" alt="" src="http://img.hc360.com/ec/Info/images/200522564.jpg" /></font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 对存储器写操作，首先，单片机向24C64发一个START命令，产生开始条件。然后，发写命令控制字（如A2H）。当24C64接到命令后，进入一个写周期，再由单片机发送存储地址，即确定数据写入到存储器的哪个地址，随后，单片机将要存储的数据送入到SDA数据线上。写周期结束时，单片机再发一停止位（STOP）。</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 对存储器读操作，首先，单片机向24C64发一个START命令，产生开始条件。然后发写命令控制字（如A2H）。当24C64接到命令后，进入一个写周期，再由单片机发送存储地址。存储地址发送成功后，单片机又向24C64发一个START命令，产生开始条件，然后发读命令控制字（A3H）。当24C64接到命令后，进入一个读周期，单片机从SDA数据线上读出指定存储地址中的数据。读周期结束时，单片机再发一停止位（STOP）。（程序略）</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 值得注意的是，对存储器操作时，每读写一个字节，单片机必须送一个应答位（ACK），释放一下SDA数据线，以便存储器能继续接收数据。</font></p>
<p><font face="Courier">5.通信程序</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 在读写器中，单片机与PC机之间的通信主要由TC232来实现TTL电平（0～5V）与RS232电平（+10～－10V）的转换（电路见图1），以完成售卡机保存的售卡记录的传送。通信格式设置为：采用串行工作方式1，波特率为9600baud， 1个起始位，8位数据位，1个停止位，采取和校验方式。读写器中，单片机程序可采用C语言进行编程。C语言有功能丰富的库函数，运算速度快、编译效率高、可移植性好、软件的可读性强，便于改进和扩充（程序略）。</font></p>
<p><font face="Courier">&nbsp;&nbsp;&nbsp; 为提高在公交系统的适应能力，包括用户的各类特殊要求，抗干扰，抗恶劣环境，除硬件上采用监控电路外，在软件</font><font face="Courier">上还采取了指令冗余和软件陷阱。</font></p>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2901353.html</guid>
        <pubDate>Wed, 04 Jun 2008 00:06:56 GMT</pubDate>

      </item>

      <item>
        <title>做上位机部分一般使用什么工具？</title>
        <link>http://kenneth.ycool.com/post.2901345.html</link>
        <description><![CDATA[我指的是开发工具，比如VC,VB,Delphi等可以吗？ 请列举几个常用的开发工具，并稍加比较其优缺点。 <br />
谢谢。 <br />
<br />
另：我将要做的上位机属于测控仪表类，用CCD现场采集图象，和上位机通信，上位机要具有界面设计和逻辑判断处理和显示等设计。整个系统必须可以在线工作，能及时响应现场的变化。
<div class="f14 wr"><strong>问题补充：</strong>我在现场见过用PAC Opto 22开发的上位机，好象是专门做仪表方面的。所以，各位请不要局限于我提到的VC,VB,Delphi。其它常用工具也可以。 <br />
谢谢！<br />
<br />
<div class="ico">
<div class="ibest"></div>
</div>
<strong>最佳答案</strong><br />
我认为用VB比较好些，我就是用VB解决任何工业自动化上位机监控方面问题的，VB无所不能，包括实时打印功能。 <br />
1、设计出来的监控画面比较容易且美观； <br />
2、VB容易上手； <br />
3、对于实时采集监控系统，定要进行对实时数据的存储与历史查询，最好用ACCESS数据库，而VB与ACCESS有比较好的联系，比较与编程，DELPHI其实对ACCESS也较容易实现，但其语句太过于麻烦，如总是要输入BEGIN...END之类的； <br />
4、DELPHI与Windows不是同一家公司的产品，有些控件不通用，所以系统设计出来后有可能会兼容性不好。</div>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2901345.html</guid>
        <pubDate>Wed, 04 Jun 2008 00:06:25 GMT</pubDate>

      </item>

      <item>
        <title>Win32串口编程</title>
        <link>http://kenneth.ycool.com/post.2900523.html</link>
        <description><![CDATA[作者：<a href="mailto:han_yao_xu@163.com">韩耀旭</a>
<p><a href="http://www.vckbase.com/code/downcode.asp?id=3002">下载源代码</a></p>
<p>　　在工业控制中，工控机（一般都基于Windows平台）经常需要与智能仪表通过串口进行通信。串口通信方便易行，应用广泛。<br />
一般情况下，工控机和各智能仪表通过RS485总线进行通信。RS485的通信方式是半双工的，只能由作为主节点的工控PC机依次轮询网络上的各智能控制单元子节点。每次通信都是由PC机通过串口向智能控制单元发布命令，智能控制单元在接收到正确的命令后作出应答。<br />
　　在Win32下，可以使用两种编程方式实现串口通信，其一是使用ActiveX控件，这种方法程序简单，但欠灵活。其二是调用Windows的API函数，这种方法可以清楚地掌握串口通信的机制，并且自由灵活。本文我们只介绍API串口通信部分。<br />
　　串口的操作可以有两种操作方式：同步操作方式和重叠操作方式（又称为异步操作方式）。同步操作时，API函数会阻塞直到操作完成以后才能返回（在多线程方式中，虽然不会阻塞主线程，但是仍然会阻塞监听线程）；而重叠操作方式，API函数会立即返回，操作在后台进行，避免线程的阻塞。</p>
<p>无论那种操作方式，一般都通过四个步骤来完成：<br />
（1） <a href="http://www.vckbase.com/document/viewdoc/?id=1734#打开串口">打开串口</a><br />
（2） <a href="http://www.vckbase.com/document/viewdoc/?id=1734#配置串口">配置串口</a><br />
（3） <a href="http://www.vckbase.com/document/viewdoc/?id=1734#读写串口">读写串口</a><br />
（4） <a href="http://www.vckbase.com/document/viewdoc/?id=1734#关闭串口">关闭串口</a></p>
<p>（1） <a name="打开串口">打开串口</a> </p>
<p>　　Win32系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台，都是用API函数CreateFile来打开或创建的。该函数的原型为： </p>
<pre>HANDLE CreateFile( LPCTSTR lpFileName,
                  DWORD dwDesiredAccess,
                  DWORD dwShareMode,
                  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                  DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
</pre>
<ul>
 <li>lpFileName：将要打开的串口逻辑名，如&ldquo;COM1&rdquo;； </li>
 <li>dwDesiredAccess：指定串口访问的类型，可以是读取、写入或二者并列； </li>
 <li>dwShareMode：指定共享属性，由于串口不能共享，该参数必须置为0； </li>
 <li>lpSecurityAttributes：引用安全性属性结构，缺省值为NULL； </li>
 <li>dwCreationDistribution：创建标志，对串口操作该参数必须置为OPEN_EXISTING； </li>
 <li>dwFlagsAndAttributes：属性描述，用于指定该串口是否进行异步操作，该值为FILE_FLAG_OVERLAPPED，表示使用异步的I/O；该值为0，表示同步I/O操作； </li>
 <li>hTemplateFile：对串口而言该参数必须置为NULL； </li>
</ul>
<p>同步I/O方式打开串口的示例代码： </p>
<pre>	HANDLE hCom;  //全局变量，串口句柄
	hCom=CreateFile(&quot;COM1&quot;,//COM1口
		GENERIC_READ|GENERIC_WRITE, //允许读和写
		0, //独占方式
		NULL,
		OPEN_EXISTING, //打开而不是创建
		0, //同步方式
		NULL);
	if(hCom==(HANDLE)-1)
	{
		AfxMessageBox(&quot;打开COM失败!&quot;);
		return FALSE;
	}
	return TRUE;

</pre>
重叠I/O打开串口的示例代码：
<pre>	HANDLE hCom;  //全局变量，串口句柄
	hCom =CreateFile(&quot;COM1&quot;,  //COM1口
             GENERIC_READ|GENERIC_WRITE, //允许读和写
             0,  //独占方式
             NULL,
             OPEN_EXISTING,  //打开而不是创建
             FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式
             NULL);
	if(hCom ==INVALID_HANDLE_VALUE)
	{
		AfxMessageBox(&quot;打开COM失败!&quot;);
		return FALSE;
	}
	   return TRUE;
</pre>
（2）、<a name="配置串口">配置串口</a>
<p>　　在打开通讯设备句柄后，常常需要对串口进行一些初始化配置工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、数据位数、奇偶校验和停止位数等信息。在查询或配置串口的属性时，都要用DCB结构来作为缓冲区。<br />
　　一般用CreateFile打开串口后，可以调用GetCommState函数来获取串口的初始配置。要修改串口的配置，应该先修改DCB结构，然后再调用SetCommState函数设置串口。<br />
　　DCB结构包含了串口的各项参数设置，下面仅介绍几个该结构常用的变量： </p>
<pre>typedef struct _DCB{
   &hellip;&hellip;&hellip;
   //波特率，指定通信设备的传输速率。这个成员可以是实际波特率值或者下面的常量值之一：
   DWORD BaudRate; 
CBR_110，CBR_300，CBR_600，CBR_1200，CBR_2400，CBR_4800，CBR_9600，CBR_19200， CBR_38400， 
CBR_56000， CBR_57600， CBR_115200， CBR_128000， CBR_256000， CBR_14400

DWORD fParity; // 指定奇偶校验使能。若此成员为1，允许奇偶校验检查 
   &hellip;
BYTE ByteSize; // 通信字节位数，4&mdash;8
BYTE Parity; //指定奇偶校验方法。此成员可以有下列值：
EVENPARITY 偶校验     NOPARITY 无校验
MARKPARITY 标记校验   ODDPARITY 奇校验
BYTE StopBits; //指定停止位的位数。此成员可以有下列值：
ONESTOPBIT 1位停止位   TWOSTOPBITS 2位停止位
ONE5STOPBITS   1.5位停止位
   &hellip;&hellip;&hellip;
  } DCB;
winbase.h文件中定义了以上用到的常量。如下：
#define NOPARITY            0
#define ODDPARITY           1
#define EVENPARITY          2
#define ONESTOPBIT          0
#define ONE5STOPBITS        1
#define TWOSTOPBITS         2
#define CBR_110             110
#define CBR_300             300
#define CBR_600             600
#define CBR_1200            1200
#define CBR_2400            2400
#define CBR_4800            4800
#define CBR_9600            9600
#define CBR_14400           14400
#define CBR_19200           19200
#define CBR_38400           38400
#define CBR_56000           56000
#define CBR_57600           57600
#define CBR_115200          115200
#define CBR_128000          128000
#define CBR_256000          256000
</pre>
GetCommState函数可以获得COM口的设备控制块，从而获得相关参数：
<pre>BOOL GetCommState(
   HANDLE hFile, //标识通讯端口的句柄
   LPDCB lpDCB //指向一个设备控制块（DCB结构）的指针
  );
SetCommState函数设置COM口的设备控制块：
BOOL SetCommState(
   HANDLE hFile, 
   LPDCB lpDCB 
  );
</pre>
　　除了在BCD中的设置外，程序一般还需要设置I/O缓冲区的大小和超时。Windows用I/O缓冲区来暂存串口输入和输出的数据。如果通信的速率较高，则应该设置较大的缓冲区。调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。
<pre>BOOL SetupComm(

    HANDLE hFile,	// 通信设备的句柄 
    DWORD dwInQueue,	// 输入缓冲区的大小（字节数） 
    DWORD dwOutQueue	// 输出缓冲区的大小（字节数）
   );
</pre>
　　在用ReadFile和WriteFile读写串行口时，需要考虑超时问题。超时的作用是在指定的时间内没有读入或发送指定数量的字符，ReadFile或WriteFile的操作仍然会结束。<br />
　　要查询当前的超时设置应调用GetCommTimeouts函数，该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。<br />
　　读写串口的超时有两种：间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延。总超时是指读写操作总共花费的最大时间。写操作只支持总超时，而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读写操作的超时。<br />
COMMTIMEOUTS结构的定义为：
<pre>typedef struct _COMMTIMEOUTS {   
    DWORD ReadIntervalTimeout; //读间隔超时
    DWORD ReadTotalTimeoutMultiplier; //读时间系数
    DWORD ReadTotalTimeoutConstant; //读时间常量
    DWORD WriteTotalTimeoutMultiplier; // 写时间系数
    DWORD WriteTotalTimeoutConstant; //写时间常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
</pre>
COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是：<br />
总超时＝时间系数&times;要求读/写的字符数＋时间常量 <br />
例如，要读入10个字符，那么读操作的总超时的计算公式为：<br />
读总超时＝ReadTotalTimeoutMultiplier&times;10＋ReadTotalTimeoutConstant <br />
可以看出：间隔超时和总超时的设置是不相关的，这可以方便通信程序灵活地设置各种超时。 <br />
<br />
如果所有写超时参数均为0，那么就不使用写超时。如果ReadIntervalTimeout为0，那么就不使用读间隔超时。如果ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都为0，则不使用读总超时。如果读间隔超时被设置成MAXDWORD并且读时间系数和读时间常量都为0，那么在读一次输入缓冲区的内容后读操作就立即返回，而不管是否读入了要求的字符。<br />
　　在用重叠方式读写串口时，虽然ReadFile和WriteFile在完成操作以前就可能返回，但超时仍然是起作用的。在这种情况下，超时规定的是操作的完成时间，而不是ReadFile和WriteFile的返回时间。<br />
配置串口的示例代码：
<pre>	SetupComm(hCom,1024,1024); //输入缓冲区和输出缓冲区的大小都是1024

	COMMTIMEOUTS TimeOuts;
	//设定读超时
	TimeOuts.ReadIntervalTimeout=1000;
	TimeOuts.ReadTotalTimeoutMultiplier=500;
	TimeOuts.ReadTotalTimeoutConstant=5000;
	//设定写超时
	TimeOuts.WriteTotalTimeoutMultiplier=500;
	TimeOuts.WriteTotalTimeoutConstant=2000;
	SetCommTimeouts(hCom,&amp;TimeOuts); //设置超时

	DCB dcb;
	GetCommState(hCom,&amp;dcb);
	dcb.BaudRate=9600; //波特率为9600
	dcb.ByteSize=8; //每个字节有8位
	dcb.Parity=NOPARITY; //无奇偶校验位
	dcb.StopBits=TWOSTOPBITS; //两个停止位
	SetCommState(hCom,&amp;dcb);

	PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
</pre>
在读写串口之前，还要用PurgeComm()函数清空缓冲区，该函数原型：
<pre>BOOL PurgeComm(

    HANDLE hFile,	//串口句柄
    DWORD dwFlags	// 需要完成的操作
   );	
</pre>
参数dwFlags指定要完成的操作，可以是下列值的组合：
<pre>PURGE_TXABORT	  中断所有写操作并立即返回，即使写操作还没有完成。
PURGE_RXABORT	  中断所有读操作并立即返回，即使读操作还没有完成。
PURGE_TXCLEAR	  清除输出缓冲区
PURGE_RXCLEAR	  清除输入缓冲区
</pre>
（3）、<a name="读写串口">读写串口</a>
<p>我们使用ReadFile和WriteFile读写串口，下面是两个函数的声明： </p>
<pre>BOOL ReadFile(

    HANDLE hFile,	//串口的句柄
    
    // 读入的数据存储的地址，
    // 即读入的数据将存储在以该指针的值为首地址的一片内存区
    LPVOID lpBuffer,	
    DWORD nNumberOfBytesToRead,	// 要读入的数据的字节数
    
    // 指向一个DWORD数值，该数值返回读操作实际读入的字节数
    LPDWORD lpNumberOfBytesRead,	
    
    // 重叠操作时，该参数指向一个OVERLAPPED结构，同步操作时，该参数为NULL。
    LPOVERLAPPED lpOverlapped 	
   );	
BOOL WriteFile(

    HANDLE hFile,	//串口的句柄
    
    // 写入的数据存储的地址，
    // 即以该指针的值为首地址的nNumberOfBytesToWrite
    // 个字节的数据将要写入串口的发送数据缓冲区。
    LPCVOID lpBuffer,	
    
    DWORD nNumberOfBytesToWrite,	//要写入的数据的字节数
    
    // 指向指向一个DWORD数值，该数值返回实际写入的字节数
    LPDWORD lpNumberOfBytesWritten,	
    
    // 重叠操作时，该参数指向一个OVERLAPPED结构，
    // 同步操作时，该参数为NULL。
    LPOVERLAPPED lpOverlapped 	
   );
</pre>
　　在用ReadFile和WriteFile读写串口时，既可以同步执行，也可以重叠执行。在同步执行时，函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞，从而导致效率下降。在重叠执行时，即使操作还未完成，这两个函数也会立即返回，费时的I/O操作在后台进行。<br />
　　ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定，如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志，那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的；如果未指定重叠标志，则读写操作应该是同步的。ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。<br />
　　ReadFile函数只要在串口输入缓冲区中读入指定数量的字符，就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区，而且要等这些字符从串行口送出去后才算完成操作。<br />
　　如果操作成功，这两个函数都返回TRUE。需要注意的是，当ReadFile和WriteFile返回FALSE时，不一定就是操作失败，线程应该调用GetLastError函数分析返回的结果。例如，在重叠操作时如果操作还未完成函数就返回，那么函数就返回FALSE，而且GetLastError函数返回ERROR_IO_PENDING。这说明重叠操作还未完成。<br />
<br />
同步方式读写串口比较简单，下面先例举同步方式读写串口的代码：
<pre>//同步读串口
char str[100];
DWORD wCount;//读取的字节数
BOOL bReadStat;
bReadStat=ReadFile(hCom,str,100,&amp;wCount,NULL);
if(!bReadStat)
{
	AfxMessageBox(&quot;读串口失败!&quot;);
	return FALSE;
}
return TRUE;

//同步写串口

	char lpOutBuffer[100];
	DWORD dwBytesWrite=100;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	BOOL bWriteStat;
	ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat);
	bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,&amp; dwBytesWrite,NULL);
	if(!bWriteStat)
	{
		AfxMessageBox(&quot;写串口失败!&quot;);
	}
	PurgeComm(hCom, PURGE_TXABORT|
		PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
</pre>
在重叠操作时,操作还未完成函数就返回。 <br />
<br />
　　重叠I/O非常灵活，它也可以实现阻塞（例如我们可以设置一定要读取到一个数据才能进行到下一步操作）。有两种方法可以等待操作完成：一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员；另一种方法是调用GetOverlappedResult函数等待，后面将演示说明。<br />
下面我们先简单说一下OVERLAPPED结构和GetOverlappedResult函数：<br />
OVERLAPPED结构<br />
OVERLAPPED结构包含了重叠I/O的一些信息，定义如下：
<pre>typedef struct _OVERLAPPED { // o  
    DWORD  Internal; 
    DWORD  InternalHigh; 
    DWORD  Offset; 
    DWORD  OffsetHigh; 
    HANDLE hEvent; 
} OVERLAPPED;
</pre>
　　在使用ReadFile和WriteFile重叠操作时，线程需要创建OVERLAPPED结构以供这两个函数使用。线程通过OVERLAPPED结构获得当前的操作状态，该结构最重要的成员是hEvent。hEvent是读写事件。当串口使用异步通讯时，函数返回时操作可能还没有完成，程序可以通过检查该事件得知是否读写完毕。<br />
　　当调用ReadFile, WriteFile 函数的时候，该成员会自动被置为无信号状态；当重叠操作完成后，该成员变量会自动被置为有信号状态。
<pre>GetOverlappedResult函数
BOOL GetOverlappedResult(
    HANDLE hFile,	// 串口的句柄  
    
    // 指向重叠操作开始时指定的OVERLAPPED结构
    LPOVERLAPPED lpOverlapped,	
    
    // 指向一个32位变量，该变量的值返回实际读写操作传输的字节数。
    LPDWORD lpNumberOfBytesTransferred,	
    
    // 该参数用于指定函数是否一直等到重叠操作结束。
    // 如果该参数为TRUE，函数直到操作结束才返回。
    // 如果该参数为FALSE，函数直接返回，这时如果操作没有完成，
    // 通过调用GetLastError()函数会返回ERROR_IO_INCOMPLETE。
    BOOL bWait 	
   );	
</pre>
该函数返回重叠操作的结果，用来判断异步操作是否完成，它是通过判断OVERLAPPED结构中的hEvent是否被置位来实现的。<br />
<br />
异步读串口的示例代码：
<pre>char lpInBuffer[1024];
DWORD dwBytesRead=1024;
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED m_osRead;
memset(&amp;m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat);
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
if(!dwBytesRead)
return FALSE;
BOOL bReadStatus;
bReadStatus=ReadFile(hCom,lpInBuffer,
					 dwBytesRead,&amp;dwBytesRead,&amp;m_osRead);

if(!bReadStatus) //如果ReadFile函数返回FALSE
{
	if(GetLastError()==ERROR_IO_PENDING)
	//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作	
	{
		WaitForSingleObject(m_osRead.hEvent,2000);
		//使用WaitForSingleObject函数等待，直到读操作完成或延时已达到2秒钟
		//当串口读操作进行完毕后，m_osRead的hEvent事件会变为有信号
		PurgeComm(hCom, PURGE_TXABORT|
			PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
		return dwBytesRead;
	}
	return 0;
}
PurgeComm(hCom, PURGE_TXABORT|
		  PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return dwBytesRead;
</pre>
　　对以上代码再作简要说明：在使用ReadFile 函数进行读操作前，应先使用ClearCommError函数清除错误。ClearCommError函数的原型如下：
<pre>BOOL ClearCommError(

    HANDLE hFile,	// 串口句柄
    LPDWORD lpErrors,	// 指向接收错误码的变量
    LPCOMSTAT lpStat	// 指向通讯状态缓冲区
   );	
</pre>
该函数获得通信错误并报告串口的当前状态，同时，该函数清除串口的错误标志以便继续输入、输出操作。<br />
参数lpStat指向一个COMSTAT结构，该结构返回串口状态信息。 COMSTAT结构 COMSTAT结构包含串口的信息，结构定义如下：
<pre>typedef struct _COMSTAT { // cst  
    DWORD fCtsHold : 1;   // Tx waiting for CTS signal 
    DWORD fDsrHold : 1;   // Tx waiting for DSR signal 
    DWORD fRlsdHold : 1;  // Tx waiting for RLSD signal 
    DWORD fXoffHold : 1;  // Tx waiting, XOFF char rec''d 
    DWORD fXoffSent : 1;  // Tx waiting, XOFF char sent 
    DWORD fEof : 1;       // EOF character sent 
    DWORD fTxim : 1;      // character waiting for Tx 
    DWORD fReserved : 25; // reserved 
    DWORD cbInQue;        // bytes in input buffer 
    DWORD cbOutQue;       // bytes in output buffer 
} COMSTAT, *LPCOMSTAT; 
</pre>
本文只用到了cbInQue成员变量，该成员变量的值代表输入缓冲区的字节数。<br />
<br />
　　最后用PurgeComm函数清空串口的输入输出缓冲区。
<p>　　这段代码用WaitForSingleObject函数来等待OVERLAPPED结构的hEvent成员，下面我们再演示一段调用GetOverlappedResult函数等待的异步读串口示例代码： </p>
<pre>char lpInBuffer[1024];
DWORD dwBytesRead=1024;
	BOOL bReadStatus;
	DWORD dwErrorFlags;
	COMSTAT ComStat;
OVERLAPPED m_osRead;

	ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat);
	if(!ComStat.cbInQue)
		return 0;
	dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
	bReadStatus=ReadFile(hCom, lpInBuffer,dwBytesRead,
		&amp;dwBytesRead,&amp;m_osRead);
	if(!bReadStatus) //如果ReadFile函数返回FALSE
	{
		if(GetLastError()==ERROR_IO_PENDING)
		{
			GetOverlappedResult(hCom,
				&amp;m_osRead,&amp;dwBytesRead,TRUE);
           // GetOverlappedResult函数的最后一个参数设为TRUE，
           //函数会一直等待，直到读操作完成或由于错误而返回。

			return dwBytesRead;
		}
		return 0;
	}
	return dwBytesRead;
</pre>
异步写串口的示例代码：
<pre>char buffer[1024];
DWORD dwBytesWritten=1024;
	DWORD dwErrorFlags;
	COMSTAT ComStat;
OVERLAPPED m_osWrite;
	BOOL bWriteStat;

	bWriteStat=WriteFile(hCom,buffer,dwBytesWritten,
		&amp;dwBytesWritten,&amp;m_OsWrite);
	if(!bWriteStat)
	{
		if(GetLastError()==ERROR_IO_PENDING)
		{
			WaitForSingleObject(m_osWrite.hEvent,1000);
			return dwBytesWritten;
		}
		return 0;
	}
	return dwBytesWritten;
</pre>
（4）、<a name="关闭串口">关闭串口</a>
<p>　　利用API函数关闭串口非常简单，只需使用CreateFile函数返回的句柄作为参数调用CloseHandle即可： </p>
<pre>BOOL CloseHandle(
    HANDLE hObject; //handle to object to close 
);
</pre>
串口编程的一个实例
<p>　　为了让您更好地理解串口编程,下面我们分别编写两个例程（见附带的源码部分）,这两个例程都实现了工控机与百特显示仪表通过RS485接口进行的串口通信。其中第一个例程采用同步串口操作,第二个例程采用异步串口操作。<br />
　　我们只介绍软件部分，RS485接口接线方法不作介绍，感兴趣的读者可以查阅相关资料。</p>
<p>例程1</p>
<p>　　打开VC++6.0，新建基于对话框的工程RS485Comm，在主对话框窗口IDD_RS485COMM_DIALOG上添加两个按钮，ID分别为IDC_SEND和IDC_RECEIVE，标题分别为&ldquo;发送&rdquo;和&ldquo;接收&rdquo;；添加一个静态文本框IDC_DISP，用于显示串口接收到的内容。<br />
<br />
在RS485CommDlg.cpp文件中添加全局变量： </p>
<pre>HANDLE hCom;  //全局变量，串口句柄
</pre>
在RS485CommDlg.cpp文件中的OnInitDialog()函数添加如下代码：
<pre>	// TODO: Add extra initialization here
	hCom=CreateFile(&quot;COM1&quot;,//COM1口
		GENERIC_READ|GENERIC_WRITE, //允许读和写
		0, //独占方式
		NULL,
		OPEN_EXISTING, //打开而不是创建
		0, //同步方式
		NULL);
	if(hCom==(HANDLE)-1)
	{
		AfxMessageBox(&quot;打开COM失败!&quot;);
		return FALSE;
	}

	SetupComm(hCom,100,100); //输入缓冲区和输出缓冲区的大小都是1024

	COMMTIMEOUTS TimeOuts;
	//设定读超时
	TimeOuts.ReadIntervalTimeout=MAXDWORD;
	TimeOuts.ReadTotalTimeoutMultiplier=0;
	TimeOuts.ReadTotalTimeoutConstant=0;
	//在读一次输入缓冲区的内容后读操作就立即返回，
	//而不管是否读入了要求的字符。


	//设定写超时
	TimeOuts.WriteTotalTimeoutMultiplier=100;
	TimeOuts.WriteTotalTimeoutConstant=500;
	SetCommTimeouts(hCom,&amp;TimeOuts); //设置超时

	DCB dcb;
	GetCommState(hCom,&amp;dcb);
	dcb.BaudRate=9600; //波特率为9600
	dcb.ByteSize=8; //每个字节有8位
	dcb.Parity=NOPARITY; //无奇偶校验位
	dcb.StopBits=TWOSTOPBITS; //两个停止位
	SetCommState(hCom,&amp;dcb);

	PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
</pre>
分别双击IDC_SEND按钮和IDC_RECEIVE按钮，添加两个按钮的响应函数：
<pre>void CRS485CommDlg::OnSend() 
{
	// TODO: Add your control notification handler code here
	// 在此需要简单介绍百特公司XMA5000的通讯协议：
	//该仪表RS485通讯采用主机广播方式通讯。
	//串行半双工，帧11位，1个起始位(0)，8个数据位，2个停止位(1)
	//如：读仪表显示的瞬时值，主机发送：DC1 AAA BB ETX
	//其中：DC1是标准ASCII码的一个控制符号，码值为11H(十进制的17)
	//在XMA5000的通讯协议中，DC1表示读瞬时值
	//AAA是从机地址码，也就是XMA5000显示仪表的通讯地址
	//BB为通道号，读瞬时值时该值为01
	//ETX也是标准ASCII码的一个控制符号，码值为03H
	//在XMA5000的通讯协议中，ETX表示主机结束符

	char lpOutBuffer[7];
	memset(lpOutBuffer,''{post.abstract}'',7); //前7个字节先清零
	lpOutBuffer[0]=''\x11'';  //发送缓冲区的第1个字节为DC1
	lpOutBuffer[1]=''0'';  //第2个字节为字符0(30H)
	lpOutBuffer[2]=''0''; //第3个字节为字符0(30H)
	lpOutBuffer[3]=''1''; // 第4个字节为字符1(31H)
	lpOutBuffer[4]=''0''; //第5个字节为字符0(30H)
	lpOutBuffer[5]=''1''; //第6个字节为字符1(31H)
	lpOutBuffer[6]=''\x03''; //第7个字节为字符ETX
	//从该段代码可以看出，仪表的通讯地址为001	
	DWORD dwBytesWrite=7;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	BOOL bWriteStat;
	ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat);
	bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,&amp; dwBytesWrite,NULL);
	if(!bWriteStat)
	{
		AfxMessageBox(&quot;写串口失败!&quot;);
	}

}
void CRS485CommDlg::OnReceive() 
{
	// TODO: Add your control notification handler code here

	char str[100];
	memset(str,''{post.abstract}'',100);
	DWORD wCount=100;//读取的字节数
	BOOL bReadStat;
	bReadStat=ReadFile(hCom,str,wCount,&amp;wCount,NULL);
	if(!bReadStat)
		AfxMessageBox(&quot;读串口失败!&quot;);
	PurgeComm(hCom, PURGE_TXABORT|
		PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
	m_disp=str;
	UpdateData(FALSE);
	
}
</pre>
您可以观察返回的字符串，其中有和仪表显示值相同的部分，您可以进行相应的字符串操作取出仪表的显示值。<br />
打开ClassWizard,为静态文本框IDC_DISP添加CString类型变量m_disp，同时添加WM_CLOSE的相应函数：
<pre>void CRS485CommDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
    CloseHandle(hCom);	//程序退出时关闭串口
	CDialog::OnClose();
}
</pre>
程序的相应部分已经在代码内部作了详细介绍。连接好硬件部分，编译运行程序，细心体会串口同步操作部分。
<p>例程2</p>
<p>　　打开VC++6.0，新建基于对话框的工程RS485Comm，在主对话框窗口IDD_RS485COMM_DIALOG上添加两个按钮，ID分别为IDC_SEND和IDC_RECEIVE，标题分别为&ldquo;发送&rdquo;和&ldquo;接收&rdquo;；添加一个静态文本框IDC_DISP，用于显示串口接收到的内容。在RS485CommDlg.cpp文件中添加全局变量： </p>
<pre>HANDLE hCom; //全局变量，</pre>
<p>串口句柄在RS485CommDlg.cpp文件中的OnInitDialog()函数添加如下代码： </p>
<pre>	hCom=CreateFile(&quot;COM1&quot;,//COM1口
		GENERIC_READ|GENERIC_WRITE, //允许读和写
		0, //独占方式
		NULL,
		OPEN_EXISTING, //打开而不是创建
		FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式
		NULL);
	if(hCom==(HANDLE)-1)
	{
		AfxMessageBox(&quot;打开COM失败!&quot;);
		return FALSE;
	}

	SetupComm(hCom,100,100); //输入缓冲区和输出缓冲区的大小都是100

	COMMTIMEOUTS TimeOuts;
	//设定读超时
	TimeOuts.ReadIntervalTimeout=MAXDWORD;
	TimeOuts.ReadTotalTimeoutMultiplier=0;
	TimeOuts.ReadTotalTimeoutConstant=0;
	//在读一次输入缓冲区的内容后读操作就立即返回，
	//而不管是否读入了要求的字符。


	//设定写超时
	TimeOuts.WriteTotalTimeoutMultiplier=100;
	TimeOuts.WriteTotalTimeoutConstant=500;
	SetCommTimeouts(hCom,&amp;TimeOuts); //设置超时

	DCB dcb;
	GetCommState(hCom,&amp;dcb);
	dcb.BaudRate=9600; //波特率为9600
	dcb.ByteSize=8; //每个字节有8位
	dcb.Parity=NOPARITY; //无奇偶校验位
	dcb.StopBits=TWOSTOPBITS; //两个停止位
	SetCommState(hCom,&amp;dcb);

	PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
</pre>
分别双击IDC_SEND按钮和IDC_RECEIVE按钮，添加两个按钮的响应函数：
<pre>void CRS485CommDlg::OnSend() 
{
	// TODO: Add your control notification handler code here
	OVERLAPPED m_osWrite;
	memset(&amp;m_osWrite,0,sizeof(OVERLAPPED));
	m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);


	char lpOutBuffer[7];
	memset(lpOutBuffer,''{post.abstract}'',7);
	lpOutBuffer[0]=''\x11'';
	lpOutBuffer[1]=''0'';
	lpOutBuffer[2]=''0'';
	lpOutBuffer[3]=''1'';
	lpOutBuffer[4]=''0'';
	lpOutBuffer[5]=''1'';
	lpOutBuffer[6]=''\x03'';
	
	DWORD dwBytesWrite=7;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	BOOL bWriteStat;
	ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat);
	bWriteStat=WriteFile(hCom,lpOutBuffer,
		dwBytesWrite,&amp; dwBytesWrite,&amp;m_osWrite);

	if(!bWriteStat)
	{
		if(GetLastError()==ERROR_IO_PENDING)
		{
			WaitForSingleObject(m_osWrite.hEvent,1000);
		}
	}

}

void CRS485CommDlg::OnReceive() 
{
	// TODO: Add your control notification handler code here
	OVERLAPPED m_osRead;
	memset(&amp;m_osRead,0,sizeof(OVERLAPPED));
	m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

	COMSTAT ComStat;
	DWORD dwErrorFlags;
	
	char str[100];
	memset(str,''{post.abstract}'',100);
	DWORD dwBytesRead=100;//读取的字节数
	BOOL bReadStat;

	ClearCommError(hCom,&amp;dwErrorFlags,&amp;ComStat);
	dwBytesRead=min(dwBytesRead, (DWORD)ComStat.cbInQue);
	bReadStat=ReadFile(hCom,str,
		dwBytesRead,&amp;dwBytesRead,&amp;m_osRead);
	if(!bReadStat)
	{
		if(GetLastError()==ERROR_IO_PENDING)
	    //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
		{
			WaitForSingleObject(m_osRead.hEvent,2000);
		    //使用WaitForSingleObject函数等待，直到读操作完成或延时已达到2秒钟
		    //当串口读操作进行完毕后，m_osRead的hEvent事件会变为有信号
		}
	}

	PurgeComm(hCom, PURGE_TXABORT|
		PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
	m_disp=str;
	UpdateData(FALSE);
}
</pre>
打开ClassWizard,为静态文本框IDC_DISP添加CString类型变量m_disp，同时添加WM_CLOSE的相应函数：
<pre>void CRS485CommDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
    CloseHandle(hCom);	//程序退出时关闭串口
	CDialog::OnClose();
}
</pre>
您可以仔细对照这两个例程，细心体会串口同步操作和异步操作的区别。
<p>好了，就到这吧，祝您好运。 </p>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2900523.html</guid>
        <pubDate>Mon, 02 Jun 2008 07:06:04 GMT</pubDate>

      </item>

      <item>
        <title>Unix/Linux下C/C++开发技术概览</title>
        <link>http://kenneth.ycool.com/post.2900360.html</link>
        <description><![CDATA[<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><strong style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 18pt; FONT-FAMILY: 黑体">Unix/Linux</span></strong><strong style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 18pt; FONT-FAMILY: 黑体">下<span lang="EN-US">C/C++</span>开发技术概览<span lang="EN-US"><o:p></o:p></span></span></strong></p>
<h1 style="MARGIN: 17pt 0cm 16.5pt 18pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo1; tab-stops: list 18.0pt"><span lang="EN-US" style="FONT-SIZE: 15pt; LINE-HEIGHT: 240%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">1.<span style="FONT: 7pt 'Times New Roman'"> </span></span></span><span style="FONT-SIZE: 15pt; LINE-HEIGHT: 240%; FONT-FAMILY: 黑体">平台差异简介<span lang="EN-US"><o:p></o:p></span></span></h1>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是当前两大主流操作系统平台，基于</span><span lang="EN-US">C/C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的开发人员经常会面临这两个平台之间的移植的问题。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作为一个开发式的系统，其下有出现了很多个分支，包括</span><span lang="EN-US">Sun</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">IBM</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">AIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">HP Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">SCO Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">Free BSD</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、苹果的</span><span lang="EN-US">MAC OS</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以及开源的</span><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等。对于这些</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的分支操作系统，其实现又有很大的差别，因此开发人员又要针对这些不同的系统进行移植。本文的目的就是介绍一下</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台之间的差别，并简单介绍一下不同</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">分支操作系统之间的差别，在移植开发过程中的一些注意事项，同时简要介绍一下</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下开发的一般流程和常用的开发调试工具。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关于平台之间的差异，主要是</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台之间的差异，这里着重介绍一下这两个平台在</span><span lang="EN-US">C/C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发中存在的差异，其间会穿插介绍一些</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不同分支之间的差异。</span></p>
<h2 style="MARGIN: 13pt 0cm"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><font face="Arial">1.1</font></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">语言特性的差异</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言特性的差异，指的是不同操作系统平台中，实现</span><span lang="EN-US">C++/C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时的一些细微的差异，忽略这些差异可能会带来一些特别隐蔽的错误。而且可能是致命的错误。所以，了解语言特性的差异，对于在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">移植来说非常重要。如果考虑系统多多个平台支持，就必须了解在不同平台下语言特性的差异，从开发一开始就把这些因素考虑进去，这样才能最低限度的降低移植的过程中工作量。</span></p>
<h3 style="MARGIN: 13pt 0cm"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">1.1.1</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">字节顺序的差异<span lang="EN-US"><o:p></o:p></span></span></h3>
<span lang="EN-US"><span style="mso-tab-count: 1">
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;字节顺序指的主要是整型变量在内存中的存储方式。在计算机中，数据都是以二进制方式存储的，包括在内存和硬盘中。而计算机又以</span><span lang="EN-US">8</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位二进制作为一个存储单元。在</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位系统中，一个整型的存储需要四个存储单元。也就是说要把一个</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位的整数分割成位四段分别进行存储，而每一段的存储位置就是字节顺序的差异。字节顺序的差异来源于硬件平台的差异，处理器在表示数的时候采用了不同的方法。严格的将，说</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下存在字节差异时不合适的，其实时</span><span lang="EN-US">Wintel</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span><span lang="EN-US">Windows+Intel</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）平台和其他平台之间的差异。考虑到通常的</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都是运行在</span><span lang="EN-US">Wintel</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台下的，而</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统一般都是在其他硬件平台（非</span><span lang="EN-US">Intel</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）下，所以还是以</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作为差异的双发来进行介绍。当然，安装在</span><span lang="EN-US">PC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">机上的</span><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拥有相同的字节表示顺序，但是设计网络程序的时候，依然应该考虑字节顺序的差异，因为你不知道通信的对方将会是什么样的硬件平台。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">为了清楚的表示每段存储的先后位置，我们用</span><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">16</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">进制来表示一段的值，下表列出了在</span><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">Unix</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">系统和</span><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">Windows</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">系统中整数</span><span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">20000</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">在内存中的情况。</span></p>
<div align="center">
<table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" border="1">
 <tbody>
  <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 99pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt" valign="top" width="132">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">十六进制表示</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="192">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">0x00004E20</span></p>
   </td>
  </tr>
  <tr style="mso-yfti-irow: 1">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 99pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="132">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内存表示</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 144pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="192">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">20 4E 00 00</span></p>
   </td>
  </tr>
  <tr style="mso-yfti-irow: 2; mso-yfti-lastrow: yes">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 99pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="132">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内存表示</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 144pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="192">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">00 00 4E 20</span></p>
   </td>
  </tr>
 </tbody>
</table>
</div>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如表中所示，</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中存储方式和该整数的</span><span lang="EN-US">16</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进制表示是相反，是一种低位在前高位在后的存储顺序。而</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的存储顺序和正常的</span><span lang="EN-US">16</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进制表示的顺序相同，称为高位在前低位在后的顺序。这种差异带来的问题，主要体现在以下几个方面：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l3 level1 lfo2; tab-stops: list 42.0pt"><span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings"><span style="mso-list: Ignore">&Oslash;<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><strong style="mso-bidi-font-weight: normal"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">网络通信时</span><span lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之间发生网络数据传输，传输一个整型数据（如一个数据包的长度）的时候，如果不经处理直接把内存中的数据传输过去，那么在对方看来完全是另一个数据，这样就会造成问题。如</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面发送过去一个</span><span lang="EN-US">20000</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span><span lang="EN-US">0x00004E20</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面收到的数据就会被理解成</span><span lang="EN-US">541982720</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span><span lang="EN-US">0x204E0000</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），这简直是天壤之别。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l3 level1 lfo2; tab-stops: list 42.0pt"><span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings"><span style="mso-list: Ignore">&Oslash;<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><strong style="mso-bidi-font-weight: normal"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件存储和读取时</span><span lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟网络传输类似，如果在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面把某个整数写到了文件中，然后在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面打开这个文件读取该数据，就会出现跟上面类似的问题。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个问题主要体现在不同平台之间互操作时，在多平台开发过程中，尤其时在网络应用开发的时候，两个平台之间数据交互是非常普遍的，所以这个问题也就显的很普遍。解决这个问题的方法就是交互的双方采用一种相同的数据编码标准，就是数据在传输和存储的时候采用什么方法进行编码，具体的做法有一下几种：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l4 level1 lfo3; tab-stops: list 39.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">1．<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数字转换成字符传进行交互</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l4 level1 lfo3; tab-stops: list 39.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">2．<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">协商一个同意的字节顺序，根据自己平台的字节顺序还原数据</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l4 level1 lfo3; tab-stops: list 39.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">3．<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">采用其他标准的编码方式，如</span><span lang="EN-US">ASN1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编码</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟这个问题类似，</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位系统和</span><span lang="EN-US">64</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位系统的差异也会出现这样的问题，解决方法跟这个问题的解决方法相同。在</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位系统和</span><span lang="EN-US">64</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位系统中，长整型（</span><span lang="EN-US">long</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）分别用</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位和</span><span lang="EN-US">64</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位表示，这样，在不同系统之间交互的时候必然会出现整型数据表示方式不同的问题。目前大多数</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统都是</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位的系统，而</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中很多都是</span><span lang="EN-US">64</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位的，尤其是大型的服务器，所以这个问题必须引起重视。</span></p>
<h3 style="MARGIN: 13pt 0cm"><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">1.1.2</span></st1:chsdate><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">变量的作用域差异<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在不同的系统下，由于编译器的不同，对变量</span><span style="FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用域</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的实现机制也有所不同，这里以</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">VC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">CC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这两个编译器为例做一个简单的比较说明。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的开发过程中，我们经常会有这样的用法：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;num;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这是一种最常用的</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">循环的用法，因为其中</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">主要使用来控制循环，所以一般没有必要拿出来单独进行声明，只是放在</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语句中一起声明。这里</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">j</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等简单的变量就成了我们常用的变量，一般不按照编程规范那样为他们命名。就是这种声明方法，在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下和</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下有了不同的理解，</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的作用域不同。我们先把作用域进行划分，如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shapetype id="_x0000_t88" coordsize="21600,21600" o:spt="88" adj="1800,10800" path="m,qx10800@0l10800@2qy21600@11,10800@3l10800@1qy,21600e" filled="f"><v:formulas><v:f eqn="val #0"></v:f><v:f eqn="sum 21600 0 #0"></v:f><v:f eqn="sum #1 0 #0"></v:f><v:f eqn="sum #1 #0 0"></v:f><v:f eqn="prod #0 9598 32768"></v:f><v:f eqn="sum 21600 0 @4"></v:f><v:f eqn="sum 21600 0 #1"></v:f><v:f eqn="min #1 @6"></v:f><v:f eqn="prod @7 1 2"></v:f><v:f eqn="prod #0 2 1"></v:f><v:f eqn="sum 21600 0 @9"></v:f><v:f eqn="val #1"></v:f></v:formulas><v:path arrowok="t" o:connecttype="custom" o:connectlocs="0,0;21600,@11;0,21600" textboxrect="0,@4,7637,@5"></v:path><v:handles><v:h position="center,#0" yrange="0,@8"></v:h><v:h position="bottomRight,#1" yrange="@9,@10"></v:h></v:handles></v:shapetype><v:shape id="_x0000_s1026" style="MARGIN-TOP: 1.55pt; Z-INDEX: 1; LEFT: 0px; MARGIN-LEFT: 315pt; WIDTH: 27pt; POSITION: absolute; HEIGHT: 140.4pt; TEXT-ALIGN: left" type="#_x0000_t88"><v:textbox style="mso-next-textbox: #_x0000_s1026"></v:textbox></v:shape><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{&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;&nbsp;&nbsp; --------------------------------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shape id="_x0000_s1028" style="MARGIN-TOP: 9.35pt; Z-INDEX: 3; LEFT: 0px; MARGIN-LEFT: 180pt; WIDTH: 18pt; POSITION: absolute; HEIGHT: 46.8pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;num;i++)----------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe"><v:stroke joinstyle="miter"></v:stroke><v:path o:connecttype="rect" gradientshapeok="t"></v:path></v:shapetype><v:shape id="_x0000_s1029" style="MARGIN-TOP: 9.35pt; Z-INDEX: 4; LEFT: 0px; MARGIN-LEFT: 198pt; WIDTH: 27pt; TEXT-INDENT: 0px; POSITION: absolute; HEIGHT: 23.4pt; TEXT-ALIGN: left" type="#_x0000_t202" stroked="f"><v:textbox style="mso-next-textbox: #_x0000_s1029"></v:textbox></v:shape><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shape id="_x0000_s1027" style="MARGIN-TOP: 1.55pt; Z-INDEX: 2; LEFT: 0px; MARGIN-LEFT: 342pt; WIDTH: 27pt; TEXT-INDENT: 0px; POSITION: absolute; HEIGHT: 23.4pt; TEXT-ALIGN: left" type="#_x0000_t202" stroked="f"><v:textbox style="mso-next-textbox: #_x0000_s1027"></v:textbox></v:shape><span lang="EN-US"><span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;&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; I&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; II</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}&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; ----------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}&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; ----------------------------------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们划分出</span><span lang="EN-US">I</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">两个作用域，其中作用域</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">包含在作用域</span><span lang="EN-US">I</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当中。在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，变量</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的作用域是</span><span lang="EN-US">I</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的整个范围，而</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的作用域只是</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的范围。其实标准的</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语法应该是</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的做法，但是微软在实现的时候没有按照这个标准实现，这就引发了我们讨论的这个问题。由于这个差异，就引发了一些微妙而隐蔽的问题。先看一下下面两端代码。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">A</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;num;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(i=0;i&lt;num;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<div style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0cm; BORDER-TOP: medium none; PADDING-LEFT: 0cm; PADDING-BOTTOM: 1pt; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div; mso-border-bottom-alt: solid windowtext .75pt">
<p class="MsoNormal" style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0cm; BORDER-TOP: medium none; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; MARGIN: 0cm 0cm 0pt; BORDER-LEFT: medium none; TEXT-INDENT: 21pt; PADDING-TOP: 0cm; BORDER-BOTTOM: medium none; mso-padding-alt: 0cm 0cm 1.0pt 0cm; mso-border-bottom-alt: solid windowtext .75pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0cm; BORDER-TOP: medium none; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; MARGIN: 0cm 0cm 0pt; BORDER-LEFT: medium none; TEXT-INDENT: 21pt; PADDING-TOP: 0cm; BORDER-BOTTOM: medium none; mso-padding-alt: 0cm 0cm 1.0pt 0cm; mso-border-bottom-alt: solid windowtext .75pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
</div>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">B</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;num;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;num;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<div style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0cm; BORDER-TOP: medium none; PADDING-LEFT: 0cm; PADDING-BOTTOM: 1pt; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div; mso-border-bottom-alt: solid windowtext .75pt">
<p class="MsoNormal" style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0cm; BORDER-TOP: medium none; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; MARGIN: 0cm 0cm 0pt; BORDER-LEFT: medium none; TEXT-INDENT: 21pt; PADDING-TOP: 0cm; BORDER-BOTTOM: medium none; mso-padding-alt: 0cm 0cm 1.0pt 0cm; mso-border-bottom-alt: solid windowtext .75pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
</div>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码</span><span lang="EN-US">A</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面可以正常编译，而在</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面确编不过去，提示第二个</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">循环中变量</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">没有定义。相反代码</span><span lang="EN-US">B</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下可以正常编译，而在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面编不过去，提示第二个</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">循环中变量</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">重复定义。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在通常的情况下，我们会按照</span><span lang="EN-US">B</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的方法书写代码，而在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译是出现错误，然后改成</span><span lang="EN-US">A</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的那种形式。这样，在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下就没有问题了，程序也可以编译过去了，但是到</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下时，有会出现问题，这是就不得不把</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的声明拿到所有</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">循环的外面。当</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的声明拿到</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">循环的外面时，真正的问题来了。首先提示一下，这样的一段代码是没有问题的：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">int i = 0;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">if(cond)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;num;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这是一段正确的代码，虽然在外面已经定义了</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，但是在</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里面重新定义一个</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也没有问题，这是</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的语法所允许的（</span><span lang="EN-US">java</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里面不允许这样做）。但就是因为这种</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言的灵活机制，引发了问题的产生。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">问题产生源于程序中出现了</span><span lang="EN-US">A_B</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">那样的代码，然后把</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的声明拿到了外面。在后期维护的过程中，又在后面增加了一个循环，但是却是按照</span><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的那种方式增加的，这样就产生了问题。请看如下代码：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><v:shape id="_x0000_s1030" style="MARGIN-TOP: 0px; Z-INDEX: 5; LEFT: 0px; MARGIN-LEFT: 261pt; WIDTH: 81pt; POSITION: absolute; HEIGHT: 296.4pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int i=0;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------------------------------------------------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char str1[10];&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char str2[10];</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>strcpy(str1,&rdquo;hello&rdquo;);</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(i=0;i&lt;20;i++)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><v:shape id="_x0000_s1033" style="MARGIN-TOP: 7.8pt; Z-INDEX: 8; LEFT: 0px; MARGIN-LEFT: 342pt; WIDTH: 18pt; POSITION: absolute; HEIGHT: 23.4pt; TEXT-ALIGN: left" type="#_x0000_t202" stroked="f"><v:textbox style="mso-next-textbox: #_x0000_s1033"></v:textbox></v:shape><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><v:shape id="_x0000_s1032" style="MARGIN-TOP: 7.8pt; Z-INDEX: 7; LEFT: 0px; MARGIN-LEFT: 3in; WIDTH: 18pt; POSITION: absolute; HEIGHT: 124.8pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(cond)&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --------------------------------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><v:shape id="_x0000_s1031" style="MARGIN-TOP: 7.8pt; Z-INDEX: 6; LEFT: 0px; MARGIN-LEFT: 171pt; WIDTH: 9pt; POSITION: absolute; HEIGHT: 46.8pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0;i&lt;10;i++)&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;&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; I</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><v:shape id="_x0000_s1035" style="MARGIN-TOP: 7.8pt; Z-INDEX: 10; LEFT: 0px; MARGIN-LEFT: 180pt; WIDTH: 27pt; POSITION: absolute; HEIGHT: 23.4pt; TEXT-ALIGN: left" type="#_x0000_t202" stroked="f"><v:textbox style="mso-next-textbox: #_x0000_s1035"></v:textbox></v:shape><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{&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;&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;III</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><v:shape id="_x0000_s1034" style="MARGIN-TOP: 0px; Z-INDEX: 9; LEFT: 0px; MARGIN-LEFT: 243pt; WIDTH: 27pt; POSITION: absolute; HEIGHT: 23.4pt; TEXT-ALIGN: left" type="#_x0000_t202" stroked="f"><v:textbox style="mso-next-textbox: #_x0000_s1034"></v:textbox></v:shape><span lang="EN-US"><span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(str1[i]==0)<span style="mso-spacerun: yes">&nbsp; </span>break;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;II&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; </span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ------------------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>memcpy(str2,str1,i);</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>str2[i]=0;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------------------------------</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------------------------------------------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在上述代码，为了分析方便，我们把整段代码分成</span><span lang="EN-US">I</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">III</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">三个作用域。其中作用域</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就是整个</span><span lang="EN-US">if</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语句，实现的相当于一个</span><span lang="EN-US">strcpy</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数的功能。</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的内容就好是我们上面说的后期维护中加入的，当然，实际情况并不像我们例子中这么明前，</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的声明可能离我们的</span><span lang="EN-US">if</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语句很远，所以加入这段代码是不知道上面是否声明了</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">变量。而且，这段代码编译的时候也不回出错，不管是</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">还是</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（单独的一段</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的代码在</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面编不过去）。在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，这段代码可以正常的运行，不回出现任何问题，因为</span><span lang="EN-US">II</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的代码完全是根据</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的习惯编写的。但是在</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，这段代码就会出现内存越界的错误，虽然编译可以正常通过，但是实现的却不是程序员预期的目的。在执行</span><span lang="EN-US">memcpy</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的时候，那个</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其实是外层声明的那个</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，值是</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，而</span><span lang="EN-US">str2</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">str1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的大小之后</span><span lang="EN-US">10</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，所以就发生了读写内存越界。而程序员预想的，这个</span><span lang="EN-US">i</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span><span lang="EN-US">for</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">循环算出来的</span><span lang="EN-US">str1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">字符串的长度，应该是</span><span lang="EN-US">5</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">要解决这类问题，就得加强编程规范，杜绝这种错误代码的生成。从开始的时候就要意识到可能产生的问题，从而避免问题的发生。</span></p>
<h3 style="MARGIN: 13pt 0cm"><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">1.1.3</span></st1:chsdate><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">全局对象的初始化<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，初始化对象的时候系统会自动调用构造函数，因此我们习惯在构造函数中做一些初始化的工作，让自动自动为我们调用初始化的操作。其中，有些对象是静态分配的全局对象，就是在任何函数体外声明的对象，如：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CMyObject g_Object;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通常情况下，程序启动的时候，系统都会自动调用这个对象的构造函数对这个全局对象进行初始化，但是在某些系统中（</span><span lang="EN-US">SCO Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），就不想我们期望的那样，也许这是编译器实现的一个</span><span lang="EN-US">bug</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，但是我们也不能忽视这个问题的存在。对于这种问题，我们可以通过显式创建对象的方法解决，如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CMyObject* g_pObject = new CMyObject;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样，系统在启动的时候，就会执行</span><span lang="EN-US">new CMyObject</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来为对象分配空间，同时执行调用对象的构造函数来初始化对象。如果不想使用指针的方式引用该对象（为了安全因素，不想某个函数在程序运行期间把这个指针置空），那么我们可以采用另一种方法，如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CMyObject&amp; g_Object = *(new CMyObject);</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样也可以达到对像创建和初始化的工作。虽然对于我们分配的这个对象没有进行释放操作，但是全局只有这么一次，所以不用担心内存泄漏问题。程序运行结束的时候，操作系统会自动释放掉程序所申请的所有内存，当然也包含这个对象。</span></p>
<h3 style="MARGIN: 13pt 0cm"><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">1.1.4</span></st1:chsdate><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体"> </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">语法检查的差异<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不同操作系统下面有不同的编译器的实现，不同的编译器对语法要求的程度不同。在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下可以正常编译的代码，在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下就可能出现语法错误。</span><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US">1.1.2</span></st1:chsdate><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中就是一个典型的例子。另外，还有一些其他方面的语法检查的差异。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是一中很灵活的语言，语法很自由，但是不同的平台下这中自由的程度也不同。</span><span lang="EN-US">Windows VC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">Solaris CC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Linux gcc</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现的都不错，但是有些其他的系统实现的就不是这么灵活，很多写法在他们下面都行不通。具体的记不太清了，在</span><span lang="EN-US">AIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">SCO Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面碰到很多这种情况。所以只能在移植的过程中逐渐的发现和改正。但是只要保证采用标准的书写规范，应该可以更少的产生这种错误。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有这样一段代码：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(NULL == pVar)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&hellip;</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这是在大多数平台下面很好的一种习惯，可以避免哪种把&ldquo;</span><span lang="EN-US">==</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;写成&ldquo;</span><span lang="EN-US">=</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;的错误，在编译期间就能发现。但是在</span><span lang="EN-US">SCO Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，这种写法就会引发编译器的一个警告。这个例子能简单的说明一下不同编译器之间存在的差别。</span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 22.5pt; TEXT-INDENT: -22.5pt; mso-list: l2 level2 lfo1; tab-stops: list 22.5pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">1.2</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">操作系统特性的差异</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不同的操作系统中都存在一些系统的限制，如打开文件句柄数的限制、</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等待队列的限制、进程和线程堆栈大小的限制等，因此在开发的过程中，必须考虑到这些限制因素对程序的影响。当然，有些限制参数可以适当的调整，这就需要在发布程序的时候加以声明。另外，操作系统的容错性也对程序有影响。下面分别进行讨论。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">1.2.1<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">文件描述符的限制<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件描述符最初是</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的一个概念，在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统中，用文件描述符来表示文件、打开的</span><span lang="EN-US">socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">连接等，跟</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下</span><span lang="EN-US">HANDLE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的概念类似。文件描述符是一种系统资源，系统对每个进程可以分配的文件描述符数量都有限制。以</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为例，默认情况下每个进程可以打开的文件描述符为</span><span lang="EN-US">1024</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个，系统的硬限制是</span><span lang="EN-US">8192</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（具体的值跟版本有关），也就是说可以调整到</span><span lang="EN-US">8192</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统下使用</span><span lang="EN-US">ulimit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令来获得系统的这些限制参数。一般情况下，这都是够用的，但是有一个例外，在</span><span lang="EN-US">32</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为的</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序中，使用标准输入输出函数（</span><span lang="EN-US">stdio</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）进行文件的操作，最大的文件描述符不能超过</span><span lang="EN-US">256</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。比如说用</span><span lang="EN-US">fopen</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打开文件，出去系统占用的</span><span lang="EN-US">3</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个文件描述符（</span><span lang="EN-US">stdin</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">stdout</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">stderr</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），程序中只能再同时打开</span><span lang="EN-US">253</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个文件。如果使用</span><span lang="EN-US">open</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数来打开文件，就没有这个限制，但是就不能够使用</span><span lang="EN-US">stdio</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的那些函数进行操作了，是程序的通用性和灵活性有所降低。这是因为在</span><span lang="EN-US">stdio</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">FILE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结构中，用一个</span><span lang="EN-US">unsigned char</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来表示文件描述符，所以只能表示</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">～</span><span lang="EN-US">255</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在网络程序的开发中，每一个网络连接也都占用一个文件描述符，如果程序打开了很多</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">连接（典型的例子就是使用了连接池技术），那么程序运行的时候可能用</span><span lang="EN-US">fopen</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打不开文件。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解决这个问题，可以采用一下几种方法：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo4; tab-stops: list 39.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">1．<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">升级为</span><span lang="EN-US">64</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位系统或采用采用</span><span lang="EN-US">64</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">位方式编译程序</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo4; tab-stops: list 39.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">2．<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span><span lang="EN-US">sys/io.h</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的函数操作文件</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo4; tab-stops: list 39.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">3．<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">采用文件池技术，预留一部分文件描述符（</span><span lang="EN-US">3</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">～</span><span lang="EN-US">255</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之间的），使用</span><span lang="EN-US">freopen</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数来重用这些描述符。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">至于采用哪种方法或者是否考虑系统中处理这个问题，就要视具体的情况而定了，那些不受这个限制影响的程序，可以不考虑这个问题。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">1.2.2<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">进程和线程的限制<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一般的操作系统对每个进程和线程可以使用的资源数都有限制，比如一个进程可以创建的线程数，一个进程可以打开的文件描述符的数量，进程和线程栈大小的限制和默认值等。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">针对这些问题，首先要分析和考虑你的系统是一个什么样的规模，会不会收到这些限制的影响，如果需求大于系统的限制，可以通过适当的调整系统参数来解决，如果还不能解决，就得考虑采用多进程的方式来解决。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于进程和线程的栈空间大小的限制，主要是线程栈空间的问题。一般的系统都有默认的线程栈空间大小，而且不同超作系统的默认值可能不同。在通常情况下，这些对程序没有影响，但是当程序的层次结构比较复杂，使用了过多的本地变量，这个限制可能就会对程序产生影响，导致栈空间溢出，这是一个比较严重的问题。不能通过调整系统参数来解决这个问题，但是可以通过相应的函数，在程序里面指定创建线程的栈空间的大小。但是具体该调整的数值应该适可而止，而不是越大越好。因为线程的栈空间过大的时候，就会影响到可创建线程的数量，虽然远没有达到系统多线程数的限制，但却可能因为系统资源占用过多导致分配内存失败。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的线程是通过进程实现的，实际上是假的线程。如果程序只在</span><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下运行，就可以考虑直接使用多进程技术来代替多线程，因为在</span><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下多线程并不能带来多线程相对于多进程的优势。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">1.2.3<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">网络通信能力的限制<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于网络编程来说，性能是最主要的因素。系统为了提高网络通信的性能，提供了很多辅助的技术，其中等待队列就是其中之一。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于程序来说，在一个时间点只能处理一个网络连接请求，而如果同时来了多个网络连接请求的话，就会有很多请求失败。为了解决这个问题，操作系统提供了等待队列技术，就是处理不上的连接请求先放到系统的等待队列中，这样就可以提高网络连接的成功率。等待队列的创建也需要消耗系统资源，因此系统对等待队列的大小都有限制，程序中可以通过函数设定等待队列的大小，但是不能超过系统的硬性限制。下面列出了几个操作系统的最大等待队列的大小：</span></p>
<div align="center">
<table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" border="1">
 <tbody>
  <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 4cm; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt" valign="top" width="151">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操作系统</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 117pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="156">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">最大等待队列</span></p>
   </td>
  </tr>
  <tr style="mso-yfti-irow: 1">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 4cm; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="151">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">Windows 2000 Server</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 117pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="156">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">200</span></p>
   </td>
  </tr>
  <tr style="mso-yfti-irow: 2">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 4cm; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="151">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">Windows XP Home</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 117pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="156">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">5</span></p>
   </td>
  </tr>
  <tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes">
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 4cm; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="151">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">Solaris E250</span></p>
   </td>
   <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #ece9d8; PADDING-BOTTOM: 0cm; WIDTH: 117pt; BORDER-TOP-COLOR: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="156">
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US">128</span></p>
   </td>
  </tr>
 </tbody>
</table>
</div>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上表中只简单列出了几个操作系统的等待队列参数，其他系统暂位列出，如果有兴趣可以自己作个简单的程序测试一下。所以这个问题就跟具体的系统环境有关了，不过我们可以在系统连接池的基础上再做一些工作，采用连接缓冲池技术。就是接受到网络连接请求以后，提交给出去线程处理的之前，先放到一个缓冲池中。这样可以接受更多的连接请求等待处理，能一定程度的提高系统的连接成功率。不过，跟系统的等待队列不同，这是通过软件方式实现的等待队列，而系统提供的连接池是从操作系统级来解决问题的，更接近硬件层次，所以效率肯定会不同。面对这类问题，首先还是得以调整系统连接池的大小，然后再采用其他辅助手段。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">1.2.4<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">容错性的影响<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">采用</span><span lang="EN-US">C/C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发程序，缓冲区溢出的错误非常普遍，但是系统运行程序的时候，对待运行期出现的这些错误的处理能力都不相同。总的来说，</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统的容错性最强，尤其是</span><span lang="EN-US">Debug</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">版的程序，系统都加入了一些保护机制，能够保证出现一些小的错误以后，程序仍能够正常运行。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台下面要求的就严格一些，有些系统更是容不得一点沙子，有一点错误就会出现宕机现象，这些跟操作系统的内存分配机制有关。</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台的程序分配内存的时候，一般都会多分出一些字节用于对齐，如果缓冲区溢出的不是太多，就不回对内存中其他变量的值造成影响，因此程序也能够正常运行。但是这种保护机制会带来更多的系统开销。这就是</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序移植到</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面稳定性降低的主要原因之一，也是为什么</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统会消耗那么多系统资源的原因。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">要解决这类问题，就要进行更严格的测试和代码检查。同时，借助相关的测试工具，找出系统中隐藏的潜在的问题，不能放过任何一个可能产生的错误，尤其是编译过程中发现的警告信息。当然，这些工作都应该再移植前做的很充分，在移植后更应该加大测试的力度。</span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 22.5pt; TEXT-INDENT: -22.5pt; mso-list: l2 level2 lfo1; tab-stops: list 22.5pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">1.3</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">图形用户界面</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">Windows </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Unix </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">图形模型差异极大，这点是</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序开发最大的差别。</span><span lang="EN-US">UNIX </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span><span lang="EN-US">X Window </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统</span><span lang="EN-US">GUI</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，而</span><span lang="EN-US">Windows </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span><span lang="EN-US">GDI</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。虽然在概念上类似，但是</span><span lang="EN-US">X API </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">GDI API </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之间没有简单的对应。在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面可以通过</span><span lang="EN-US">MFC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等类库很方便的开发出图形用户界面的程序，而</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下相对来说就麻烦了些，缺少哪种所见即所得的好的开发工具。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">GUI</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序开发，是一个比较复杂的过程，这里就不在详细介绍。如果要进行</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面</span><span lang="EN-US">GUI</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序的开发的话，可以单独去查找相关的文档。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 22.5pt; TEXT-INDENT: -22.5pt; mso-list: l2 level2 lfo1; tab-stops: list 22.5pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">1.4</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">并发处理</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">并发处理包括多进程和多线程的概念，</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的并发处理差别也比较大，但是基本上都能找到一组对应的函数来实现类似的功能。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，创建进程和线程可以通过调用</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">API</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来完成，或者通过调用</span><span lang="EN-US">MFC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">提供的并发处理类库来实现。在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面创建进程通常使用</span><span lang="EN-US">fork</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数，这跟</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的多进程概念有所不同，相当于在当前位置给当前进程创建一个副本；而</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的创建进程大都是创建一个新的进程。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的多线程操作，通过一组线程函数来完成，通常我们使用</span><span lang="EN-US">POSIX </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">PTHREAD</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">线程库来创建线程，但是在不同的</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">分支系统中，都包含又自己的本地线程库。如在</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的本地线程库，是一组以</span><span lang="EN-US">thr_</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开头的函数，而</span><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的线程函数一般都已</span><span lang="EN-US">pthread_</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开头。虽然有两种不同的线程库空我们选择，但在某一个特定的系统下，他们的实现实质都是一样的，而且基本上都能够找到对应的函数。为了程序的可移植性，建议采用</span><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的线程库。这是大多数</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统都支持的线程库，但是不同系统下实现的功能可能有所差别，可能只是实现了这个函数库的一个子集。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在有些</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统下，没有实现线程库，如</span><span lang="EN-US">SCO Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，系统只提供多进程的开发方式。但是，如果为了实现程序代码的统一性，我们可以采用第三方提供的线程库。这里有一个叫</span><span lang="EN-US">FSU-threads</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的线程库供我们选择。这个线程库中实现了</span><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中定义的线程函数，而且是开源的，可以支持</span><span lang="EN-US">SunOS 4.1.x, Solaris 2.x, SCO UNIX, FreeBSD, Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等系统。除此之外，还有</span><span lang="EN-US">ZThreads</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">线程库等。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的线程库中，实现了互斥（</span><span lang="EN-US">Mutex</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）、事件</span><span lang="EN-US">(Event)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、信号量</span><span lang="EN-US">(Semaphore)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等同步对象，用于实现线程之间的同步。在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，线程同步主要使用互斥（</span><span lang="EN-US">mutex</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）和条件变量</span><span lang="EN-US">(cond)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，其中条件变量可以实现事件和信号量的功能。另外，</span> <span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">还定义了一套信号量函数，跟线程函数不同，是一组以</span><span lang="EN-US">sem_</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开头的函数（</span><span lang="EN-US">POSIX 1003.1b semaphores</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。但是这套函数就不想</span><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">线程函数支持的那么广泛了，比如在</span><span lang="EN-US">AIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上就不支持</span><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的信号量函数，不过</span><span lang="EN-US">AIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统下有另一组函数来实现信号量的功能（</span><span lang="EN-US">SystemV semaphores</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。在很多</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统中，同时支持</span><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的信号量和</span><span lang="EN-US">SystemV</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的信号量，在</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面还有一套自己的本地函数来实现信号量。下面分别列出</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统中的用于并发处理的主要的函数。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>fork<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建进程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">线程库</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_create<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建一个信的线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_attr_init <span style="mso-tab-count: 1">&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个线程属性对象</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_attr_destroy <span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">释放一个线程属性对象</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_exit <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">终止执行调用的线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_join <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">把当前调用线程挂起，直到目标线程结束</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_setschedparam <span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设置线程的调度策略和优先级</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_getschedparam <span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">获得线程的调度策略和优先级</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_sigmask <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改变</span><span lang="EN-US">/</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">检查调用线程的信号掩码</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_kill <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发送信号到另一个线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_self <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">返回当前线程的</span><span lang="EN-US">ID</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthead_mutex_init <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个互斥量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_mutexattr_init <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化互斥量的属性对象</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 167.8pt; TEXT-INDENT: -125.8pt; TEXT-ALIGN: left; mso-para-margin-left: 4.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_mutex_lock<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">给一个互斥量加锁，如果互斥量已经被别的线程锁定，调用线程挂起，直到别的线程释放</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_mutex_unlock <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">释放互斥量（解锁）</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">ptherad_mutex_destroy <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">销毁一个互斥量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_cond_init <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个条件变量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_condattr_init <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个条件变量的属性对象</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_cond_wait <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">阻塞在一个条件变量上</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_cond_signal <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解除下一个线程在条件变量的阻塞</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_cond_boradcast <span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解除所有线程在这个条件变量上的阻塞</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_cond_destroy <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">销毁一个条件变量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">pthread_cancel <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">请求结束一个线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本地线程库</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_create <span style="mso-tab-count: 4">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建一个新线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_exit <span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">终止调用线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_join <span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">把当前调用线程挂起，直到目标线程结束</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_yield <span style="mso-tab-count: 4">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用当前线程创建出另一个线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_suspend <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">挂起一个指定的线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_continue <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">恢复一个被挂起的线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_setprio <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修改线程的优先级</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_getprio <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">获得线程的优先级</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_sigsetmask <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改变</span><span lang="EN-US">/</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">检查调用线程的信号掩码</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_kill <span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发送信号到另一个线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_self <span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">返回当前线程的</span><span lang="EN-US">ID</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_main <span style="mso-tab-count: 4">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标记为主线程</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_mutex_init <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个互斥量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 167.8pt; TEXT-INDENT: -125.8pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_mutex_lock <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">给一个互斥量加锁，如果互斥量已经被别的线程锁定，调用线程挂起，直到别的线程释放</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_mutex_unlock <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">释放互斥量（解锁）</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_mutex_destroy<span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">销毁一个条互斥量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_cond_init <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个条件变量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_cond_wait <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">阻塞在一个条件变量上</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_cond_signal<span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解除下一个线程在条件变量的阻塞</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_cond_boradcast <span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解除所有线程在这个条件变量上的阻塞</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">thr_cond_destroy <span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">销毁任何状态的条件变量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">rwlock_init <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个读写锁</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">rw_rdlock <span style="mso-tab-count: 4">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">获得一个读写锁的读锁定</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">rw_wrlock <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">获得一个读写锁的写锁定</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">rw_unlock <span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解锁一个读写锁</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">POSIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">信号量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sem_init<span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个信号量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sem_destroy<span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">销毁一个信号量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 167.8pt; TEXT-INDENT: -125.8pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US">sem_wait<span style="mso-tab-count: 2">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等待获得一个信号量，获得后信号量的值减</span><span lang="EN-US">1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如果当前信号量值位</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，当前线程阻塞，支持有别的线程释放信号量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 167.8pt; TEXT-INDENT: -125.8pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US">sem_trywait<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">尝试获得一个信号量，获得后信号量的值减</span><span lang="EN-US">1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如果当前信号量值位</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，返回失败</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sem_post<span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">释放一个信号量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sem_getvalue<span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">获得指定信号量的值</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System V</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">信号量</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US"><a href="javascript:if(confirm('http://personal.xfol.com/~rezaie/api/ipc/man.cgi@semctl%20%20\n\nThis%20file%20was%20not%20retrieved%20by%20Teleport%20Pro,%20because%20the%20server%20reports%20that%20this%20file%20cannot%20be%20found.%20%20\n\nDo%20you%20want%20to%20open%20it%20from%20the%20server?'))window.location='http://personal.xfol.com/%7Erezaie/api/ipc/man.cgi@semctl'"><span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">semctl</span></a><span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对信号量进行一系列的控制</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US"><a href="javascript:if(confirm('http://personal.xfol.com/~rezaie/api/ipc/man.cgi@semget%20%20\n\nThis%20file%20was%20not%20retrieved%20by%20Teleport%20Pro,%20because%20the%20server%20reports%20that%20this%20file%20cannot%20be%20found.%20%20\n\nDo%20you%20want%20to%20open%20it%20from%20the%20server?'))window.location='http://personal.xfol.com/%7Erezaie/api/ipc/man.cgi@semget'"><span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">semget</span></a><span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建一个信号量，成功时返回信号的</span><span lang="EN-US">ID</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US"><a href="javascript:if(confirm('http://personal.xfol.com/~rezaie/api/ipc/man.cgi@semop%20%20\n\nThis%20file%20was%20not%20retrieved%20by%20Teleport%20Pro,%20because%20the%20server%20reports%20that%20this%20file%20cannot%20be%20found.%20%20\n\nDo%20you%20want%20to%20open%20it%20from%20the%20server?'))window.location='http://personal.xfol.com/%7Erezaie/api/ipc/man.cgi@semop'"><span style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none">semop</span></a><span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对信号进行操作</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的本地信号量，更接近于操作系统中我们学到的</span><span lang="EN-US">PV</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操作的信号灯</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sema_init<span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初始化一个信号灯</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">信号量</span><span lang="EN-US">)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sema_destroy<span style="mso-tab-count: 4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">销毁一个信号灯</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sema_p<span style="mso-tab-count: 5">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行信号灯的</span><span lang="EN-US">P</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操作</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 167.8pt; TEXT-INDENT: -125.8pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US">sema_p_sig<span style="mso-tab-count: 2">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span><span lang="EN-US">sema_p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类似，当阻塞再这个函数的时候，如果线程收到一个信号，函数退出</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sema_tryp<span style="mso-tab-count: 4">&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; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">尝试执行信号灯的</span><span lang="EN-US">P</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操作</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-para-margin-left: 2.0gd; mso-layout-grid-align: none" align="left"><span lang="EN-US">sema_v<span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行信号灯的</span><span lang="EN-US">V</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操作</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为了方便使用，我在开发的过程中已经把上面常用的函数都封装成了类，兼容</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和各种常见的</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统，而且网上还有很多这方面的代码资源可用。如果感兴趣的话可以向我索要。</span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 22.5pt; TEXT-INDENT: -22.5pt; mso-list: l2 level2 lfo1; tab-stops: list 22.5pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">1.5</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">网络通信</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US">Socket(</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文译名：套接字</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">最初在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上出现</span><span lang="EN-US">,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">并很快成为</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上最流行的网络编程接口之一。后来，微软将它引入到</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中并得到实现</span><span lang="EN-US">,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">于是从</span><span lang="EN-US">Windows 95</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">WinNT4</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开始</span><span lang="EN-US">,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统就内置了</span><span lang="EN-US">Winsock1.1,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">后来到了</span><span lang="EN-US">Windows98</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">Windows2000,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">它内置的</span><span lang="EN-US">Winsock DLL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">更新为</span><span lang="EN-US">Winsock2.2</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数大体上和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数差不多，函数名称很参数用法都类似，只有一些细微的差别，某些参数的意义不同，而且对于</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的属性控制也不太一样。</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面还对</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数进行了封装，有一系列相关类可用使用，简化网络编程的复杂性。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本身没有这些类库，但是我们也已经积累了很多这方面的经验和资源。我们有一组现成的类对</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数进行了封装，上层只需要简单的调用即可，不用关心底层的差别。而且，这套类库也可以同时支持多种平台，可移植性非常好。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关于</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发就简单说这些，想深入了解的话请参考介绍</span><span lang="EN-US">Socket</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编程的一些相关资料。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<h1 style="MARGIN: 17pt 0cm 16.5pt 18pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo1; tab-stops: list 18.0pt"><span lang="EN-US" style="FONT-SIZE: 15pt; LINE-HEIGHT: 240%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.<span style="FONT: 7pt 'Times New Roman'"> </span></span></span><span style="FONT-SIZE: 15pt; LINE-HEIGHT: 240%; FONT-FAMILY: 黑体">基本开发流程<span lang="EN-US"><o:p></o:p></span></span></h1>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下开发程序，不同于在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下开发，除了上面介绍的程序级的差别外，开发环境也有很大的差别。在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，大都使用集成开发环境进行开发，如</span><span lang="EN-US">MS Visual C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">Borland C++ Builder</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等。在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面也有集成开发环境，如</span><span lang="EN-US">Sun </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">Workshop</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">KDevelop</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等，但是因为很多</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发都是移植，即现在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基本完成，然后在移植到</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，所以需要的代码量就不是太大，所以经常采用</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的方法，而不用</span><span lang="EN-US">IDE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境来重新创建工程。本章的主要内容就是介绍在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下开发的基本过程和一些开发调试工具。</span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level2 lfo5; tab-stops: list 18.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">2.1</font><span style="FONT: 7pt 'Times New Roman'"> </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">代码的编写</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于移植工程来讲，基本代码都在</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下完成，只需要吧代码传到</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，然后在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面组织源码目录即可。对于传到</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码进行编辑，可以使用</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">工具来完成，也可以通过</span><span lang="EN-US">UltraEdit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以</span><span lang="EN-US">Ftp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式打开</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的文件进行编辑。</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面最常用的一个文本编辑器，后面将会介绍</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一些基本用法。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有一点值得注意，</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下文本里面的回车符包含两个字符&lsquo;</span><span lang="EN-US">\n</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;和&lsquo;</span><span lang="EN-US">\r</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;，而</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的文本里面的回车符只包含一个字符&lsquo;</span><span lang="EN-US">\n</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;。这样，如果上传问文件的时候没有选择正确的方式，应该使用文本方式上传的使用了二进制方式，或者应该使用二进制方式上传的使用了文本方式，那么在</span><span lang="EN-US">unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下都会出现问题，打开的文本当中每一行的行尾就会出现一个&lsquo;</span><span lang="EN-US">^M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;字符。可以通过</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的匹配替换功能（稍后会做介绍）或者重新按照正确的方式上传来解决。</span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level2 lfo5; tab-stops: list 18.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">2.2</font><span style="FONT: 7pt 'Times New Roman'"> </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">编译</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.2.1<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">简单编译<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于简单的程序，如只有几个源文件，可以直接使用编译器进行编译，或者把几条编译命令写在一个脚本文件里面，通过执行脚本文件实现工程的编译和连接。比如只有一个</span><span lang="EN-US">hello.cpp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件的工程，可以通过如下命令编译：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">CC &ndash;o hello hello.cpp</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中</span><span lang="EN-US">CC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是编译器，不同的系统下面可能有不同的编译器。一般来说，大多数</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统下的</span><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器都叫</span><span lang="EN-US">cc</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，而</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器叫</span><span lang="EN-US">CC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span><span lang="EN-US">Linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面带的</span><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器为</span><span lang="EN-US">gcc</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器为</span><span lang="EN-US">g++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span><span lang="EN-US">-o</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数用来指定输出的目标的名称，也就是编译后执行程序的名称。这种情况下编译和连接一步完成。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于稍微负责一些的程序，包含多个源文件的，可以编写一个编译脚本，相当于</span><span lang="EN-US">windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的批处理。如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">工程中包含</span><span lang="EN-US">hello.cpp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">func.cpp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span><span lang="EN-US">other.cpp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，我们可以用如下脚本来实现工程的编译。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CC &ndash;c hello.cpp</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CC &ndash;c func.cpp</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CC &ndash;c other.cpp</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CC &ndash;o hello hello.o func.o other.o</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">多个文件情况下，把编译和连接分开执行，先逐个编译源文件，然后再进行链接，形成最终的可执行程序。参数</span><span lang="EN-US">-c</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就是声明只进行编译操作。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.2.2<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">使用<span lang="EN-US">Makefile<o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当工程达到一定的规模的时候，</span><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US">2.2.1</span></st1:chsdate><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的做法显然是不能满足要求的，如果非要那样做，将会带来很大的工作量，而且还非常容易出错。这是我们就要使用</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来帮助我们完成工程的编译工作。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件相当于一个工程文件，文件中描述了工程中的源代码、额外需要的库文件及其路径、额外需要的头文件路径已经编译器类型、编译参数等。通过</span><span lang="EN-US">make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令来调入</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进行工程的编译。当执行</span><span lang="EN-US">make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令是，会在当前目录下搜索名称为&ldquo;</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;或者&ldquo;</span><span lang="EN-US">makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;的文件，作为当前编译的工程文件，也可一指定其他的工程文件，如</span><span lang="EN-US">make &ndash;f MyMakefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一个简单的</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件内容如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US">#Makefile for Linux(RedHat)</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><v:shapetype id="_x0000_t62" coordsize="21600,21600" o:spt="62" adj="1350,25920" path="m3600,qx,3600l0@8@12@24,0@9,,18000qy3600,21600l@6,21600@15@27@7,21600,18000,21600qx21600,18000l21600@9@18@30,21600@8,21600,3600qy18000,l@7,0@21@33@6,xe"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="sum 10800 0 #0"></v:f><v:f eqn="sum 10800 0 #1"></v:f><v:f eqn="sum #0 0 #1"></v:f><v:f eqn="sum @0 @1 0"></v:f><v:f eqn="sum 21600 0 #0"></v:f><v:f eqn="sum 21600 0 #1"></v:f><v:f eqn="if @0 3600 12600"></v:f><v:f eqn="if @0 9000 18000"></v:f><v:f eqn="if @1 3600 12600"></v:f><v:f eqn="if @1 9000 18000"></v:f><v:f eqn="if @2 0 #0"></v:f><v:f eqn="if @3 @10 0"></v:f><v:f eqn="if #0 0 @11"></v:f><v:f eqn="if @2 @6 #0"></v:f><v:f eqn="if @3 @6 @13"></v:f><v:f eqn="if @5 @6 @14"></v:f><v:f eqn="if @2 #0 21600"></v:f><v:f eqn="if @3 21600 @16"></v:f><v:f eqn="if @4 21600 @17"></v:f><v:f eqn="if @2 #0 @6"></v:f><v:f eqn="if @3 @19 @6"></v:f><v:f eqn="if #1 @6 @20"></v:f><v:f eqn="if @2 @8 #1"></v:f><v:f eqn="if @3 @22 @8"></v:f><v:f eqn="if #0 @8 @23"></v:f><v:f eqn="if @2 21600 #1"></v:f><v:f eqn="if @3 21600 @25"></v:f><v:f eqn="if @5 21600 @26"></v:f><v:f eqn="if @2 #1 @8"></v:f><v:f eqn="if @3 @8 @28"></v:f><v:f eqn="if @4 @8 @29"></v:f><v:f eqn="if @2 #1 0"></v:f><v:f eqn="if @3 @31 0"></v:f><v:f eqn="if #1 0 @32"></v:f><v:f eqn="val #0"></v:f><v:f eqn="val #1"></v:f></v:formulas><v:path o:connecttype="custom" o:connectlocs="10800,0;0,10800;10800,21600;21600,10800;@34,@35" textboxrect="791,791,20809,20809"></v:path><v:handles><v:h position="#0,#1"></v:h></v:handles></v:shapetype><v:shape id="_x0000_s1039" style="MARGIN-TOP: 7.8pt; Z-INDEX: 14; LEFT: 0px; MARGIN-LEFT: 225pt; WIDTH: 54pt; TEXT-INDENT: 0px; POSITION: absolute; HEIGHT: 31.2pt; TEXT-ALIGN: left" adj="-7640,29804" type="#_x0000_t62"><v:textbox>
<table cellspacing="0" cellpadding="0" width="100%">
 <tbody>
  <tr>
   <td style="BORDER-LEFT-COLOR: #ece9d8; BORDER-BOTTOM-COLOR: #ece9d8; BORDER-TOP-COLOR: #ece9d8; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #ece9d8">
   <div>
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">宏定义</span></p>
   </div>
   </td>
  </tr>
 </tbody>
</table>
</v:textbox></v:shape><v:shape id="_x0000_s1036" style="MARGIN-TOP: 0px; Z-INDEX: 11; LEFT: 0px; MARGIN-LEFT: 198pt; WIDTH: 9pt; POSITION: absolute; HEIGHT: 101.4pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US">#</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目标程序名称</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US">BIN_NAME=demo</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US">#</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器及编译参数</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US">CC = gcc</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US">CXX = g++</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; tab-stops: list 36.0pt"><span lang="EN-US">CXXFLAGS = -g</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shape id="_x0000_s1040" style="MARGIN-TOP: 7.8pt; Z-INDEX: 15; LEFT: 0px; MARGIN-LEFT: 261pt; WIDTH: 63pt; TEXT-INDENT: 0px; POSITION: absolute; HEIGHT: 31.2pt; TEXT-ALIGN: left" adj="-2949,31362" type="#_x0000_t62"><v:textbox>
<table cellspacing="0" cellpadding="0" width="100%">
 <tbody>
  <tr>
   <td style="BORDER-LEFT-COLOR: #ece9d8; BORDER-BOTTOM-COLOR: #ece9d8; BORDER-TOP-COLOR: #ece9d8; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #ece9d8">
   <div>
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件列表</span></p>
   </div>
   </td>
  </tr>
 </tbody>
</table>
</v:textbox></v:shape><span lang="EN-US">#</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">源代码列表</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shape id="_x0000_s1037" style="MARGIN-TOP: 0px; Z-INDEX: 12; LEFT: 0px; MARGIN-LEFT: 243pt; WIDTH: 9pt; POSITION: absolute; HEIGHT: 78pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US">SRCS=\</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>demo.cpp \</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>func.cpp</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">#</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目标文件列表，通过源代码列表生成</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">OBJS=${SRCS:.cpp=.o}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">#</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">依赖关系</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shape id="_x0000_s1038" style="MARGIN-TOP: 0px; Z-INDEX: 13; LEFT: 0px; MARGIN-LEFT: 279pt; WIDTH: 9pt; POSITION: absolute; HEIGHT: 210.6pt; TEXT-ALIGN: left" type="#_x0000_t88"></v:shape><span lang="EN-US">#depends</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">all:${BIN_NAME}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="COLOR: red">.depends : ${SRCS}<span style="mso-spacerun: yes">&nbsp; </span>#</span><span style="COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">依赖规则</span><span lang="EN-US" style="COLOR: red"><o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="COLOR: red"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>@echo Creating depend information,please wait ...<o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><v:shape id="_x0000_s1041" style="MARGIN-TOP: 0px; Z-INDEX: 16; LEFT: 0px; MARGIN-LEFT: 306pt; WIDTH: 63pt; TEXT-INDENT: 0px; POSITION: absolute; HEIGHT: 31.2pt; TEXT-ALIGN: left" adj="-6549,29804" type="#_x0000_t62"><v:textbox>
<table cellspacing="0" cellpadding="0" width="100%">
 <tbody>
  <tr>
   <td style="BORDER-LEFT-COLOR: #ece9d8; BORDER-BOTTOM-COLOR: #ece9d8; BORDER-TOP-COLOR: #ece9d8; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #ece9d8">
   <div>
   <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">依赖关系</span></p>
   </div>
   </td>
  </tr>
 </tbody>
</table>
</v:textbox></v:shape><span lang="EN-US" style="COLOR: red"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>${CXX} -M ${SRCS} &gt; .depends<span style="mso-spacerun: yes">&nbsp;&nbsp; </span>#</span><span style="COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行的命令</span><span lang="EN-US" style="COLOR: red"><o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="COLOR: red">-include .depends<o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="COLOR: blue">#%.o:%.cpp<o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="COLOR: blue">#<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp; </span>@echo Compling file: $? please wait ...<o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="COLOR: blue">#<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp; </span>${CXX} ${CXXFLAGS} -c $?<o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">${BIN_NAME}:${OBJS}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>@echo Linking file: $@ please wait ...</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>${CXX} -o $@ ${OBJS}</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">clean:</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>rm -f ${BIN_NAME} ${OBJS} *pure .depends</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件中，大体来说分为&ldquo;宏定义&rdquo;、&ldquo;文件列表&rdquo;和&ldquo;依赖关系&rdquo;三个部分。宏定义中定义</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中可以使用的一些宏，定义好一个宏以后，在</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的后面部分可以通过宏引用来获得宏的值。像编译器、编译参数等通常都会定义成宏，然后通过修改宏的值就可以修改编译器类型及编译参数。在更复杂的</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，宏定义中还会包含依赖的库文件、需要增加的库文件路径及头文件路径、程序中预定义的宏等。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其实文件列表也是一个宏，只是考虑到他的重要性，所以单独作为一个部分来介绍。在后面的依赖关系中，就会用到这个宏。文件列表中定义了工程包含的所有源文件和这些源文件编译以后生成的目标文件。目标文件可以通过源文件列表生成。上面我们使用</span><span lang="EN-US">${SRCS:.cpp=.o}</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来生成目标文件列表，意思就是说把源文件中所有扩展名为&ldquo;</span><span lang="EN-US">.cpp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;换成&ldquo;</span><span lang="EN-US">.o</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">依赖关系部分是</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件的关键，其中定义了多个依赖关系。每一个依赖关系又包括一个依赖规则和一组执行的命令。依赖规则由目标和依赖对象构成，也就是说这个目标依赖于指定的依赖对象。当执行</span><span lang="EN-US">make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的时候，如果发现目标不存在或者目标的依赖对象的更新时间比目标还新，就会执行依赖关系中的命令，来完成对目标的编译。</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中可以定义多个目标，每个目标对应一个依赖关系和一组命令。执行</span><span lang="EN-US">make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的时候，可以执行要编译的目标。如</span><span lang="EN-US">make clean</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示检查执行目标</span><span lang="EN-US">clean</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span><span lang="EN-US">all</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是一个默认的目标，即执行</span><span lang="EN-US">make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不加参数的时候，就会默认为要检查执行</span><span lang="EN-US">all</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个目标。</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中可以为</span><span lang="EN-US">all</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目标指定依赖对象和要执行的命令。</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，也可以只指定依赖关系，不指定要执行的命令，这种情况大多用于依赖对象也是一个定义的目标。</span><span lang="EN-US">Make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在检查依赖关系的时候，如果发现依赖对象也是一个目标，就会先去检查这个目标的依赖关系，看是否需要重新编译这个目标，然后才会执行本依赖关系下面的命令。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为了实现源文件的编译，我们在依赖关系中需要定义源文件和目标文件之间的依赖关系，然后执行程序和这些目标文件之间建立一个依赖关系。这样就可以实现整个工程的编译了。上面的这个</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，包含了两种定义这种依赖关系的方法，一种是通过编译器的&ldquo;</span><span lang="EN-US">-M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;命令来形成依赖关系文件，然后把这个文件的内容</span><span lang="EN-US">include</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">到当前的依赖关系中，另一种是通过匹配替换的做法，直接通过源文件和目标文件的映射关系形成依赖关系。红色字体部分和蓝色字体部分分别代表这两种做法。&ldquo;</span><span lang="EN-US">-M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;参数是</span><span lang="EN-US">gcc/g++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器特有的，其他编译器一般没有这个参数，应该使用第二种做法。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在不同的系统中，</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的语法会有一些细微的差别，在进行多平台移植的时候应该注意这个问题，分别对不同的系统编写不同的</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l2 level3 lfo1; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.2.3<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">automake</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">和<span lang="EN-US">autoconf<o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">Makefile </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基本结构虽然很简单，但是妥善运用这些规则就可以变换出许多不同的花样。却也因为这样，许多刚刚开始学习写</span><span lang="EN-US">Makefile </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时会觉得没有规范可以遵循，每个人写出来的</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都不大一样，不知道从哪里下手，而且常常会受到自己的开发环境的限制，只要环境参数不同或者路径更改，可能</span><span lang="EN-US"> Makefile </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就得跟着修改修改。虽然有</span><span lang="EN-US"> GNU Makefile Conventions (GNU Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">惯例例</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">订出一些使用</span><span lang="EN-US"> GNU </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程式设计时撰写</span><span lang="EN-US"> Makefile </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一些标准和规范，但是内容很长而且很复杂，并且经常作一些调整，为了减轻程序开发人员维护</span><span lang="EN-US">Makefile </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的负担，因此出现了</span><span lang="EN-US">Automake</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序设计者只需要写一些预先定义好的宏</span><span lang="EN-US"> (macro)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，提交给</span><span lang="EN-US">Automake</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">处理后会产生一个可以供</span><span lang="EN-US"> Autoconf </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用的</span><span lang="EN-US"> Makefile.in</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件。再配合利用</span><span lang="EN-US"> Autoconf</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">产生的自动培植设置文件</span><span lang="EN-US"> configure </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">即可产生一份符合符合</span><span lang="EN-US"> GNU Makefile </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">惯例的</span><span lang="EN-US"> Makeifle </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">了。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>automake</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的基本用法，是先用</span><span lang="EN-US">autoscan</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">搜索当前目录，然后形成一个</span><span lang="EN-US">configure.scan</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，然后以</span><span lang="EN-US">configure.scan</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件为蓝本，形成一个</span><span lang="EN-US">configure.in</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，这是最终需要的文件。然后使用</span><span lang="EN-US">aclocal</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">处理一下本地的宏，再使用</span><span lang="EN-US">autoconf</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">生成一个</span><span lang="EN-US">configure</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本文件。</span><span lang="EN-US">configure</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本文件用来形成最终的</span><span lang="EN-US">makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。之后编译一个</span><span lang="EN-US">Makefile.am</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，定义</span><span lang="EN-US">automake</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">需要的一些宏，包括源文件列表等。执行</span><span lang="EN-US">automake</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，形成</span><span lang="EN-US">Makefile.in</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件。这样，需要的准备工作基本完成。编译的时候，通过执行</span><span lang="EN-US">configure</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本，会自动生成</span><span lang="EN-US">Makefile</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，然后再执行</span><span lang="EN-US">make</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就可以了。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关于</span><span lang="EN-US">automake</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的详细用法请查看参考资料。</span></p>
<h2 style="MARGIN: 13pt 0cm 13pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level2 lfo5; tab-stops: list 18.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; mso-bidi-font-family: Arial; mso-fareast-font-family: Arial"><span style="mso-list: Ignore"><font face="Arial">2.3</font><span style="FONT: 7pt 'Times New Roman'"> </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">运行和调试</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不统，</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的文件只有有可执行的权限就可以执行，不像</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">那样依赖于扩展名。所以</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的执行程序大都没有扩展名，任何文件只要给了一个执行权限，就可以直接运行。可以通过</span><span lang="EN-US">chmod +x</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来给一个文件增加可执行的权限。编译后形成的目标文件，通常都已经有了执行的权限，所以可以直接执行。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level3 lfo5; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.3.1<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">设置运行环境<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于简单的程序来说，不用设置什么运行环境，直接运行即可。对于负责的程序来讲，可能执行程序和需要的共享库文件不在同一个目录下，就需要设置一些运行环境了。设置运行环境主要就是设置共享库的路径。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的共享库，相当于</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的动态库</span><span lang="EN-US">(dll</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，是一种以</span><span lang="EN-US">.so</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为扩展名的文件。系统的共享库存放在</span><span lang="EN-US">/usr/lib</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，程序运行的时候会自动去那个目录下面寻找需要的共享库。对于用户自己开发的共享库，一般不能放在</span><span lang="EN-US">/usr/lib</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目录下面，而是放在用户的程序目录下面。一个</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">比较复杂的程序，其目录结构分的比较清晰，并不是把所有的文件都放在一个目录下面。下面列出了一个典型的目录结构：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">mainpath<span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序主目录</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">mainpath/bin<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行程序目录</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">mainpath/lib<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">共享库目录</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这种情况下，就需要设置程序的运行环境，指定库文件目录。设置运行环境其实就是在运行程序前设置若干个环境变量，其中共享库的路径就是其中之一，也可一设置一些程序需要的其他的环境变量。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面用</span><span lang="EN-US">LD_LIBRARY_PATH</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来表示用户共享库的路径。设置完环境变量，就可以运行程序了。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有一种更方便的方法，就是编写执行脚本。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的脚本相当于</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的批处理文件，就是执行一系列的命令。本质上来说，脚本文件就是一个文本文件，编辑完成后增加一个可执行权限即可。在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的终端窗口，都是基于外壳（</span><span lang="EN-US">shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）的。在</span><span lang="EN-US">UNIX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中大家最常使用</span><span lang="EN-US">Bourne&nbsp;Shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以及</span><span lang="EN-US">C&nbsp;Shell&nbsp;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，系统默认采用的是</span><span lang="EN-US">Bourne&nbsp;Shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。不同的</span><span lang="EN-US">shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有不同的编程语言，也就是说编写</span><span lang="EN-US">shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本的语言，用来实现一些更高级的功能。在脚本中，可以指定本脚本采用的语言。关于</span><span lang="EN-US">shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编程的详细信息，请查阅参考资料。一般情况下，</span><span lang="EN-US">Bourne&nbsp;Shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本文件以</span><span lang="EN-US">.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为扩展名，</span><span lang="EN-US">C Shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本文件以</span><span lang="EN-US">.csh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为扩展名。这里我们以</span><span lang="EN-US">Bourne&nbsp;Shell</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为例。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一个典型的程序目录中，一般存在</span><span lang="EN-US">3</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个脚本：执行脚本</span><span lang="EN-US">(run.sh)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、停止进程脚本（</span><span lang="EN-US">kill.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）和设置环境脚本</span><span lang="EN-US">(setenv.sh)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。脚本文件一般都放在程序的主目录下面，进入主目录可以直接通过这些脚本来执行程序。下面简单列出了这几个脚本的内容。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">setenv.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>#!/bin/sh</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">path=`pwd`</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">LD_LIBRARY_PATH=$path/lib:$LD_LIBRARY_PATH</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">export LD_LIBRARY_PATH</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">run.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>#!/bin/sh</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">path=`pwd`</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">LD_LIBRARY_PATH=$path/lib:$LD_LIBRARY_PATH</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">export LD_LIBRARY_PATH</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">cd bin</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">./demo</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-para-margin-left: 2.0gd"><span lang="EN-US">cd ..</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>kill.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; mso-para-margin-left: 4.0gd"><span lang="EN-US">#!/usr/bin/sh</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; mso-para-margin-left: 4.0gd"><span lang="EN-US">for sid in `ps -e |grep demo |awk {'print '}`</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; mso-para-margin-left: 4.0gd"><span lang="EN-US">do</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; mso-para-margin-left: 4.0gd"><span lang="EN-US">kill $sid</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; mso-para-margin-left: 4.0gd"><span lang="EN-US">done</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">值得注意的一点是，外壳其实也是一个进程，运行脚本以后会创建一个新的进程。环境变量依赖于进程，也就是说脚本里面设置的环境变量在脚本完成后将会消失，不回影响外壳进程和其他进程。也就是说，正常情况下我们的</span><span lang="EN-US">setenv.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">相当于不起任何作用。不过可以通过另一种执行方法来保留脚本执行过程中设置的环境变量，即&ldquo;</span><span lang="EN-US">. setenv.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;。其实就是在执行命令的前面加上一个&lsquo;</span><span lang="EN-US">.</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;和空格。这样脚本中设置的环境变量就会作用域执行这个脚本的外壳进程，也会影响到以后在这个外壳下面运行的所有进程。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level3 lfo5; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.3.2<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">使用调试工具进行调试<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序的调试，是程序开发中最重要的一部分，通过调试来找到程序中的</span><span lang="EN-US">bug</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的程序调试工具有很多，包括</span><span lang="EN-US">IDE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境下的调试工具和字符界面的调试工具。这里我们主要介绍字符界面的调试工具。常用的调是工具是</span><span lang="EN-US">dbx</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，大部分</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统下都有。在</span><span lang="EN-US">linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，调试工具为</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，功能跟</span><span lang="EN-US">dbx</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类似。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类似，要以调试方式运行程序，就必须按照</span><span lang="EN-US">debug</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">版来编译程序。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的编译一一般通过</span><span lang="EN-US">-g</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数来声明使用</span><span lang="EN-US">debug</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式进行编译，这样编译后的目标文件中就包含了源代码的信息。下面以</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为例，介绍一下</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面程序调试的基本方法。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l5 level1 lfo6; tab-stops: list 42.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">1)<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以调试方式运行程序</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在执行程序所在的目录下，执行</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，以程序名称为参数即可进入</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调试界面。如</span><span lang="EN-US">:<span style="COLOR: red">gdb demo</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l5 level1 lfo6; tab-stops: list 42.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">2)<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">查看源文件，设置断点</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，使用</span><span lang="EN-US">list</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以查看主函数所在的文件的内容。默认情况下，一次显示</span><span lang="EN-US">10</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">行内容，再次执行</span><span lang="EN-US">list</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以显示后面的</span><span lang="EN-US">10</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">行。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">确定要在哪行上设置断点，然后用</span><span lang="EN-US">break</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令进行断点设置。如：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US" style="COLOR: red">break 10</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示在第</span><span lang="EN-US">10</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">行上设置一个断点。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US">break</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令还可以指定要设置断点的文件（如果不是主函数所在的文件），如：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US" style="COLOR: red">break func.cpp:10</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示在</span><span lang="EN-US">func.cpp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的第</span><span lang="EN-US">10</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">行上设置一个断点。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">除了在具体的行上设置断点外，还可以在某个函数上设置断点，只要把行号换成函数名即可。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US">clear</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令用来清楚当前行的断点，</span><span lang="EN-US">delete</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以删除所有设置的断点。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l5 level1 lfo6; tab-stops: list 42.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">3)<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行程序</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设置完断点后，可以在</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下通过</span><span lang="EN-US">run</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令运行程序，如果程序需要什么参数，直接放在</span><span lang="EN-US">run</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令后即可，如：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US" style="COLOR: red">run &ndash;start<o:p></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中</span><span lang="EN-US" style="COLOR: red">-start</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是程序允许需要的一个参数。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l5 level1 lfo6; tab-stops: list 42.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">4)<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">断点处程序分析</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当程序执行到断点的时候，就会定下来等待用户进行处理，这是可以通过一些命令来查看程序当前的运行状态，这些命令包括：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US">print<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打印变量的值，只需要用变量名做命令参数即可</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US">where<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">显示程序当前的调用栈</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US">set variable </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改变变量的值，可能会影响到程序后面运行的结果</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l5 level1 lfo6; tab-stops: list 42.0pt"><span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"><span style="mso-list: Ignore">5)<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">单步调试</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在断点处处理完成后，可以继续往下执行程序，</span><span lang="EN-US">next</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令用来执行一行代码，</span><span lang="EN-US">step</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令用来跟踪到即将执行的函数中。</span><span lang="EN-US">continue</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以继续运行当前程序，直到遇到下一个断点。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上述流程中，简单介绍了一些如何使用使用</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来进行程序的调试。</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的所有命令，都可以用简写来表示，只要写道能够区分处改命令的字母数即可，比如可以简单的输入</span><span lang="EN-US">n</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示</span><span lang="EN-US">next</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令。除了上面介绍的命令外，还有很多有用的命令。</span><span lang="EN-US">attach</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">detach</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令，可以在程序正常运行的情况下把</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">帮定到一个进程中，进行调试，调试结束后恢复正常的程序运行，推出</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对程序运行没有影响；</span><span lang="EN-US">pwd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以显示当前的工作目录，</span><span lang="EN-US">cd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以改变当前的工作目录；</span><span lang="EN-US">thread</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以查看当前的线程</span><span lang="EN-US">ID</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。还有很多别的命令，可以通过</span><span lang="EN-US">help</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令获得详细的帮助信息。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">除了</span><span lang="EN-US">dbx</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">外，</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面还有很多调试工具，详细信息请看参考资料。</span></p>
<h3 style="MARGIN: 13pt 0cm 13pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level3 lfo5; tab-stops: list 36.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">2.3.3<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">core dump<o:p></o:p></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发人员来说，</span><span lang="EN-US">core dump</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是再熟悉不过的了。再</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，</span><span lang="EN-US">core dump</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就是程序</span><span lang="EN-US">bug</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的最严重的体现。</span><span lang="EN-US">core dump</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">又叫核心转储，当程序运行过程中发生异常，程序以外退出的时候，系统会把程序当前的内存状况存储在一个</span><span lang="EN-US">core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件中，就叫</span><span lang="EN-US">core dump</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">既然</span><span lang="EN-US">core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件记录了程序运行时的情况，就可以通过</span><span lang="EN-US">core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件来分析错误的原因。使用</span><span lang="EN-US">gdb/dbx </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行程序名</span><span lang="EN-US"> core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就可以把程序恢复到发生错误的哪一时刻，可以看到程序在执行哪行代码，调用什么函数时发生了错误。这是，可以借助调试工具的其他命令进行更细致的分析。个人觉得，</span><span lang="EN-US">Solaris</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下实现的</span><span lang="EN-US">dbx</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">远比</span><span lang="EN-US">gdb</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">强大的多，可以看到更多的信息。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">值得注意的是，在</span><span lang="EN-US">linux</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面有一个系统限制，就是</span><span lang="EN-US">core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件的大小。如果这个限制设成</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，则程序发生异常以后不回产生</span><span lang="EN-US">core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件。如果想得到</span><span lang="EN-US">core</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，请使用</span><span lang="EN-US">ulimit &ndash;c</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令来调整这个参数。</span><span lang="EN-US">ulimit &ndash;a</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以查看到系统当前的限制参数情况。</span></p>
<h1 style="MARGIN: 17pt 0cm 16.5pt 18pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo1; tab-stops: list 18.0pt"><span lang="EN-US" style="FONT-SIZE: 15pt; LINE-HEIGHT: 240%; FONT-FAMILY: 黑体; mso-bidi-font-family: 黑体"><span style="mso-list: Ignore">3.<span style="FONT: 7pt 'Times New Roman'"> </span></span></span><span style="FONT-SIZE: 15pt; LINE-HEIGHT: 240%; FONT-FAMILY: 黑体">常用命令介绍<span lang="EN-US"><o:p></o:p></span></span></h1>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的常用命令，跟</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的控制台命令有很大差别。</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的命令，可能是一个执行程序，或者一个可以执行的脚本，系统的命令一般都可以在</span><span lang="EN-US">/usr/bin/</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面找到。另外需要说明的一点，</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面严格区分文件名的大小写，包括命令的大小写。下面简单介绍一下</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统下常用的几个命令。</span></p>
<h2 style="MARGIN: 13pt 0cm"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><font face="Arial">3.1 </font></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">常用命令列表</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">ls<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">列出当前目录下的文件，相当于</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">dir</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">cd<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">切换目录，和</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span><span lang="EN-US">cd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令相同。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">mkdir<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">创建一个目录。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">rm<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除一个文件或者目录。</span><span lang="EN-US">-r</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数表示删除的是目录，</span><span lang="EN-US">-f</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数表示强制删除。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">mv<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">移动或者修改文件</span><span lang="EN-US">/</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目录名称。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">cp<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拷贝文件或目录，</span><span lang="EN-US">-r</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数表示拷贝的对象是目录。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">ps<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">查看当前系统的进程情况，</span><span lang="EN-US">-e</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是最常用的一个参数，表示列出所有进程。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 62.8pt; TEXT-INDENT: -44.8pt"><span lang="EN-US">man<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">查看手册，这是一个最常用的命令，通过他可以查看指定命令或者函数的使用手册。比如</span><span lang="EN-US">man ps</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就可以产看</span><span lang="EN-US">ps</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令的帮助手册，</span><span lang="EN-US">man fopen</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以查看</span><span lang="EN-US">fopen</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数的用法。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 62.8pt; TEXT-INDENT: -44.8pt"><span lang="EN-US">find<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在指定目录下查找指定的文件。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 62.8pt; TEXT-INDENT: -44.8pt"><span lang="EN-US">grep<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在指定文件中查找指定的内容。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">vi<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编辑文本文件，后面会做详细的介绍。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt"><span lang="EN-US">tar<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件打包和解包工具，通过</span><span lang="EN-US">cvf</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数打包，通过</span><span lang="EN-US">xvf</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解包</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 62.8pt; TEXT-INDENT: -44.8pt"><span lang="EN-US">gzip<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">压缩工具，可以把文件压缩成</span><span lang="EN-US">gz</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，通过</span><span lang="EN-US">-d</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数进行解压缩，常于</span><span lang="EN-US">tar</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令一起使用。</span></p>
<h2 style="MARGIN: 13pt 0cm"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><font face="Arial">3.2 </font></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">命令的组合</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面，可以把多个命令组合使用，可以把一个命令的执行结果作为另一个命令的输入。其中，最常跟别的命令组合使用的命令就是</span><span lang="EN-US">grep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。在</span><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US">2.3.1</span></st1:chsdate><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的那个</span><span lang="EN-US">kill.sh</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本中，我们就使用了这样一个组合命令&ldquo;</span><span lang="EN-US">ps -e |grep demo |awk {'print '}</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;，用来列出当前系统中所有名称为</span><span lang="EN-US">demo</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的进程的进程号。这种用法是我们开发过程中最常用的方法。另外如果我们想知道我们的程序的网络情况，可以通过</span><span lang="EN-US">netstat</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令和</span><span lang="EN-US">grep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令来组合使用，获得指定端口的状态情况，比如</span><span lang="EN-US">netstat &ndash;a | grep 43001</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，这个命令将列出当前系统中所有在端口</span><span lang="EN-US">43001</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上的连接情况。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通常的</span><span lang="EN-US">grep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令，只能查找当前目录下的文件，比如：</span><span lang="EN-US">grep </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&lsquo;</span><span lang="EN-US">OPEN_MAX&rsquo; *.h </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就是查找当前目录下面的所有头文件中是否含有&ldquo;</span><span lang="EN-US">OPEN_MAX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;这个词。而</span><span lang="EN-US">find</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令可以查找指定路径下面的所有子目录，发现所有匹配的文件，那么，我们就可以用</span><span lang="EN-US">grep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令和</span><span lang="EN-US">find</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令组合，来实现子目录下的文件内容查找。命令格式如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">grep 'OPEN_MAX' `find /usr/include -name '*.h'`</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样可以查找所有在</span><span lang="EN-US">/usr/include</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">及其子目录下的头文件，看是否包含&ldquo;</span><span lang="EN-US">OPEN_MAX</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;。执行的时候，先执行</span><span lang="EN-US">find</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令，形成一个文件列表，然后把这个文件列表作为</span><span lang="EN-US">grep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一个参数来执行</span><span lang="EN-US">grep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令。这是命令组合的另一种方式。</span></p>
<h2 style="MARGIN: 13pt 0cm"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><font face="Arial">3.3 vi</font></span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体; mso-ascii-font-family: Arial">简介</span><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%"><o:p></o:p></span></h2>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下最常用的一个文本编辑器，小巧而且功能强大，一次我们把它单独拿出来做一下介绍。如果想了解更详细的信息，请执行</span><span lang="EN-US">man vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">查看其联机帮助文档。</span></p>
<h3 style="MARGIN: 13pt 0cm"><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">3.3.1</span></st1:chsdate><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体"> </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">命令模式和编辑模式<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的工作模式包括命令模式和编辑模式两种。命令模式下可以执行</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中定义的一些命令，这些命令跟一些特定的键相对应，命令模式下所有的键盘相应将会作为命令来解释。编辑模式就是编辑文档的模式，在编辑模式下所有键盘的相应都为作为文档输入的内容。通过</span><span lang="EN-US">ESC</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键可以从编辑模式切换到命令模式。通过一些编辑命名可以从命令模式进入编辑模式。</span></p>
<h3 style="MARGIN: 13pt 0cm"><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">3.3.2</span></st1:chsdate><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体"> </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">基本命令<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基本命令指的是在命令模式下，通过敲键执行的命令，这里我们介绍几个常用的命令：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">i<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在当前开始插入，进入编辑模式</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">I<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在行首开始插入，进入编辑模式</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">a<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在当前字符后追加，进入编辑模式</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">A<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在行尾追加，进入编辑模式</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">x<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除当前光标处的字符</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">X<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除当前光标前面的字符</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">D<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除从光标位置到行尾的所有字符</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">dd<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除当前行</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">dw<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除当前的单词</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">u<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">取消刚才的操作</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">G<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跳到文件末尾</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">此外，在命令模式下，通过输入&lsquo;</span><span lang="EN-US">/</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;可以进行查询，通过输入&lsquo;</span><span lang="EN-US">:</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;可以输入一些其他命令。输入&lsquo;</span><span lang="EN-US">:</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;可以输入的命令包括：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">q<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">退出</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">w<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">保存</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">wq<span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">保存退出</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">q</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">！</span><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">强制退出，不保存</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">w</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">！</span><span lang="EN-US"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对受保护的文件强制写，包括只读文件</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">set number<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">显示行号</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数字</span><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跳到某一行</span></p>
<h3 style="MARGIN: 13pt 0cm"><span lang="EN-US" style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">3.3.3 </span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 173%; FONT-FAMILY: 黑体">查找和匹配<span lang="EN-US"><o:p></o:p></span></span></h3>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的查找功能也非常强大，命令模式下通过输入&lsquo;</span><span lang="EN-US">/</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;就可以进入查找模式，可以输入要查找的关键字。然后可以通过&lsquo;</span><span lang="EN-US">n</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;来查找下一处。</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在输入&lsquo;</span><span lang="EN-US">:</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rsquo;后，还可以输入一些匹配替换的命令&mdash;&mdash;&ldquo;</span><span lang="EN-US">%s</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;。命令的格式为&ldquo;</span><span lang="EN-US">:%s /str1/str<st1:chmetcnv w:st="on" unitname="”" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0">2<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><span lang="EN-US">&rdquo;</span></span></st1:chmetcnv><span lang="EN-US" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，执行之后将把当前文件中所有</span>str1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">替换成</span><span lang="EN-US">str2</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。举一个典型的例子，前面我们说过，</span><span lang="EN-US">Windows</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的文本文件如果以二进制的方式传到了</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，那么</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打开的时候每行的行尾就会出现一个&ldquo;</span><span lang="EN-US">^M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;，我们可以用</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打开这个文件，然后通过</span><span lang="EN-US">vi</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的匹配替换功能去掉这些&ldquo;</span><span lang="EN-US">^M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;。命令格式如下：</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>:%s /^M//</span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中&ldquo;</span><span lang="EN-US">^M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&rdquo;通过</span><span lang="EN-US">CTRL+V </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US"> CTRL+M</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来输入。</span></p>
</span></span>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2900360.html</guid>
        <pubDate>Mon, 02 Jun 2008 01:06:31 GMT</pubDate>

      </item>

      <item>
        <title>How To: Code Your First Web App (Part 1)</title>
        <link>http://kenneth.ycool.com/post.2863064.html</link>
        <description><![CDATA[<font face="Arial"><a href="http://paulstamatiou.com/2006/12/27/how-to-code-your-first-web-app-part-1">http://paulstamatiou.com/2006/12/27/how-to-code-your-first-web-app-part-1</a><br />
<div class="itemtext">
<p>In its most basic form, a web application is typically comprised of multiple files utilizing PHP and MySQL technologies on a <abbr title="Linux Apache MySQL PHP">LAMP</abbr>LAMP server. PHP provides a powerful means of carrying out your web application&rsquo;s functions by way of server-side scripting while MySQL is used to store information in a database. In this series of posts I will be showing you how easy <span id="more-922"></span>it is to create a simple web application framework which you can adapt for almost any purpose - all this with only basic PHP and MySQL knowledge.</p>
<p><strong>The following files will be available as a download in the next part, so don&rsquo;t worry about copying and pasting everything.</strong></p>
<h4>Planning &amp; Database Design</h4>
<p>Before you start creating your web application you need to figure out what your web application will be doing and what types of things will need to be stored in the database. I will be showing you how to handle user accounts in this how to.</p>
<p>You will have one table dedicated to storing user information; things like user name, password, email, session and user id. Depending on what your web application will do you might have more user-related fields. My party finder web application had additional fields for age, city and state. Then you might have another database table for other types of data stored on your web app - if your web app manages events you would probably have a table for events including fields like date, time, street, zip code, city, state, venue name, etcetera.</p>
<p>I&rsquo;ll leave the design of other database tables up to you so I&rsquo;ll continue with setting up a database and table for users. If you want to learn more about database design, <a href="http://www.dtgeeks.com/features/tutorialview/basic_database_design/">take a look at this great article</a>. Here&rsquo;s what I want to create so far: a database with a &ldquo;users&rdquo; table containing the fields &ldquo;user&rdquo;, &ldquo;password&rdquo;, &ldquo;email&rdquo;, &ldquo;session&rdquo; and &ldquo;id&rdquo;. The user id can be used later on for making specific MySQL queries on users since I will setup the id to automatically increment with each new user. Setting up auto-incrementing indexes is also just good programming practice.</p>
<p>Assuming you have phpMyAdmin installed on your server, go to the homepage for your phpMyAdmin install and create a new database named &ldquo;webapp&rdquo;. For those lacking phpMyAdmin, you can simply run the following code once logged into MySQL.</p>
<pre>create database webapp;</pre>
<p>Create the &ldquo;users&rdquo; table by selecting the newly created database &ldquo;webapp&rdquo; in phpMyAdmin and finding the &ldquo;Create new table on database webapp&rdquo; text at the bottom. Type in &ldquo;users&rdquo; for the name of the table as well as &ldquo;5&Prime; for the number of fields. I recommend using phpMyAdmin for the next part - filling out the details for each of the 5 fields.</p>
<div class="center"><img id="image925" alt="Webapp Database new table" src="http://paulstamatiou.com/wp-content/uploads/2006/12/webapp_newtable.jpg" /></div>
<p>The next hurdle to overcome regards which data types and attributes to set each field in our users table. The id for each of the users in the table should be an int(7) - an integer with room for 7 digit values. Unless you are expecting to have more than a million users you&rsquo;ll want to keep that value as small as possible. The same goes for most data types for table fields - keep them as small as possible to reduce overhead and increase speed. Cal Henderson of <a href="http://flickr.com/">Flickr</a> explains this concept in great detail in his book <a href="http://safari.oreilly.com/0596102356">Building Scalable Web Sites</a>.</p>
<p>The other fields we have - user, password, email and session, will all be of the type &ldquo;varchar&rdquo; but might have varying lengths. For email addresses and user names, I think 32 is long enough for typical user names/email addresses. That would be varchar(32). The sessions field will also be varchar(32) due to the way I will setup <a href="http://us3.php.net/session">PHP sessions</a>. Finally, the password field will be set to varchar(32) since I will implement <a href="http://en.wikipedia.org/wiki/Md5"><abbr title="Message-Digest algorithm 5">MD5</abbr>MD5</a> encryption before each password is stored or changed.</p>
<pre>CREATE TABLE `users` (
`id` INT( 7 ) NOT NULL AUTO_INCREMENT ,
`user` VARCHAR( 32 ) NULL ,
`password` VARCHAR( 32 ) NULL ,
`email` VARCHAR( 32 ) NULL ,
`session` VARCHAR( 32 ) NULL ,
INDEX ( `id` )
) TYPE = MYISAM ;</pre>
<div class="center"><img id="image924" alt="Webapp Database users table" src="http://paulstamatiou.com/wp-content/uploads/2006/12/webapp_table.jpg" /><br />
<small>Overview of the users table in phpMyAdmin</small></div>
<h4>Connecting to the Database</h4>
<p>Before I begin with the PHP functions for creating and accessing user information, I need to write a few lines of PHP to connect to the MySQL database. In a file called &ldquo;util.php&rdquo; I have written the following lines:</p>
<div class="codesnip-container">
<div class="codesnip"><span class="kw2">&lt;?php</span><br />
<span class="kw1">if</span><span class="br0">(</span> !<a href="http://www.php.net/defined"><span class="kw3">defined</span></a><span class="br0">(</span><span class="st0">&lsquo;IN_PHP&rsquo;</span><span class="br0">)</span> <span class="br0">)</span><br />
<span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">(</span><span class="st0">&ldquo;hacking attempt&rdquo;</span><span class="br0">)</span>;<br />
<span class="br0">}</span>
<p>&nbsp;</p>
<p><span class="re0">$mysql_host</span> = <span class="st0">&ldquo;localhost&rdquo;</span>;<br />
<span class="re0">$mysql_user</span> = <span class="st0">&ldquo;root&rdquo;</span>; <span class="co1">// YOUR USERNAME</span><br />
<span class="re0">$mysql_pass</span> = <span class="st0">&ldquo;root&rdquo;</span>; <span class="co1">// YOUR PASSWORD</span><br />
<span class="re0">$mysql_db</span> = webapp;<br />
<span class="kw2">?&gt;</span></p>
</div>
</div>
<p>The file will be loaded with each file in the web application requiring access to the database. The first few lines at the top are a minor precaution to ensure that no one can directly view this file and thus steal your database info. In all other web app PHP files I will define &ldquo;IN_PHP&rdquo;, allowing util.php to be accessed.</p>
<p>Now to actually connect to the database, I have a simple function in a new file called &ldquo;functions.php&rdquo; that will also be included in each web app file requiring database connectivity. This function is called xmysql_connect() since there is already <a href="http://us2.php.net/manual/en/function.mysql-connect.php">a PHP function named mysql_connect()</a>. This file also has the lines for that &ldquo;IN_PHP&rdquo; thing for basic security.</p>
<div class="codesnip-container">
<div class="codesnip"><span class="kw2">&lt;?php</span><br />
<span class="kw1">if</span><span class="br0">(</span> !<a href="http://www.php.net/defined"><span class="kw3">defined</span></a><span class="br0">(</span><span class="st0">&lsquo;IN_PHP&rsquo;</span><span class="br0">)</span> <span class="br0">)</span><br />
<span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">(</span><span class="st0">&ldquo;hacking attempt&rdquo;</span><span class="br0">)</span>;<br />
<span class="br0">}</span><br />
<span class="kw2">function</span> xmysql_connect<span class="br0">(</span><span class="br0">)</span><br />
<span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/global"><span class="kw3">global</span></a> <span class="re0">$mysql_host</span>, <span class="re0">$mysql_user</span>, <span class="re0">$mysql_pass</span>, <span class="re0">$mysql_db</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; @<a href="http://www.php.net/mysql_connect"><span class="kw3">mysql_connect</span></a><span class="br0">(</span><span class="re0">$msql_host</span>, <span class="re0">$mysql_user</span>, <span class="re0">$mysql_pass</span><span class="br0">)</span> or <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">(</span><span class="st0">&lsquo;Could not connect to database: &lsquo;</span> . <a href="http://www.php.net/mysql_error"><span class="kw3">mysql_error</span></a><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/mysql_select_db"><span class="kw3">mysql_select_db</span></a><span class="br0">(</span><span class="re0">$mysql_db</span><span class="br0">)</span> or <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">(</span><span class="st0">&lsquo;Could not select database: &lsquo;</span> . <a href="http://www.php.net/mysql_error"><span class="kw3">mysql_error</span></a><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br />
<span class="br0">}</span><br />
<span class="kw2">?&gt;</span></div>
</div>
<p>When xmysql_connect() is run in other web app files that include util.php, functions.php and define &ldquo;IN_PHP&rdquo;, a successful connection to the database is made. You can see how it accesses the database information from util.php. One thing you will quickly learn about PHP is that you must declare variables as global before they can be read within a function.</p>
<p>Wherever you see die(), that outputs a statement when the action it is OR&rsquo;d with fails. For example, if I forgot to specify a database name, mysql_select_db() wouldn&rsquo;t be able to run and would output &ldquo;Could not select database: &rdquo; and then concatenate (that&rsquo;s what the dot does) the mysql error. Outputting errors like this is good practice and helpful when it comes time to debug.</p>
<h4>How &rsquo;bout Them Users?</h4>
<p>To manage user accounts, there are several necessary functions I have included in the functions.php file. The first function below, create_user(), takes three parameters and feeds them into the database to create a new user. If your web application keeps track of more than just user name, password and email, you will have to edit this function to accommodate for the extra parameters.</p>
<p>The next function, user_exists(), does as it implies and checks to see if a user by the name $user already exists in the database. This is used later on when making new users. Meanwhile, get_user() polls the database to get the current, logged in user&rsquo;s information - based on the session. Finally, do_login() and do_logout() do exactly what you think while make_safe() is a very handy function given to me by <a title="Josh Pigford" href="http://sabotagemedia.com/">Josh Pigford</a> that is heavily used later on to ensure that the site is not vulnerable from mischievous data entry (it prevents things like <a href="http://en.wikipedia.org/wiki/XSS"><abbr title="Cross-site scripting">XSS</abbr>XSS</a> in forms). This is inline with data input validation for forms. There&rsquo;s a fantastic article that goes in-depth about various methods of data validation (things like validating phone numbers, etc) in the O&rsquo;Reilly book <a href="http://www.oreilly.com/catalog/webdbapps2/">Web Database Applications with PHP &amp; MySQL</a>.</p>
<div class="codesnip-container">
<div class="codesnip"><span class="kw2">function</span> create_user<span class="br0">(</span><span class="re0">$user</span>, <span class="re0">$password</span>, <span class="re0">$email</span><span class="br0">)</span> <span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$encpwd</span> = <a href="http://www.php.net/md5"><span class="kw3">md5</span></a><span class="br0">(</span><span class="re0">$password</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> = <span class="st0">&ldquo;insert into users set user=&rsquo;$user&rsquo;, password=&rsquo;$encpwd&rsquo;, email=&rsquo;$email&rsquo;&rdquo;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$result</span> = <a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">(</span><span class="re0">$query</span><span class="br0">)</span>;<br />
<span class="br0">}</span>
<p>&nbsp;</p>
<p><span class="kw2">function</span> user_exists<span class="br0">(</span><span class="re0">$user</span><span class="br0">)</span> <span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> = <span class="st0">&ldquo;select user from users where user=&rsquo;$user&rsquo;&rdquo;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$result</span> = <a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">(</span><span class="re0">$query</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">(</span><span class="re0">$result</span> == <span class="kw2">NULL</span><span class="br0">)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$line</span> = <a href="http://www.php.net/mysql_fetch_array"><span class="kw3">mysql_fetch_array</span></a><span class="br0">(</span><span class="re0">$result</span>, MYSQL_ASSOC<span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/mysql_free_result"><span class="kw3">mysql_free_result</span></a><span class="br0">(</span><span class="re0">$result</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$line</span> !== <span class="kw2">FALSE</span>;<br />
<span class="br0">}</span></p>
<p><span class="kw2">function</span> get_user<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> = <span class="st0">&ldquo;select user from users where session=&rsquo;&rdquo;</span>.<a href="http://www.php.net/session_id"><span class="kw3">session_id</span></a><span class="br0">(</span><span class="br0">)</span>.<span class="st0">&ldquo;&lsquo;&rdquo;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$result</span> = <a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">(</span><span class="re0">$query</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">(</span><span class="re0">$result</span> == <span class="kw2">NULL</span><span class="br0">)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$line</span> = <a href="http://www.php.net/mysql_fetch_array"><span class="kw3">mysql_fetch_array</span></a><span class="br0">(</span><span class="re0">$result</span>, MYSQL_ASSOC<span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/mysql_free_result"><span class="kw3">mysql_free_result</span></a><span class="br0">(</span><span class="re0">$result</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">(</span><span class="re0">$line</span> === <span class="kw2">FALSE</span><span class="br0">)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$line</span><span class="br0">[</span><span class="st0">&lsquo;user&rsquo;</span><span class="br0">]</span>;<br />
<span class="br0">}</span></p>
<p><span class="kw2">function</span> do_login<span class="br0">(</span><span class="re0">$user</span>, <span class="re0">$password</span><span class="br0">)</span> <span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$encpwd</span> = <a href="http://www.php.net/md5"><span class="kw3">md5</span></a><span class="br0">(</span><span class="re0">$password</span><span class="br0">)</span>; <span class="co1">//encrypt password with MD5!</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> = <span class="st0">&ldquo;select user, password from users where user=&rsquo;$user&rsquo;&rdquo;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$result</span> = <a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">(</span><span class="re0">$query</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">(</span><span class="re0">$result</span> == <span class="kw2">NULL</span><span class="br0">)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$line</span> = <a href="http://www.php.net/mysql_fetch_array"><span class="kw3">mysql_fetch_array</span></a><span class="br0">(</span><span class="re0">$result</span>, MYSQL_ASSOC<span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/mysql_free_result"><span class="kw3">mysql_free_result</span></a><span class="br0">(</span><span class="re0">$result</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">(</span> <span class="re0">$line</span><span class="br0">[</span><span class="st0">&lsquo;password&rsquo;</span><span class="br0">]</span> !== <span class="re0">$encpwd</span> <span class="br0">)</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> = <span class="st0">&ldquo;update users set session=&rsquo;&rdquo;</span>.<a href="http://www.php.net/session_id"><span class="kw3">session_id</span></a><span class="br0">(</span><span class="br0">)</span>.<span class="st0">&ldquo;&lsquo; where user=&rsquo;$user&rsquo;&rdquo;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$result</span> = <a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">(</span><span class="re0">$query</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">}</span></p>
<p><span class="kw2">function</span> do_logout<span class="br0">(</span><span class="re0">$user</span><span class="br0">)</span> <span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$query</span> = <span class="st0">&ldquo;update users set session=&rdquo; where user=&rsquo;$user&rsquo;&rdquo;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//that clears the session</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$result</span> = <a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">(</span><span class="re0">$query</span><span class="br0">)</span>;<br />
<span class="br0">}</span></p>
<p><span class="kw2">function</span> make_safe<span class="br0">(</span><span class="re0">$variable</span><span class="br0">)</span> <span class="br0">{</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$variable</span> = <a href="http://www.php.net/htmlentities"><span class="kw3">htmlentities</span></a><span class="br0">(</span><span class="re0">$variable</span>, ENT_QUOTES<span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">(</span><a href="http://www.php.net/get_magic_quotes_gpc"><span class="kw3">get_magic_quotes_gpc</span></a><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re0">$variable</span> = <a href="http://www.php.net/stripslashes"><span class="kw3">stripslashes</span></a><span class="br0">(</span><span class="re0">$variable</span><span class="br0">)</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$variable</span> = <a href="http://www.php.net/mysql_real_escape_string"><span class="kw3">mysql_real_escape_string</span></a><span class="br0">(</span><a href="http://www.php.net/trim"><span class="kw3">trim</span></a><span class="br0">(</span><span class="re0">$variable</span><span class="br0">)</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$variable</span> = <a href="http://www.php.net/strip_tags"><span class="kw3">strip_tags</span></a><span class="br0">(</span><span class="re0">$variable</span><span class="br0">)</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$variable</span>;<br />
<span class="br0">}</span></p>
</div>
</div>
<p>These functions finish off my functions.php file so now I can begin to concentrate on the main PHP file and forms.</p>
<h4>The Basic Framework</h4>
<p>Now that I have most of the vital functions taken care of, it&rsquo;s time to start coding the index.php file. Every new file will pretty much require a few includes and commands so creating a header.php file that will be included in each file is an excellent idea. My header.php file is composed of the following lines:</p>
<div class="codesnip-container">
<div class="codesnip"><span class="kw2">&lt;?php</span><br />
<a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">(</span><span class="st0">&lsquo;IN_PHP&rsquo;</span>, <span class="kw2">true</span><span class="br0">)</span>;<br />
<span class="co1">//very very basic security</span><br />
<span class="kw1">include</span><span class="br0">(</span><span class="st0">&lsquo;util.php&rsquo;</span><span class="br0">)</span>;<br />
<span class="kw1">include</span><span class="br0">(</span><span class="st0">&lsquo;functions.php&rsquo;</span><span class="br0">)</span>;<br />
<a href="http://www.php.net/session_start"><span class="kw3">session_start</span></a><span class="br0">(</span><span class="br0">)</span>; <br />
xmysql_connect<span class="br0">(</span><span class="br0">)</span>;
<p>&nbsp;</p>
<p><span class="co1">//these next lines are optional</span><br />
<span class="co1">//they provide unique page titles</span><br />
<span class="re0">$url</span> = <span class="re0">$_SERVER</span><span class="br0">[</span><span class="st0">&lsquo;REQUEST_URI&rsquo;</span><span class="br0">]</span>;<br />
<span class="re0">$pages</span> = <a href="http://www.php.net/array"><span class="kw3">Array</span></a><span class="br0">(</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&ldquo;/about.php&rdquo;</span> =&gt; <span class="st0">&ldquo;&amp;raquo; About&rdquo;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&ldquo;/blah.php&rdquo;</span> =&gt; <span class="st0">&ldquo;&amp;raquo; Blah&rdquo;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&ldquo;/blah2.php&rdquo;</span> =&gt; <span class="st0">&ldquo;&amp;raquo; Blah 2&Prime;</span><br />
<span class="br0">)</span>;<br />
<span class="re0">$title</span> = <span class="re0">$pages</span><span class="br0">[</span><span class="re0">$url</span><span class="br0">]</span>;<br />
<span class="kw2">?&gt;</span><br />
&lt; !DOCTYPE html PUBLIC <span class="st0">&ldquo;-//W3C//DTD XHTML 1.0 Transitional//EN&rdquo;</span> <span class="st0">&ldquo;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&rdquo;</span>&gt;&lt; html xmlns=<span class="st0">&ldquo;http://www.w3.org/1999/xhtml&rdquo;</span>&gt;</p>
<p>&lt;link rel=<span class="st0">&ldquo;stylesheet&rdquo;</span> type=<span class="st0">&ldquo;text/css&rdquo;</span> media=<span class="st0">&ldquo;screen&rdquo;</span> href=<span class="st0">&ldquo;style.css&rdquo;</span>/&gt;</p>
<p>&lt;head&gt;<br />
&nbsp; &nbsp;&lt;meta http-equiv=<span class="st0">&ldquo;Content-Type&rdquo;</span> content=<span class="st0">&ldquo;text/html;charset=utf-8&Prime;</span> /&gt;<br />
&nbsp; &nbsp;&lt;title&gt;My First Web App&nbsp; <span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$title</span>; ?&gt;&lt;/title&gt;<br />
&lt;/head&gt;</p>
</div>
</div>
<p>First, I defined my basic security precaution of the &ldquo;IN_PHP&rdquo; phrase that util.php and functions.php look for, then I included those two files. After that, <a href="http://us2.php.net/manual/en/function.session-start.php">session_start()</a> is called to initialize the user session. Finally, the xmysql_connect() function from functions.php is executed. There is now an active connection to the database.</p>
<p>The next PHP lines are a nifty way to dynamically alter page title names depending on what page the user is on. You have to manually input the pages and their accompanying page titles in the $pages array. The code grabs the current page requsted by the user with REQUEST_URI, looks in the array and snags the appropriate title. Since the page title is later declared as &ldquo;My First Web App&rdquo; and then a PHP echo of $title, the full title for the hypothetical about.php would be &ldquo;My First Web App &raquo; About&rdquo;.</p>
<p>The header file also links to a CSS file but I won&rsquo;t be covering any CSS or styling in this series of posts. The header file where you load other javascript files your web app might utilize or things like setting an API key if your web app makes uses Google Maps.</p>
<p>This is getting a bit long so I&rsquo;ll be splitting it up into parts. Tune in for the next segment hopefully tomorrow. You might find it easier to just grab <a href="http://feeds.feedburner.com/paulstamatiou">my RSS feed</a>. <strong><a href="http://paulstamatiou.com/2006/12/28/how-to-code-your-first-web-app-part-2/">Part 2</a> and <a href="http://paulstamatiou.com/2006/12/29/how-to-code-your-first-web-app-part-3/">Part 3</a> have been published.</strong></p>
</div>
<!--
				<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
				xmlns:dc="http://purl.org/dc/elements/1.1/"
				xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
			<rdf:Description rdf:about="http://paulstamatiou.com/2006/12/27/how-to-code-your-first-web-app-part-1"
    dc:identifier="http://paulstamatiou.com/2006/12/27/how-to-code-your-first-web-app-part-1"
    dc:title="How To: Code Your First Web App (Part 1)"
    trackback:ping="http://paulstamatiou.com/2006/12/27/how-to-code-your-first-web-app-part-1/trackback" />
</rdf:RDF>				--></font>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2863064.html</guid>
        <pubDate>Fri, 04 Apr 2008 03:04:43 GMT</pubDate>

      </item>

      <item>
        <title>PHP &amp; memcached</title>
        <link>http://kenneth.ycool.com/post.2859352.html</link>
        <description><![CDATA[<p><strong><em>肖理达 (KrazyNio AT hotmail.com), 2006.04. 06, 转载请注明出处</em></strong></p>
<p><strong>一、memcached 简介</strong></p>
<p>在很多场合，我们都会听到 <a href="http://www.danga.com/memcached/">memcached</a> 这个名字，但很多同学只是听过，并没有用过或实际了解过，只知道它是一个很不错的东东。这里简单介绍一下，memcached 是高效、快速的分布式内存对象缓存系统，主要用于加速 WEB 动态应用程序。</p>
<p><strong>二、memcached 安装</strong></p>
<p>首先是下载 memcached 了，目前最新版本是 1.1.12，直接从官方网站即可下载到 <a href="http://www.danga.com/memcached/dist/memcached-1.1.12.tar.gz">memcached-1.1.12.tar.gz</a>。除此之外，memcached 用到了 <a href="http://monkey.org/~provos/libevent/">libevent</a>，我<a href="http://monkey.org/~provos/libevent-1.1a.tar.gz">下载的是 libevent-1.1a.tar.gz</a>。</p>
<p>接下来是分别将 libevent-1.1a.tar.gz 和 memcached-1.1.12.tar.gz 解开包、编译、安装：</p>
<pre class="code" style="PADDING-BOTTOM: 20px; WIDTH: 500px"># tar -xzf libevent-1.1a.tar.gz
# cd libevent-1.1a
# ./configure --prefix=/usr
# make
# make install
# cd ..
# tar -xzf memcached-1.1.12.tar.gz
# cd memcached-1.1.12
# ./configure --prefix=/usr
# make
# make install
</pre>
<p>安装完成之后，memcached 应该在 /usr/bin/memcached。</p>
<p><strong>三、运行 memcached 守护程序</strong></p>
<p>运行 memcached 守护程序很简单，只需一个命令行即可，不需要修改任何配置文件（也没有配置文件给你修改 <img class="wp-smiley" alt=":)" src="http://nio.infor96.com/wp-includes/images/smilies/icon_smile.gif" /> ）：</p>
<pre class="code" style="PADDING-BOTTOM: 20px; WIDTH: 500px">/usr/bin/memcached -d -m 128 -l 192.168.1.1 -p 11211 -u httpd</pre>
<p>参数解释：</p>
<pre class="code" style="PADDING-BOTTOM: 20px; WIDTH: 500px">-d 以守护程序（daemon）方式运行 memcached；
-m 设置 memcached 可以使用的内存大小，单位为 M；
-l 设置监听的 IP 地址，如果是本机的话，通常可以不设置此参数；
-p 设置监听的端口，默认为 11211，所以也可以不设置此参数；
-u 指定用户，如果当前为 root 的话，需要使用此参数指定用户。
</pre>
<p>当然，还有其它参数可以用，<code>man memcached</code> 一下就可以看到了。</p>
<p><strong>四、memcached 的工作原理</strong></p>
<p>首先 memcached 是以守护程序方式运行于一个或多个服务器中，随时接受客户端的连接操作，客户端可以由各种语言编写，目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。PHP 等客户端在与 memcached 服务建立连接之后，接下来的事情就是存取对象了，每个被存取的对象都有一个唯一的标识符 key，存取操作均通过这个 key 进行，保存到 memcached 中的对象实际上是放置内存中的，并不是保存在 cache 文件中的，这也是为什么 memcached 能够如此高效快速的原因。注意，这些对象并不是持久的，服务停止之后，里边的数据就会丢失。</p>
<p><img id="image622" alt="image001.png" src="http://nio.infor96.com/wp-content/uploads/2006/11/image001.png" /></p>
<p><strong>三、PHP 如何作为 memcached 客户端</strong></p>
<p>有两种方法可以使 PHP 作为 memcached 客户端，调用 memcached 的服务进行对象存取操作。</p>
<p>第一种，PHP 有一个叫做 <a href="http://www.php.net/manual/en/ref.memcache.php">memcache 的扩展</a>，Linux 下编译时需要带上 <em>&ndash;enable-memcache[=DIR]</em> 选项，Window 下则在 php.ini 中去掉 php_memcache.dll 前边的注释符，使其可用。</p>
<p>除此之外，还有一种方法，可以避开扩展、重新编译所带来的麻烦，那就是直接使用 <a href="http://wikipedia.sourceforge.net/doc/memcached-client/_includes_memcached-client_php.html">php-memcached-client</a>。</p>
<p>本文选用第二种方式，虽然效率会比扩展库稍差一些，但问题不大。</p>
<p><strong>四、PHP memcached 应用示例</strong></p>
<p>首先 <a id="p481" href="http://nio.infor96.com/wp-content/uploads/2006/04/memcached-client.zip">下载 memcached-client.php</a>，在下载了 memcached-client.php 之后，就可以通过这个文件中的类&ldquo;memcached&rdquo;对 memcached 服务进行操作了。其实代码调用非常简单，主要会用到的方法有 add()、get()、replace() 和 delete()，方法说明如下：</p>
<p><code>add ($key, $val, $exp = 0)</code><br />
往 memcached 中写入对象，$key 是对象的唯一标识符，$val 是写入的对象数据，$exp 为过期时间，单位为秒，默认为不限时间；</p>
<p><code>get ($key)</code><br />
从 memcached 中获取对象数据，通过对象的唯一标识符 $key 获取；</p>
<p><code>replace ($key, $value, $exp=0)</code><br />
使用 $value 替换 memcached 中标识符为 $key 的对象内容，参数与 add() 方法一样，只有 $key 对象存在的情况下才会起作用；</p>
<p><code>delete ($key, $time = 0)</code><br />
删除 memcached 中标识符为 $key 的对象，$time 为可选参数，表示删除之前需要等待多长时间。</p>
<p>下面是一段简单的测试代码，代码中对标识符为 'mykey' 的对象数据进行存取操作：</p>
<pre class="code" style="PADDING-BOTTOM: 20px; WIDTH: 500px"><code><span style="COLOR: #000000">
&lt;pre&gt;
<span style="COLOR: #0000bb">&lt;?php
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;包含&nbsp;memcached&nbsp;类文件
</span><span style="COLOR: #007700">require_once(</span><span style="COLOR: #dd0000">'memcached-client.php'</span><span style="COLOR: #007700">);
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;选项设置
</span><span style="COLOR: #0000bb">$options&nbsp;</span><span style="COLOR: #007700">=&nbsp;array(
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #dd0000">'servers'&nbsp;</span><span style="COLOR: #007700">=&gt;&nbsp;array(</span><span style="COLOR: #dd0000">'192.168.1.1:11211'</span><span style="COLOR: #007700">),&nbsp;</span><span style="COLOR: #ff8000">//memcached&nbsp;服务的地址、端口，可用多个数组元素表示多个&nbsp;memcached&nbsp;服务
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #dd0000">'debug'&nbsp;</span><span style="COLOR: #007700">=&gt;&nbsp;</span><span style="COLOR: #0000bb">true</span><span style="COLOR: #007700">,&nbsp;&nbsp;</span><span style="COLOR: #ff8000">//是否打开&nbsp;debug
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #dd0000">'compress_threshold'&nbsp;</span><span style="COLOR: #007700">=&gt;&nbsp;</span><span style="COLOR: #0000bb">10240</span><span style="COLOR: #007700">,&nbsp;&nbsp;</span><span style="COLOR: #ff8000">//超过多少字节的数据时进行压缩
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #dd0000">'persistant'&nbsp;</span><span style="COLOR: #007700">=&gt;&nbsp;</span><span style="COLOR: #0000bb">false&nbsp;&nbsp;</span><span style="COLOR: #ff8000">//是否使用持久连接
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #007700">);
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;创建&nbsp;memcached&nbsp;对象实例
</span><span style="COLOR: #0000bb">$mc&nbsp;</span><span style="COLOR: #007700">=&nbsp;new&nbsp;</span><span style="COLOR: #0000bb">memcached</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$options</span><span style="COLOR: #007700">);
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;设置此脚本使用的唯一标识符
</span><span style="COLOR: #0000bb">$key&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #dd0000">'mykey'</span><span style="COLOR: #007700">;
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;往&nbsp;memcached&nbsp;中写入对象
</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">add</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'some&nbsp;random&nbsp;strings'</span><span style="COLOR: #007700">);
</span><span style="COLOR: #0000bb">$val&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">get</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">);
echo&nbsp;</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">.</span><span style="COLOR: #0000bb">str_pad</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'$mc-&gt;add()&nbsp;'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #0000bb">60</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'_'</span><span style="COLOR: #007700">).</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">;
</span><span style="COLOR: #0000bb">var_dump</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$val</span><span style="COLOR: #007700">);
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;替换已写入的对象数据值
</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">replace</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">,&nbsp;array(</span><span style="COLOR: #dd0000">'some'</span><span style="COLOR: #007700">=&gt;</span><span style="COLOR: #dd0000">'haha'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'array'</span><span style="COLOR: #007700">=&gt;</span><span style="COLOR: #dd0000">'xxx'</span><span style="COLOR: #007700">));
</span><span style="COLOR: #0000bb">$val&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">get</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">);
echo&nbsp;</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">.</span><span style="COLOR: #0000bb">str_pad</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'$mc-&gt;replace()&nbsp;'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #0000bb">60</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'_'</span><span style="COLOR: #007700">).</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">;
</span><span style="COLOR: #0000bb">var_dump</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$val</span><span style="COLOR: #007700">);
</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;删除&nbsp;memcached&nbsp;中的对象
</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">delete</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">);
</span><span style="COLOR: #0000bb">$val&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">get</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">);
echo&nbsp;</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">.</span><span style="COLOR: #0000bb">str_pad</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'$mc-&gt;delete()&nbsp;'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #0000bb">60</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'_'</span><span style="COLOR: #007700">).</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">;
</span><span style="COLOR: #0000bb">var_dump</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$val</span><span style="COLOR: #007700">);
</span><span style="COLOR: #0000bb">?&gt;
</span>&lt;/pre&gt;</span>
</code></pre>
<p>是不是很简单，在实际应用中，通常会把数据库查询的结果集保存到 memcached 中，下次访问时直接从 memcached 中获取，而不再做数据库查询操作，这样可以在很大程度上减轻数据库的负担。通常会将 SQL 语句 md5() 之后的值作为唯一标识符 key。下边是一个利用 memcached 来缓存数据库查询结果集的示例（此代码片段紧接上边的示例代码）：</p>
<pre class="code" style="PADDING-BOTTOM: 20px; WIDTH: 500px"><code><span style="COLOR: #000000">
<span style="COLOR: #0000bb">&lt;?php
$sql&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #dd0000">'SELECT&nbsp;*&nbsp;FROM&nbsp;users'</span><span style="COLOR: #007700">;
</span><span style="COLOR: #0000bb">$key&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">md5</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$sql</span><span style="COLOR: #007700">);&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #ff8000">//memcached&nbsp;对象标识符
</span><span style="COLOR: #007700">if&nbsp;(&nbsp;!(</span><span style="COLOR: #0000bb">$datas&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">get</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">))&nbsp;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;在&nbsp;memcached&nbsp;中未获取到缓存数据，则使用数据库查询获取记录集。
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #007700">echo&nbsp;</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">.</span><span style="COLOR: #0000bb">str_pad</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'Read&nbsp;datas&nbsp;from&nbsp;MySQL.'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #0000bb">60</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'_'</span><span style="COLOR: #007700">).</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">;
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000bb">$conn&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">mysql_connect</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'localhost'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'test'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'test'</span><span style="COLOR: #007700">);
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000bb">mysql_select_db</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'test'</span><span style="COLOR: #007700">);
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000bb">$result&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">mysql_query</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$sql</span><span style="COLOR: #007700">);
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(</span><span style="COLOR: #0000bb">$row&nbsp;</span><span style="COLOR: #007700">=&nbsp;</span><span style="COLOR: #0000bb">mysql_fetch_object</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$result</span><span style="COLOR: #007700">))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000bb">$datas</span><span style="COLOR: #007700">[]&nbsp;=&nbsp;</span><span style="COLOR: #0000bb">$row</span><span style="COLOR: #007700">;
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #ff8000">//&nbsp;&nbsp;将数据库中获取到的结果集数据保存到&nbsp;memcached&nbsp;中，以供下次访问时使用。
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000bb">$mc</span><span style="COLOR: #007700">-&gt;</span><span style="COLOR: #0000bb">add</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$key</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #0000bb">$datas</span><span style="COLOR: #007700">);
}&nbsp;else&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">.</span><span style="COLOR: #0000bb">str_pad</span><span style="COLOR: #007700">(</span><span style="COLOR: #dd0000">'Read&nbsp;datas&nbsp;from&nbsp;memcached.'</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #0000bb">60</span><span style="COLOR: #007700">,&nbsp;</span><span style="COLOR: #dd0000">'_'</span><span style="COLOR: #007700">).</span><span style="COLOR: #dd0000">&quot;n&quot;</span><span style="COLOR: #007700">;
}
</span><span style="COLOR: #0000bb">var_dump</span><span style="COLOR: #007700">(</span><span style="COLOR: #0000bb">$datas</span><span style="COLOR: #007700">);
</span><span style="COLOR: #0000bb">?&gt;</span>
</span>
</code></pre>
<p>可以看出，使用 memcached 之后，可以减少数据库连接、查询操作，数据库负载下来了，脚本的运行速度也提高了。</p>
<p>之前我曾经写过一篇名为<a href="http://nio.infor96.com/sharing-php-session-data-between-servers/">《PHP 实现多服务器共享 SESSION 数据》</a>文章，文中的 SESSION 是使用数据库保存的，在并发访问量大的时候，服务器的负载会很大，经常会超出 MySQL 最大连接数，利用 memcached，我们可以很好地解决这个问题，工作原理如下：</p>
<ul>
 <li>用户访问网页时，查看 memcached 中是否有当前用户的 SESSION 数据，使用 session_id() 作为唯一标识符；如果数据存在，则直接返回，如果不存在，再进行数据库连接，获取 SESSION 数据，并将此数据保存到 memcached 中，供下次使用； </li>
 <li>当前的 PHP 运行结束（或使用了 <a href="http://php.liukang.com/manual/en/function.session-write-close.php">session_write_close()</a>）时，会调用 My_Sess::write() 方法，将数据写入数据库，这样的话，每次仍然会有数据库操作，对于这个方法，也需要进行优化。使用一个全局变量，记录用户进入页面时的 SESSION 数据，然后在 write() 方法内比较此数据与想要写入的 SESSION 数据是否相同，不同才进行数据库连接、写入数据库，同时将 memcached 中对应的对象删除，如果相同的话，则表示 SESSION 数据未改变，那么就可以不做任何操作，直接返回了； </li>
 <li>那么用户 SESSION 过期时间怎么解决呢？记得 memcached 的 add() 方法有个过期时间参数 $exp 吗？把这个参数值设置成小于 SESSION 最大存活时间即可。另外别忘了给那些一直在线的用户延续 SESSION 时长，这个可以在 write() 方法中解决，通过判断时间，符合条件则更新数据库数据。 </li>
</ul>
<p><strong>五、相关资源</strong></p>
<ul>
 <li><a href="http://www.danga.com/memcached/">memcached 官方网站</a> </li>
 <li><a href="http://wikipedia.sourceforge.net/doc/memcached-client/_includes_memcached-client_php.html">PHP memcached client</a> </li>
 <li><a href="http://nio.infor96.com/wp-content/uploads/2006/04/memcached-client.zip">下载 memcached-client.php</a> </li>
</ul>
<!-- You can start editing here. -->...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2859352.html</guid>
        <pubDate>Wed, 02 Apr 2008 09:04:08 GMT</pubDate>

      </item>

      <item>
        <title>discuz标题不能超过80字符这个怎么修改成不限制那？</title>
        <link>http://kenneth.ycool.com/post.2857188.html</link>
        <description><![CDATA[<div class="archiver_postbody">注意：字符最大不能超过255<br />
<br />
第一步：<br />
修改include/post.func.php<br />
找： <br />
function checkpost() {<br />
&nbsp; &nbsp; global $subject, $message, $disablepostctrl, $minpostsize, $maxpostsize;<br />
&nbsp; &nbsp; if(strlen($subject) &gt; 80) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;return 'post_subject_toolong';<br />
&nbsp; &nbsp; }<br />
把80改为想要的数目<br />
<br />
第二步：修改模板 <br />
<br />
templates/default/post_newreply.htm<br />
&nbsp; &nbsp; } else if (theform.subject.value.length &gt; 80) { <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;alert(&quot;{lang post_subject_toolong}&quot;); <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;return false; <br />
templates/default/post_newthread.htm<br />
&nbsp; &nbsp;} else if (theform.subject.value.length &gt; 80) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;alert(&quot;{lang post_subject_toolong}&quot;); <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;theform.subject.focus(); <br />
templates/default/post_editpost.htm <br />
&nbsp; &nbsp; } else if (theform.subject.value.length &gt; 80) { <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;alert(&quot;{lang post_subject_toolong}&quot;); <br />
把80改为想要的数字 <br />
<br />
第三步：修改语言包 <br />
templates/default/messages.lang.php<br />
对不起，您的标题超过 80 个字符，请返回修改标题长度<br />
templates/default/templates.lang.php<br />
'post_subject_toolong' =&gt; '您的标题超过 80 个字符的限制。',<br />
把80改为想要的数字<br />
<br />
第四步：论坛后台－系统工具－升级数据库 <br />
ALTER TABLE `cdb_threads` CHANGE `subject` `subject` VARCHAR(想要的数字) NOT NULL; <br />
ALTER TABLE `cdb_posts` CHANGE `subject` `subject` VARCHAR(想要的数字) NOT NULL;<br />
ALTER TABLE `cdb_pms` CHANGE `subject` `subject` VARCHAR(想要的数字) NOT NULL;<br />
第5步：更新缓存</div>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2857188.html</guid>
        <pubDate>Sun, 30 Mar 2008 07:03:09 GMT</pubDate>

      </item>

      <item>
        <title>下级子版块横排图片怎样才能显示？</title>
        <link>http://kenneth.ycool.com/post.2854293.html</link>
        <description><![CDATA[<div class="t_msgfont" id="postmessage_6893430">　梳排可以显示，但改成了横排．做了图片连接以后，不显示，请问怎么才能让他显示出来，急需<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%C7%F3%D6%FA">求助</span>．谢谢！<br />
<br />
<div class="t_msgfont" id="postmessage_6896121">templates\default\discuz.htm<br />
模板文件中修改：<br />
&lt;th width=&quot;$cat[forumcolwidth]&quot;{$forum[folder]}&gt;<br />
改为：<br />
&lt;th width=&quot;$cat[forumcolwidth]&quot;&gt;{$forum[icon]}</div>
</div>...
]]></description>
        <guid isPermaLink="true">http://kenneth.ycool.com/post.2854293.html</guid>
        <pubDate>Wed, 26 Mar 2008 15:03:20 GMT</pubDate>

      </item>
    </channel>
  </rss>
