﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Tommy的技术博客-文章分类-LINUX/UNIX</title><link>http://www.cppblog.com/tommyyan/category/1336.html</link><description>&lt;br&gt;C++/web技术/设计模式/LINUX/MYSQL/P2P交流/嵌入式系统&lt;br&gt;
个人相关：&lt;a href="http://3965743.qzone.qq.com/" id = "MyLinks1_HomeLink" class="listitem" &gt;http://3965743.qzone.qq.com/&lt;/a&gt;</description><language>zh-cn</language><lastBuildDate>Wed, 20 May 2009 03:52:30 GMT</lastBuildDate><pubDate>Wed, 20 May 2009 03:52:30 GMT</pubDate><ttl>60</ttl><item><title>Secure CRT 乱码 问题 解决</title><link>http://www.cppblog.com/tommyyan/articles/83355.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Tue, 19 May 2009 03:42:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/83355.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/83355.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/83355.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/83355.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/83355.html</trackback:ping><description><![CDATA[<span id=ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry>
<div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div>在中文windows上，使用securecrt ssh FC, ubuntu等 2.6 kenerl 的linux，编译和man的时候，经常会出现乱码。这个问题困扰了我好久。<br><br>昨天晚上才发现，2.6 kernel的ssh默认编码是UTF 8，将securecrt的编码也改成UTF 8，嗯，问题解决了。<br><br>修改方法：<br><br>Options -&gt; Session Options -&gt;&nbsp; Apperance -&gt; Fonts -&gt; Character。写下来发现，SecureCRT的配置真是折腾人阿。</div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div>++++++++++++++++++++++++++++++++</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>一直以来，我的secureCRT设置都还算好看，字体大小合适，颜色都有。
<div>用起来也挺分别顺手，就是有一个很致命的毛病：</div>
<div>文字copy总是会出现乱码。</div>
<div>&nbsp;</div>
<div>比如：声声醉如兰 五个字符，copy出来粘贴到记事本上，就成了&#8220;&#201;&#249;&#201;&#249;&#215;&#237;&#200;&#231;&#192;&#188;&#8221;。</div>
<div>从SecureCRT复制到SecureCRT也是乱码。</div>
<div>&nbsp;</div>
<div>同事那就没有这个问题，用得好好得。</div>
<div>可能是我们的设置不大一样。</div>
<div>对比了一下区别，有这样几个地方：</div>
<div>&nbsp;</div>
<div>1，Emulation</div>
<div>&nbsp;&nbsp; Terminal 选择的是Linux，并且选中&#8220;ANSI Color&#8221;</div>
<div>&nbsp;</div>
<div>2，Appearance</div>
<div>&nbsp;&nbsp; Font 选择的是vt100 12pt</div>
<div>&nbsp;&nbsp;&nbsp;没有选中&#8220;Use Unicode line drawing characters&#8221;</div>
<div>&nbsp;&nbsp; </div>
<div>在Character 选择的Default，不知道和这有没有关系。</div>
<div>&nbsp;</div>
<div>另外，在linux系统中，LANG环境变量设置的是：zh_CN.gb2312，他们是：en_US</div>
<div>&nbsp;</div>
<div>于是，我就把这几个因素综合起来考虑，改来改去。</div>
<div>也算运气好，在别人提示下，总算找到了一个正确的设置。</div>
<div>再仔细的分析下去，发现问题出在了字体上面。</div>
<div>我原来用的是vt100 12pt，SecureCRT默认安装设置的这个字体。</div>
<div>&nbsp;</div>
<div>尝试了几个常用字体，发现有的会程序乱码，有的不会出现。</div>
<div>不会有乱码的是：<font size=2><strong>fixedsys，新宋体，宋体</strong></font></div>
<div>会出现乱码的是：vt100，courier，courier new</div>
<div>&nbsp;</div>
<div>乱码的原因没有找到，猜测是编码的问题。</div>
<div>如果你也出现乱码，建议把字体换换。还成fixedsys吧。</div>
<div>&nbsp;</div>
<div>有个无聊的情况就是，在替换的时候，有可能还是乱码，但坚持换几次，</div>
<div>就会正常。绝对让人莫名其妙。</div>
<div>&nbsp;</div>
<div>结论：</div>
<div>最大的废话是：我也没有找到具体原因是什么。</div>
<div>不过呢，可能性最大的是字体。因为用fixedsys字体不会有乱码问题，而用vt100就可能会有哦。</div>
<div>&nbsp;</div>
<div>characer的编码设置是否有关系，暂时不大清楚。设置成default应该没有问题。</div>
<div>&nbsp;</div>
<div>和服务器端的环境变量应该也没有什么关系。</div>
<div>比如：LANG为 zh_CN.gb2312 或者 en_US.UTF-8，都可以的。</div>
<div>&nbsp;</div>
<div>和vim的编码设置应该也没有关系。</div>
<div>&nbsp;</div>
<div>和终端设置也没有关系，选择linux或者vt100或者xterm都不会出现乱码。</div>
<div>&nbsp;</div>
<div>----------------------------</div>
<div>&nbsp;</div>
<div>现在说说secureCRT的设置</div>
<div>&nbsp;</div>
<div>字体：</div>
<div>建议用fixedsys，这个字体虽然不是最美丽的,但在终端上也是一个不错选择，大家都可以接受。</div>
<div>选择它，主要是因为它大小固定，在所有地方显示，效果都一样。</div>
<div>大家都知道，如果有人把tab设置成4个空格，有人设置成8个，那么同样一个程序，本来很美观的一个程序，到别人电脑上就不美观了。</div>
<div>同样，如果字体大小设置得不一致，也会出现这种问题。</div>
<div>所以，我一般都建议大家把字体设置成统一的fixedsys。</div>
<div>&nbsp;</div>
<div>Linux终端是有颜色的。</div>
<div>vim也是可以打开颜色的。</div>
<div>为什么很多人都不喜欢把两者的颜色打开呢。</div>
<div>&nbsp;</div>
<div>secureCRT设置：</div>
<div>&nbsp; Terminal -&gt;Emulation -&gt;ANSI Color 选中就可以了。</div>
</div>
</span>
<img src ="http://www.cppblog.com/tommyyan/aggbug/83355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2009-05-19 11:42 <a href="http://www.cppblog.com/tommyyan/articles/83355.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微软提供的NFS Server软件</title><link>http://www.cppblog.com/tommyyan/articles/82947.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Thu, 14 May 2009 06:14:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/82947.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/82947.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/82947.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/82947.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/82947.html</trackback:ping><description><![CDATA[最近需要在Windows系统导出NFS，供一块开发板开发Linux应用程序。在cygwin中有nfs-server软件包（参考：<a href="http://linuxman.blog.ccidnet.com/blog-htm-do-showone-uid-60710-type-blog-itemid-265432.html" target=_blank><u><font color=#0000ff>Windows上的NFS Server 软件</font></u></a>），但在我公司的电脑上，软件包安装的portmap服务无法启动，因而无法使用。因工作环境限制，必须找到windows版本的NFS Server软件，否则后续的工作就要停止。<br>网上google了两天，发现微软提供的Services for UNIX（SFU）软件包里包含NFS Server，可以满足我的要求。目前SFU的版本是3.5，于2004年1月发布，可免费使用。SFU软件包还包含其他的UNIX功能组件、Unix shell环境和SDK，但版本太老，不推荐使用。<br><br><strong>1、安装</strong><br>SFU软件包的下载地址是: "http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=896c9688-601b-44f1-81a4-02878ff11778"<br>下载的软件包程序是自解压程序，运行后解压到某个目录内，然后运行其中的setup.exe程序安装软件包。安装时选择custom模式，只选择安装NFS Server，和相应的认证模块（安装程序会提示安装此认证模块），其他步骤按缺省设置安装即可。安装完毕后需要重启机器。<br><br><strong>2、配置</strong><br>（1）准备UNIX的用户、组的描述文件passwd和group<br>passwd:<br><font color=#0000ff>root:x:0:0:root:/root:/bin/sh</font><br><br>group：<br><font color=#0000ff>root:x:0</font><br><br>上面的是最简单的内容，可以根据实际情况添加其他用户、组。<br><br>（2）将UNIX的用户映射到Windows用户<br>在 &#8220;开始&#8221;菜单启动windows for UNIX--&gt;Services for Unix Administration，然后在程序界面上点击左面的User Name Mapping项，进行配置：在configuration标签下，选择Use password and Group files，填入上步骤准备的passwd和group文件的文件路径；在Maps标签下，将UNIX用户映射到合适的Windows用户。配置完成后，点程序界面右上角的Apply按钮，使配置生效。<br><br><strong>3、将Windows的目录按NFS导出</strong><br>在Windows系统中选择要导出的目录，点鼠标右键，在弹出菜单中选择&#8220;属性&#8221;菜单项。然后在属性配置对话框内，点NFS Sharing 标签，选它下面的share this folder。点&#8220;确定&#8221;按钮后，该目录就能按NFS导出了，目录的图标也有了变化。<br><br><strong>4、客户端安装NFS共享目录</strong><br>客户端用mount命令来安装NFS共享目录。我的客户端是一块Linux的开发板，安装时还需要在mount命令中添加 -o nolock 选项，否则无法正确安装NFS共享目录。<br><br><strong>5、对客户端的读写权限控制</strong><br>可以通过Client Groups对客户端的读写权限进行控制。在Services for Unix Administration程序中，点击左面的Server for NFS项，选择Client Groups标签，添加客户端组和所包含的客户端的IP地址。配置完成后，点程序界面右上角的Apply按钮，使配置生效。<br>在要导出的NFS目录设置对话框中，点NFS Sharing 标签右下角的Permissions按钮，把刚才设置的客户端组Add进来，并设置合适的读写权限。
<img src ="http://www.cppblog.com/tommyyan/aggbug/82947.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2009-05-14 14:14 <a href="http://www.cppblog.com/tommyyan/articles/82947.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>修改字符终端的字体颜色的一点经验</title><link>http://www.cppblog.com/tommyyan/articles/82859.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Wed, 13 May 2009 11:32:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/82859.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/82859.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/82859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/82859.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/82859.html</trackback:ping><description><![CDATA[可能大伙对修改终端背景都比较熟悉，不同的终端虚拟器都提供配置文件。不过对如何修改终端字体的颜色未必都很清楚，我总结了自己的一点经验。<br><br>目的：美化终端，保护视力。<br><br>步骤：<br>1、让终端显示彩色字体<br>默认安装好 Debian 系统后,大家会发现用 ls 命令不带参数，不会显示彩色。<br>可加一个 --color 参数来显示彩色。<br>$ ls --color<br><br>2、修改 .bashrc 文件<br>每次都带参数未免有些麻烦，最好的方法是把它写到默认配置文件 .bashrc 里,位于用户目录。<br>$ vi ~/.bashrc<br><br>代码:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;# enable color support of ls and also add handy aliases<br>&nbsp;&nbsp;&nbsp;&nbsp;if [ "$TERM" != "dumb" ]; then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eval `dircolors -b`<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias ls='ls --color=auto'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias dir='ls --color=auto --format=vertical'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias vdir='ls --color=auto --format=long'<br>&nbsp;&nbsp;&nbsp;&nbsp;fi <br><br><br>去掉默认的注释后，保存退出，重新打开一个终端，运行 ls 命令就可以看到彩色效果了。<br><br>3、建立自己的 .coloursrc 文件<br>因为每个人的风格不同，对颜色的喜欢也不同，默认的色彩配置文件不能满足需要，让我们来自定义颜色。<br><br>$ dir -p<br>你会看到默认的色彩配置信息。让我们把它保存到文件 .coloursrc 里，名字可以自己取,放到当前用户目录下。<br>$ dir -p &gt; ~/.coloursrc<br>$ vi ~/.coloursrc<br><br>发挥你的想象力，改成适合自己口味的。如我的目录字体颜色默认为蓝色和黑色的背景很不相称，根本看不清显示的文字。<br>搜索 DIR ,找到 DIR 01;34 ,这里 34=blue, 你可以在上面的注释里得到色彩信息，我将它改成 DIR 01;46 ,46=cyan , 因为 46 号并没有使用，所以不会冲突，存盘。<br><br>4、现在我们让自定义色彩生效<br>$ vi ~/.bashrc<br>将 eval `dircolors -b` 改成 eval `dircolors $HOME/.coloursrc<br>存盘。重新打开一个终端，就能看到效果。<br><br>5、查看可供使用的色彩<br>大家会想到，由于我们不能直观的看到将要使用的颜色，也不清楚我们的终端到底支持哪些颜色，有没有好方法呢？<br><br>使用下面这个非常酷的 bash 脚本来给我们直观的显示色彩信息：<br>$ cat display_ANSI_colors<br><br>代码:<br>#!/bin/bash<br># Display ANSI colours.<br>#tiff 01;35<br>esc="\033["<br>echo -n " _ _ _ _ _40 _ _ _ 41_ _ _ _42 _ _ _ 43"<br>echo "_ _ _ 44_ _ _ _45 _ _ _ 46_ _ _ _47 _"<br>for fore in 30 31 32 33 34 35 36 37; do<br>&nbsp;&nbsp;&nbsp;&nbsp;line1="$fore&nbsp;&nbsp;"<br>&nbsp;&nbsp;&nbsp;&nbsp;line2="&nbsp;&nbsp;&nbsp;&nbsp;"<br>&nbsp;&nbsp;&nbsp;&nbsp;for back in 40 41 42 43 44 45 46 47; do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line1="${line1}${esc}${back};${fore}m Normal&nbsp;&nbsp;${esc}0m"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line2="${line2}${esc}${back};${fore};1m Bold&nbsp;&nbsp;&nbsp;&nbsp;${esc}0m"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo -e "$line1\n$line2"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done <br><br><br>拷贝、复制，保存成文件 display_ANSI_colors,并修改属性，让它可执行：<br>$ chmod +x display_ANSI_colors<br><br>$ ./display_ANSI_colors<br>就可以看到终端输出的彩色图片了。
<img src ="http://www.cppblog.com/tommyyan/aggbug/82859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2009-05-13 19:32 <a href="http://www.cppblog.com/tommyyan/articles/82859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下C程序内存泄露检测</title><link>http://www.cppblog.com/tommyyan/articles/82434.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Sat, 09 May 2009 15:19:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/82434.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/82434.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/82434.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/82434.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/82434.html</trackback:ping><description><![CDATA[<font color=#02368d><font color=#000000>在linux下些C语言程序，最大的问题就是没有一个好的编程IDE，当然想kdevelop等工具都相当的强大，但我还是习惯使用kdevelop工具，由于没有一个习惯的编程IDE，内存检测也就成了在linux下编写程序的一个大问题。<br>是不是说没有一种内存检查工具能够在linux使用呢，也不是，像valgrind工具还是相当不错的。他的下载地址是</font><a href="http://valgrind.org/downloads/current.html#current" target=_blank><u><font color=#0000ff>http://valgrind.org/downloads/current.html#current</font></u></a><font color=#000000> 下载一个</font><a href="http://valgrind.org/downloads/valgrind-3.2.3.tar.bz2"><u><font color=#0000ff>valgrind 3.2.3 (tar.bz2)</font></u></a></font><font color=#000000> 工具，按照里面的README提示，安装后就可以使用这个工具来检测内存泄露和内存越界等。这是一个没有界面的内存检测工具，安装后，输入 valgrind ls -l 验证一下该工具是否工作正常（这是README里面的方法，实际上是验证一下对ls -l命令的内存检测），如果你看到一堆的信息说明你的工具可以使用了。<br><br>在编译你的程序时，请设置-g参数，编译出后使用如下的命令来判断你的程序存在内存泄露：<br>valgrind --leak-check=yes yourProg在输出信息中就会看到你的内存问题了。关于这些参数是什么意思可以参考valgrind --help 的输出信息。 </font>
<img src ="http://www.cppblog.com/tommyyan/aggbug/82434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2009-05-09 23:19 <a href="http://www.cppblog.com/tommyyan/articles/82434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 32位向64位的移植常见问题</title><link>http://www.cppblog.com/tommyyan/articles/30393.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Sun, 19 Aug 2007 16:25:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/30393.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/30393.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/30393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/30393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/30393.html</trackback:ping><description><![CDATA[<p><span></span></p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>数据截断：</span></p>
<p><span>由于</span><span>long</span><span>类型变量的运算（赋值、比较、移位等）产生。</span><span>long</span><span>定义在</span><span>x86</span><span>上为</span><span>32bits,</span><span>而在</span><span>ia64</span><span>上为</span><span>64bits.</span><span>容易在与</span><span>int</span><span>型变量运算时出现异常。</span></p>
<p><span>处理方法：尽量避免不同类型变量间的运算</span><span>,</span><span>避免将长度较长的变量赋值到较短的变量中，统一变量长度可以解决这个问题。简单的对于</span><span>32</span><span>位转移到</span><span>64</span><span>位可以将所有</span><span>long</span><span>定义转换为</span><span>int</span><span>定义。</span></p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>指针存储：</span></p>
<p><span>在</span><span>x86</span><span>平台下，习惯使用</span><span>int</span><span>来存储指针，并将指针直接参与到</span><span>int</span><span>型的运算中，而</span><span>64</span><span>位平台下指针大小为</span><span>64bits,</span><span>无法存储到</span><span>int</span><span>中。</span><span>对指针的运算也可能会因为数据长度的不一致导致异常。</span></p>
<p><span>处理方法：修改用于存储传递指针的变量为</span><span>intptr_t </span><span>类型定义，以保证平台兼容性</span></p>
<p><span><span>3.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>不规范的结构：</span></p>
<p><span>未命名或为指定数量的成员可能会出现异常</span></p>
<p><span>处理方法：命名未命名的成员，声明类型符号，将</span><span>long</span><span>型定义转为</span><span>int</span><span>型。</span></p>
<p><span><span>4.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>代码中的直接数</span></p>
<p><span>直接使用</span><span>16</span><span>进制数字进行赋值时（一般会隐含假设该变量为</span><span>32</span><span>位变量的前提）</span><span> </span><span>可能出现异常。使用数字定义数据大小，进行移位运算时会出现异常。</span></p>
<p><span>处理方法：检查代码中的直接数字是否有表示</span><span>32</span><span>位有关的各种形式，如</span><span>4,32,</span><span> 0x7fffffff</span><span>等，替换为宏定义。</span></p>
<p>&nbsp;</p>
<p><span>编写代码时注意可移植化：</span></p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>在<span>32</span>位与<span>64</span>位下使用同样的头文件</span></p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>使用严禁的格式定义，如：用<span>off_t</span>定义偏移量，用<span>fpos_t</span>定义文件位置<span>, intptr_t</span>定义指针</span></p>
<p><span><span>3.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>使用<span>&lt;intypes.h&gt;</span>中定义的整数类型，不使用<span>int,long,long long</span>的传统定义方式。使用带有整形标示符参数的<span>printf</span>函数，不使用<span>%d,%ld</span>的格式化方式。</span></p>
<p><span><span>4.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>使用固定宽度或宏定义的整数类型，数字，掩码</span></p>
<p><span><span>5.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>对整形变量作边界检查。</span></p>
<p><span><span>6.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>32</span><span>位与</span><span>64</span><span>位进程共享内存操作时，使用</span><span>64</span><span>位作为操作字长。</span></p>
<img src ="http://www.cppblog.com/tommyyan/aggbug/30393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2007-08-20 00:25 <a href="http://www.cppblog.com/tommyyan/articles/30393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>32位Linux单进程有4G内存限制</title><link>http://www.cppblog.com/tommyyan/articles/30387.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Sun, 19 Aug 2007 14:56:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/30387.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/30387.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/30387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/30387.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/30387.html</trackback:ping><description><![CDATA[可用下面代码测试系统能给单进程分配多少用户态内存： <br><br>1 #include <stdio.h><br>2 #include <stdlib.h><br>3 <br>4 int main(){ <br>5 int MB = 0; <br>6 while(malloc(1 &lt;&lt; 20)) ++MB; <br>7 printf("Allocated %d MB total.n", MB); <br>8 } <br><br>　　这段代码在32位系统上执行，返回3066M;在64位系统上执行，系统最后会变得负载很高，然后内核就把进程kill了。这说明32位系统上单进程是有内存分配限制的，而64位则没有。 <br><br>　　编译32位linux内核时，打开linux内核的PAE寻址支持，最大支持的内存可以从32位提高到36位（4G-&gt;64G），而单进程能分配的内存却仍然有4G限制。即：对于每个进程，用户态最多分配3G内存，核心态最多分配1G内存。 <br><br>　　那么能不能通过调整内核参数的办法动态调整，使得32位linux内核支持单进程分配大于4G内存呢？这是个有现实意义的问题。Squid,Mysql,Java等都是单进程应用。而现在的主流服务器，很多都可以可以配置非常高的内存。例如Dell 6850,HP580都能插16G内存，我见过的一款Sun的服务器甚至支持48G内存。这些大内存机器如果跑单进程应用，那么内存就全浪费了。 <br><br>　　我查了一些资料，结论是，32位BSD可以动态调整内核参数以支持单进程分配大内存， <br><br>　　32位linux系统是无法解决单进程4G内存限制的。 <br><br>　　下面是摘自High Memory in the Linux Kernel里面的一段话： <br><br>　　This is enabled via the PAE (Physical Address Extension) extension of the PentiumPro processors. PAE addresses the 4 GB physical memory limitation and is seen as Intel's answer to AMD 64-bit and AMD x86-64. PAE allows processors to access physical memory up to 64 GB (36 bits of address bus). However, since the virtual address space is just 32 bits wide, each process can't grow beyond 4 GB.
<img src ="http://www.cppblog.com/tommyyan/aggbug/30387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2007-08-19 22:56 <a href="http://www.cppblog.com/tommyyan/articles/30387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将 Linux 应用程序移植到 64 位系统上</title><link>http://www.cppblog.com/tommyyan/articles/30386.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Sun, 19 Aug 2007 14:54:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/30386.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/30386.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/30386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/30386.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/30386.html</trackback:ping><description><![CDATA[<p id=subtitle><em>平滑迁移的技巧和技术</em></p>
<table cellSpacing=0 cellPadding=0 width="97%" border=0>
    <tbody>
        <tr vAlign=top>
            <td width="100%">
            <p>级别: 初级</p>
            <p><a href="http://www.ibm.com/developerworks/cn/linux/l-port64.html#author"><font color=#606420><u>Harsha S. Adiga</u></font></a> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#104;&#97;&#114;&#97;&#100;&#105;&#103;&#97;&#64;&#105;&#110;&#46;&#105;&#98;&#109;&#46;&#99;&#111;&#109;&#63;&#115;&#117;&#98;&#106;&#101;&#99;&#116;&#61;&#23558;&#32;&#76;&#105;&#110;&#117;&#120;&#32;&#24212;&#29992;&#31243;&#24207;&#31227;&#26893;&#21040;&#32;&#54;&#52;&#32;&#20301;&#31995;&#32479;&#19978;"><font color=#0000ff><u>haradiga@in.ibm.com</u></font></a>), 软件工程师, IBM<br></p>
            <p>2006 年 5 月 18 日</p>
            <blockquote>随着 64 位体系结构的普及，针对 64 位系统准备好您的 Linux&#174; 软件已经变得比以前更为重要。在本文中，您将学习如何在进行语句声明、赋值、位移、类型转换、字符串格式化以及更多操作时，防止出现可移植性缺陷。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p>Linux 是可以使用 64 位处理器的跨平台操作系统之一，现在 64 位的系统在服务器和桌面端都已经非常常见了。很多开发人员现在都面临着需要将自己的应用程序从 32 位环境移植到 64 位环境中。随着 Intel&#174; Itanium&#174; 和其他 64 位处理器的引入，使软件针对 64 位环境做好准备变得日益重要了。 </p>
            <p>与 UNIX&#174; 和其他类 UNIX 操作系统一样，Linux 使用了 LP64 标准，其中指针和长整数都是 64 位的，而普通的整数则依然是 32 位的。尽管有些高级语言并不会受到这种类型大小不同的影响，但是另外一些语言（例如 C 语言）却的确会受到这种影响。 </p>
            <p>将应用程序从 32 位系统移植到 64 位系统上的工作可能会非常简单，也可能会非常困难，这取决于这些应用程序是如何编写和维护的。很多琐碎的问题都可能导致产生问题，即使在一个编写得非常好的高度可移植的应用程序中也是如此，因此本文将对这些问题进行归纳总结，并给出解决这些问题的一些方法建议。 </p>
            <p><a name=N10058><span class=atitle>64 位的优点</span></a></p>
            <p>32 位平台有很多限制，这些限制正在阻碍大型应用程序（例如数据库）开发人员的工作进展，尤其对那些希望充分利用计算机硬件优点的开发人员来说更是如此。科学计算通常要依赖于浮点计算，而有些应用程序（例如金融计算）则需要一个比较狭窄的数字范围，但是却要求更高的精度，其精度高于浮点数所提供的精度。64 位数学运算提供了这种更高精度的定点数学计算，同时还提供了足够的数字范围。现在在计算机业界中有很多关于 32 位地址空间所表示的地址空间的讨论。32 位指针只能寻址 4GB 的虚拟地址空间。我们可以克服这种限制，但是应用程序开发就变得非常复杂了，其性能也会显著降低。 </p>
            <p>在语言实现方面，目前的 C 语言标准要求 &#8220;long long&#8221; 数据类型至少是 64 位的。然而，其实现可能会将其定义为更大。 </p>
            <p>另外一个需要改进的地方是日期。在 Linux 中，日期是使用 32 位整数来表示的，该值所表示的是从 1970 年 1 月 1 日至今所经过的秒数。这在 2038 年就会失效。但是在 64 位的系统中，日期是使用有符号的 64 位整数表示的，这可以极大地扩充其可用范围。 </p>
            <p>总之，64 位具有以下优点：
            <ul>
                <li>64 位的应用程序可以直接访问 4EB 的虚拟内存，Intel Itanium 处理器提供了连续的线性地址空间。
                <li>64 位的 Linux 允许文件大小最大达到 4 EB（2 的 63 次幂），其重要的优点之一就是可以处理对大型数据库的访问。 </li>
            </ul>
            <p>&#160;</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-port64.html#main"><strong><font color=#606420><u>回页首</u></font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10073><span class=atitle>Linux 64 位体系结构</span></a></p>
            <p>不幸的是，C 编程语言并没有提供一种机制来添加新的基本数据类型。因此，提供 64 位的寻址和整数运算能力必须要修改现有数据类型的绑定或映射，或者向 C 语言中添加新的数据类型。 </p>
            <br><br><a name=table1><strong>表 1. 32 位和 64 位数据模型</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="32-bit and 64-bit data models" border=0>
                <tbody>
                    <tr>
                        <th>&nbsp;</th>
                        <th>ILP32</th>
                        <th>LP64</th>
                        <th>LLP64</th>
                        <th>ILP64</th>
                    </tr>
                    <tr>
                        <td class=tb-row>char</td>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                    </tr>
                    <tr>
                        <td class=tb-row>short</td>
                        <td>16</td>
                        <td>16</td>
                        <td>16</td>
                        <td>16</td>
                    </tr>
                    <tr>
                        <td class=tb-row>int</td>
                        <td>32</td>
                        <td>32</td>
                        <td>32</td>
                        <td>64</td>
                    </tr>
                    <tr>
                        <td class=tb-row>long</td>
                        <td>32</td>
                        <td>64</td>
                        <td>32</td>
                        <td>64</td>
                    </tr>
                    <tr>
                        <td class=tb-row>long long</td>
                        <td>64</td>
                        <td>64</td>
                        <td>64</td>
                        <td>64</td>
                    </tr>
                    <tr>
                        <td class=tb-row>指针</td>
                        <td>32</td>
                        <td>64</td>
                        <td>64</td>
                        <td>64</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>这 3 个 64 位模型（LP64、LLP64 和 ILP64）之间的区别在于非浮点数据类型。当一个或多个 C 数据类型的宽度从一种模型变换成另外一种模型时，应用程序可能会受到很多方面的影响。这些影响主要可以分为两类：
            <ul>
                <li><strong>数据对象的大小</strong>。编译器按照自然边界对数据类型进行对齐；换而言之，32 位的数据类型在 64 位系统上要按照 32 位边界进行对齐，而 64 位的数据类型在 64 位系统上则要按照 64 位边界进行对齐。这意味着诸如结构或联合之类的数据对象的大小在 32 位和 64 位系统上是不同的。<br><br>
                <li><strong>基本数据类型的大小</strong>。通常关于基本数据类型之间关系的假设在 64 位数据模型上都已经无效了。依赖于这些关系的应用程序在 64 位平台上编译也会失败。例如，<code><font face=新宋体>sizeof (int) = sizeof (long) = sizeof (pointer)</font></code> 的假设对于 ILP32 数据模型有效，但是对于其他数据模型就无效了。 </li>
            </ul>
            <p>&#160;</p>
            <p>总之，编译器要按照自然边界对数据类型进行对齐，这意味着编译器会进行 &#8220;填充&#8221;，从而强制进行这种方式的对齐，就像是在 C 结构和联合中所做的一样。结构或联合的成员是根据最宽的成员进行对齐的。清单 1 对这个结构进行了解释。 </p>
            <br><br><a name=listing1><strong>清单 1. C 结构 </strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>struct test {
                        int i1;
                        double d;
                        int i2;
                        long l;
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>表 2 给出了这个结构中每个成员的大小，以及这个结构在 32 位系统和 64 位系统上的大小。 </p>
            <br><br><a name=table2><strong>表 2. 结构和结构成员的大小</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="Size of structure and structure members" border=0>
                <tbody>
                    <tr>
                        <th>结构成员</th>
                        <th>在 32 位系统上的大小</th>
                        <th>在 64 位系统上的大小</th>
                    </tr>
                    <tr>
                        <td class=tb-row>struct test {</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                    </tr>
                    <tr>
                        <td class=tb-row>int i1;</td>
                        <td>32 位</td>
                        <td>32 位</td>
                    </tr>
                    <tr>
                        <td class=tb-row>
                        <td>&nbsp;</td>
                        <td>32 位填充</td>
                    </tr>
                    <tr>
                        <td class=tb-row>double d;</td>
                        <td>64 位</td>
                        <td>64 位</td>
                    </tr>
                    <tr>
                        <td class=tb-row>int i2;</td>
                        <td>32 位</td>
                        <td>32 位</td>
                    </tr>
                    <tr>
                        <td class=tb-row>
                        <td>&nbsp;</td>
                        <td>32 位填充</td>
                    </tr>
                    <tr>
                        <td class=tb-row>long l;</td>
                        <td>32 位</td>
                        <td>64 位</td>
                    </tr>
                    <tr>
                        <td class=tb-row>};</td>
                        <td>结构大小为 20 字节</td>
                        <td>结构大小为 32 字节</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>注意，在一个 32 位的系统上，编译器可能并没有对变量 <code><font face=新宋体>d</font></code> 进行对齐，尽管它是一个 64 位的对象，这是因为硬件会将其当作两个 32 位的对象进行处理。然而，64 位的系统会对 <code><font face=新宋体>d</font></code> 和 <code><font face=新宋体>l</font></code> 都进行对齐，这样会添加两个 4 字节的填充。 </p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-port64.html#main"><strong><font color=#606420><u>回页首</u></font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N101CB><span class=atitle>从 32 位系统移植到 64 位系统</span></a></p>
            <p>本节介绍如何解决一些常见的问题：
            <ul>
                <li>声明
                <li>表达式
                <li>赋值
                <li>数字常数
                <li>Endianism
                <li>类型定义
                <li>位移
                <li>字符串格式化
                <li>函数参数 </li>
            </ul>
            <p>&#160;</p>
            <p><a name=sidebars><span class=smalltitle>声明</span></a></p>
            <p>要想让您的代码在 32 位和 64 位系统上都可以工作，请注意以下有关声明的用法：
            <ul>
                <li>根据需要适当地使用 &#8220;L&#8221; 或 &#8220;U&#8221; 来声明整型常量。
                <li>确保使用无符号整数来防止符号扩展的问题。
                <li>如果有些变量在这两个平台上都需要是 32 位的，请将其类型定义为 int。
                <li>如果有些变量在 32 位系统上是 32 位的，在 64 位系统上是 64 位的，请将其类型定义为 long。
                <li>为了对齐和性能的需要，请将数字变量声明为 int 或 long 类型。不要试图使用 char 或 short 类型来保存字节。
                <li>将字符指针和字符字节声明为无符号类型的，这样可以防止 8 位字符的符号扩展问题。 </li>
            </ul>
            <p>&#160;</p>
            <p><a name=sidebars><span class=smalltitle>表达式</span></a></p>
            <p>在 C/C++ 中，表达式是基于结合律、操作符的优先级和一组数学计算规则的。要想让表达式在 32 位和 64 位系统上都可以正确工作，请注意以下规则：
            <ul>
                <li>两个有符号整数相加的结果是一个有符号整数。
                <li>int 和 long 类型的两个数相加，结果是一个 long 类型的数。
                <li>如果一个操作数是无符号整数，另外一个操作数是有符号整数，那么表达式的结果就是无符号整数。
                <li>int 和 doubule 类型的两个数相加，结果是一个 double 类型的数。此处 int 类型的数在执行加法运算之前转换成 double 类型。 </li>
            </ul>
            <p>&#160;</p>
            <p><a name=sidebars><span class=smalltitle>赋值</span></a></p>
            <p>由于指针、int 和 long 在 64 位系统上大小不再相同了，因此根据这些变量是如何赋值和在应用程序中使用的，可能会出现问题。下面是有关赋值的一些技巧：</p>
            <ul>
                <li>不要交换使用 int 和 long 类型，因为这可能会导致高位数字被截断。例如，不要做下面的事情：
                <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                    <tbody>
                        <tr>
                            <td class=code-outline>
                            <pre class=displaycode>int i;
                            long l;
                            i = l;</pre>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <br>
                <li>不要使用 int 类型来存储指针。下面这个例子在 32 位系统上可以很好地工作，但是在 64 位系统上会失败，这是因为 32 位整数无法存放 64 位的指针。例如，不要做下面的事情：
                <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                    <tbody>
                        <tr>
                            <td class=code-outline>
                            <pre class=displaycode>unsigned int i, *ptr;
                            i = (unsigned) ptr;</pre>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <br>
                <li>不要使用指针来存放 int 类型的值。例如，不要做下面的事情；
                <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                    <tbody>
                        <tr>
                            <td class=code-outline>
                            <pre class=displaycode>int *ptr;
                            int i;
                            ptr = (int *) i;
                            </pre>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <br>
                <li>如果在表达式中混合使用无符号和有符号的 32 位整数，并将其赋值给一个有符号的 long 类型，那么将其中一个操作数转换成 64 位的类型。这会导致其他操作数也被转换成 64 位的类型，这样在对表达式进行赋值时就不需要再进行转换了。另外一种解决方案是对整个表达式进行转换，这样就可以在赋值时进行符号扩展。例如，考虑下面这种用法可能会出现的问题：
                <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                    <tbody>
                        <tr>
                            <td class=code-outline>
                            <pre class=displaycode>long n;
                            int i = -2;
                            unsigned k = 1;
                            <span class=boldcode>n = i + k;</span>
                            </pre>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <br>
                <p>从数学计算上来说，上面这个黑体显示的表达式的结果应该是 -1 。但是由于表达式是无符号的，因此不会进行符号扩展。解决方案是将一个操作数转换成 64 位类型（下面的第一行就是这样），或者对整个表达式进行转换（下面第二行）：
                <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                    <tbody>
                        <tr>
                            <td class=code-outline>
                            <pre class=displaycode>n = (long) i + k;
                            n = (int) (i + k);
                            </pre>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <br></p>
                </li>
            </ul>
            <p><a name=sidebars><span class=smalltitle>数字常量</span></a></p>
            <p>16 进制的常量通常都用作掩码或特殊位的值。如果一个没有后缀的 16 进制的常量是 32 位的，并且其高位被置位了，那么它就可以作为无符号整型进行定义。 </p>
            <p>例如，常数 OxFFFFFFFFL 是一个有符号的 long 类型。在 32 位系统上，这会将所有位都置位（每位全为 1），但是在 64 位系统上，只有低 32 位被置位了，结果是这个值是 0x00000000FFFFFFFF。 </p>
            <p>如果我们希望所有位全部置位，那么一种可移植的方法是定义一个有符号的常数，其值为 -1。这会将所有位全部置位，因为它采用了二进制补码算法。
            <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>long x = -1L;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br></p>
            <p>可能产生的另外一个问题是最高位的设置。在 32 位系统上，我们使用的是常量 0x80000000。但是可移植性更好的方法是使用一个位移表达式：
            <table cellSpacing=0 cellPadding=0 width="50%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>1L &lt;&lt; ((sizeof(long) * 8) - 1);
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br></p>
            <p><a name=sidebars><span class=smalltitle>Endianism</span></a></p>
            <p>Endianism 是指用来存储数据的方法，它定义了整数和浮点数据类型中是如何对字节进行寻址的。 </p>
            <p>Little-endian 是将低位字节存储在内存的低地址中，将高位字节存储在内存的高地址中。 </p>
            <p>Big-endian 是将高位字节存储在内存的低地址中，将低位字节存储在内存的高地址中。 </p>
            <p>表 3 给出了一个 64 位长整数的布局示例。 </p>
            <br><br><a name=table3><strong>表 3. 64 位 long int 类型的布局</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="Layout of a 64-bit long int" border=0>
                <tbody>
                    <tr>
                        <th>&nbsp;</th>
                        <th>低地址</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>
                        <th>&nbsp;</th>
                        <th>高地址</th>
                    </tr>
                    <tr>
                        <td class=tb-row>Little endian</td>
                        <td>Byte 0</td>
                        <td>Byte 1</td>
                        <td>Byte 2</td>
                        <td>Byte 3</td>
                        <td>Byte 4</td>
                        <td>Byte 5</td>
                        <td>Byte 6</td>
                        <td>Byte 7</td>
                    </tr>
                    <tr>
                        <td class=tb-row>Big endian</td>
                        <td>Byte 7</td>
                        <td>Byte 6</td>
                        <td>Byte 5</td>
                        <td>Byte 4</td>
                        <td>Byte 3</td>
                        <td>Byte 2</td>
                        <td>Byte 1</td>
                        <td>Byte 0</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>例如，32 位的字 0x12345678 在 big endian 机器上的布局如下： </p>
            <br><br><a name=table4><strong>表 4. 0x12345678 在 big-endian 系统上的布局</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="0x12345678 on a big-endian system" border=0>
                <tbody>
                    <tr>
                        <td class=tb-row>内存偏移量</td>
                        <td>0</td>
                        <td>1</td>
                        <td>2</td>
                        <td>3</td>
                    </tr>
                    <tr>
                        <td class=tb-row>内存内容</td>
                        <td>0x12</td>
                        <td>0x34</td>
                        <td>0x56</td>
                        <td>0x78</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>如果将 0x12345678 当作两个半字来看待，分别是 0x1234 和 0x5678，那么就会看到在 big endian 机器上是下面的情况： </p>
            <br><br><a name=table5><strong>表 5. 0x12345678 在 big-endian 系统上当作两个半字来看待的情况</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="" border=0>
                <tbody>
                    <tr>
                        <td class=tb-row>内存偏移量</td>
                        <td>0</td>
                        <td>2</td>
                    </tr>
                    <tr>
                        <td class=tb-row>内存内容</td>
                        <td>0x1234</td>
                        <td>0x5678</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>然而，在 little endian 机器上，字 0x12345678 的布局如下所示： </p>
            <br><br><a name=table6><strong>表 6. 0x12345678 在 little-endian 系统上的布局</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="0x12345678 on a little-endian system" border=0>
                <tbody>
                    <tr>
                        <td class=tb-row>内存偏移量</td>
                        <td>0</td>
                        <td>1</td>
                        <td>2</td>
                        <td>3</td>
                    </tr>
                    <tr>
                        <td class=tb-row>内存内容</td>
                        <td>0x78</td>
                        <td>0x56</td>
                        <td>0x34</td>
                        <td>0x12</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>类似地，两个半字 0x1234 和 0x5678 如下所示： </p>
            <br><br><a name=table7><strong>表 7. 0x12345678 在 little-endian 系统上作为两个半字看到的情况</strong></a><br>
            <table class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" summary="0x12345678 as two half words on a little-endian system" border=0>
                <tbody>
                    <tr>
                        <td class=tb-row>内存偏移量</td>
                        <td>0</td>
                        <td>2</td>
                    </tr>
                    <tr>
                        <td class=tb-row>内存内容</td>
                        <td>0x3412</td>
                        <td>0x7856</td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>下面这个例子解释了 big endian 和 little endian 机器上字节顺序之间的区别。 </p>
            <p>下面的 C 程序在一台 big endian 机器上进行编译和运行时会打印 &#8220;Big endian&#8221;，在一台 little endian 机器上进行编译和运行时会打印 &#8220;Little endian&#8221;。 </p>
            <br><br><a name=listing1><strong>清单 2. big endian 与 little endian</strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>#include &lt;stdio.h&gt;
                        main () {
                        int i = 0x12345678;
                        if (*(char *)&amp;i == 0x12)
                        printf ("Big endian\n");
                        else if (*(char *)&amp;i == 0x78)
                        printf ("Little endian\n");
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>Endianism 在以下情况中非常重要：
            <ul>
                <li>使用位掩码时
                <li>对象的间接指针地址部分 </li>
            </ul>
            <p>&#160;</p>
            <p>在 C 和 C++ 中有位域来帮助处理 endian 的问题。我建议使用位域，而不要使用掩码域或 16 进制的常量。有几个函数可以用来将 16 位和 32 位数据从 &#8220;主机字节顺序&#8221; 转换成 &#8220;网络字节顺序&#8221;。例如，<code><font face=新宋体>htonl (3)</font></code>、<code><font face=新宋体>ntohl (3)</font></code> 用来转换 32 位整数。类似地，<code><font face=新宋体>htons (3)</font></code>、<code><font face=新宋体>ntohs (3)</font></code> 用来转换 16 位整数。然而，对于 64 位整数来说，并没有标准的函数集。但是在 big endian 和 little endian 系统上，Linux 都提供了下面的几个宏：
            <ul>
                <li>bswap_16
                <li>bswap_32
                <li>bswap_64 </li>
            </ul>
            <p>&#160;</p>
            <p><a name=sidebars><span class=smalltitle>类型定义</span></a></p>
            <p>建议您不要使用 C/C++ 中那些在 64 位系统上会改变大小的数据类型来编写应用程序，而是使用一些类型定义或宏来显式地说明变量中所包含的数据的大小和类型。有些定义可以使代码的可移植性更好。</p>
            <ul>
                <li><code><font face=新宋体>ptrdiff_t</font></code>： <br>这是一个有符号整型，是两个指针相减后的结果。<br><br>
                <li><code><font face=新宋体>size_t</font></code>： <br>这是一个无符号整型，是执行 <code><font face=新宋体>sizeof</font></code> 操作的结果。这在向一些函数（例如 <code><font face=新宋体>malloc (3)</font></code>）传递参数时使用，也可以从一些函数（比如 <code><font face=新宋体>fred (2)</font></code>）中返回。<br><br>
                <li><code><font face=新宋体>int32_t</font></code>、<code><font face=新宋体>uint32_t</font></code> 等： <br>定义具有预定义宽度的整型。<br><br>
                <li><code><font face=新宋体>intptr_t</font></code> 和 <code><font face=新宋体>uintptr_t</font></code>： <br>定义整型类型，任何有效指针都可以转换成这个类型。 </li>
            </ul>
            <p><strong>例 1：</strong> </p>
            <p>在下面这条语句中，在对 <code><font face=新宋体>bufferSize</font></code> 进行赋值时，从 <code><font face=新宋体>sizeof</font></code> 返回的 64 位值被截断成了 32 位。 </p>
            <p><code><font face=新宋体>int bufferSize = (int) sizeof (something); </font></code></p>
            <p>解决方案是使用 <code><font face=新宋体>size_t</font></code> 对返回值进行类型转换，并将其赋给声明为 <code><font face=新宋体>size_t</font></code> 类型的 bufferSize，如下所示： </p>
            <p><code><font face=新宋体>size_t bufferSize = (size_t) sizeof (something); </font></code></p>
            <p><strong>例 2：</strong> </p>
            <p>在 32 位系统上，int 和 long 大小相同。由于这一点，有些开发人员会交换使用这两种类型。这可能会导致指针被赋值给 int 类型，或者反之。但是在 64 位的系统上，将指针赋值给 int 类型会导致截断高 32 位的值。 </p>
            <p>解决方案是将指针作为指针类型或为此而定义的特殊类型进行存储，例如 <code><font face=新宋体>intptr_t</font></code> 和 <code><font face=新宋体>uintptr_t</font></code>。 </p>
            <p><a name=sidebars><span class=smalltitle>位移</span></a></p>
            <p>无类型的整数常量就是 (unsigned) int 类型的。这可能会导致在位移时出现被截断的问题。 </p>
            <p>例如，在下面的代码中，<code><font face=新宋体>a</font></code> 的最大值可以是 31。这是因为 <code><font face=新宋体>1 &lt;&lt; a</font></code> 是 int 类型的。 </p>
            <p><code><font face=新宋体>long t = 1 &lt;&lt; a; </font></code></p>
            <p>要在 64 位系统上进行位移，应该使用 <code><font face=新宋体>1L</font></code>，如下所示： </p>
            <p><code><font face=新宋体>long t = 1L &lt;&lt; a; </font></code></p>
            <p><a name=sidebars><span class=smalltitle>字符串格式化</span></a></p>
            <p>函数 <code><font face=新宋体>printf (3)</font></code> 及其相关函数都可能成为问题的根源。例如，在 32 位系统上，使用 <code><font face=新宋体>%d</font></code> 来打印 int 或 long 类型的值都可以，但是在 64 位平台上，这会导致将 long 类型的值截断成低 32 位的值。对于 long 类型的变量来说，正确的用法是 <code><font face=新宋体>%ld</font></code>。 </p>
            <p>类似地，当一个小整数（char、short、int）被传递给 <code><font face=新宋体>printf (3)</font></code> 时，它会扩展成 64 位的，符号会适当地进行扩展。在下面的例子中，<code><font face=新宋体>printf (3)</font></code> 假设指针是 32 位的。 </p>
            <p><code><font face=新宋体>char *ptr = &amp;something;<br>printf (%x\n", ptr); </font></code></p>
            <p>上面的代码在 64 位系统上会失败，它只会显示低 4 字节的内容。 </p>
            <p>这个问题的解决方案是使用 <code><font face=新宋体>%p</font></code>，如下所示；这在 32 位和 64 位系统上都可以很好地工作： </p>
            <p><code><font face=新宋体>char *ptr = &amp;something;<br>printf (%p\n", ptr); </font></code></p>
            <p><a name=sidebars><span class=smalltitle>函数参数</span></a></p>
            <p>在向函数传递参数时需要记住几件事情：
            <ul>
                <li>在参数的数据类型是由函数原型定义的情况中，参数应该根据标准规则转换成这种类型。
                <li>在参数类型没有指定的情况中，参数会被转换成更大的类型。
                <li>在 64 位系统上，整型被转换成 64 位的整型值，单精度的浮点类型被转换成双精度的浮点类型。
                <li>如果返回值没有指定，那么函数的缺省返回值是 int 类型的。 </li>
            </ul>
            <p>&#160;</p>
            <p>在将有符号整型和无符号整型的和作为 long 类型传递时就会出现问题。考虑下面的情况： </p>
            <br><br><a name=listing1><strong>清单 3. 将有符号整型和无符号整型的和作为 long 类型传递</strong></a><br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td class=code-outline>
                        <pre class=displaycode>long function (long l);
                        int main () {
                        int i = -2;
                        unsigned k = 1U;
                        long n = function (i + k);
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br>
            <p>上面这段代码在 64 位系统上会失败，因为表达式 <code><font face=新宋体>(i + k)</font></code> 是一个无符号的 32 位表达式，在将其转换成 long 类型时，符号并没有得到扩展。解决方案是将一个操作数强制转换成 64 位的类型。 </p>
            <p>在基于寄存器的系统上还有一个问题：系统采用寄存器而不是堆栈来向函数传递参数。考虑下面的例子： </p>
            <p><code><font face=新宋体>float f = 1.25;<br>printf ("The hex value of %f is %x", f, f); </font></code></p>
            <p>在基于堆栈的系统中，这会打印对应的 16 进制值。但是在基于寄存器的系统中，这个 16 进制的值会从一个整数寄存器中读取，而不是从浮点寄存器中读取。 </p>
            <p>解决方案是将浮点变量的地址强制转换成一个指向整型类型的指针，如下所示： </p>
            <p><code><font face=新宋体>printf ("The hex value of %f is %x", f, *(int *)&amp;f); </font></code></p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><font face=新宋体><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></font></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><font face=新宋体><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br></font>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><font face=新宋体><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></font></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www.ibm.com/developerworks/cn/linux/l-port64.html#main"><strong><font color=#606420><u>回页首</u></font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10542><span class=atitle>结束语</span></a></p>
            主流的硬件供应商最近都在扩充自己的 64 位产品，这是因为 64 位平台可以提供更好的性能、价值和可伸缩性。32 位系统的限制，特别是 4GB 的虚拟内存上限，已经极大地刺激很多公司开始考虑迁移到 64 位平台上。了解如何将应用程序移植到 64 位体系结构上可以帮助我们编写可移植性更好且效率更高的代码。 <br><br>
            <p><a name=resources><span class=atitle>参考资料 </span></a></p>
            <strong>学习</strong><br>
            <ul>
                <li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/linux/library/l-port64.html?S_TACT=105AGX52&amp;S_CMP=cn-a-l" target=_blank><font color=#0000ff><u>英文原文</u></font></a>。<br><br>
                <li><a href="http://www.unix.org/version2/whatsnew/lp64_wp.html"><font color=#0000ff><u>64-Bit Programming Models: Why LP64?</u></font></a> 介绍了有关各种 64 位编程模型的更多细节知识和有关 LP64 的争论。 <br><br>
                <li>请在 Wikipedia 上了解 32 位系统所具有的 <a href="http://en.wikipedia.org/wiki/Year_2038_problem"><font color=#0000ff><u>2038 年问题</u></font></a>。 <br><br>
                <li>请阅读 &#8220;<a href="http://www.ibm.com/developerworks/cn/linux/l-porting/"><font color=#0000ff><u>将企业应用程序从 UNIX 移植到 Linux</u></font></a>&#8221;（developerWorks，2005 年 2 月），了解有关将大型多线程应用程序移植到 Linux 上的技巧和内幕。 <br><br>
                <li>&#8220;<a href="http://www.ibm.com/developerworks/eserver/articles/davis_64_linux.html?S_TACT=105AGX52&amp;S_CMP=cn-a-l"><font color=#0000ff><u>Porting Intel applications to 64 bit Linux PowerPC</u></font></a>&#8221; 讨论了在将 Linux 从 IA32 移植到 PowerPC 上时所要考虑的一些问题。 <br><br>
                <li>Linux Online（linux.org） <a href="http://www.linux.org/dist/index.html"><font color=#0000ff><u>Linux distributions site</u></font></a> 提供了有关发行版的丰富信息，包括 64 位系统上的发行版。 <br><br>
                <li>developerWorks <a href="http://www.ibm.com/developerworks/linux/power/?S_TACT=105AGX52&amp;S_CMP=cn-a-l"><font color=#0000ff><u>Linux on Power Architecture developer's corner</u></font></a> 是为在基于 POWER 硬件的 Linux 上运行的应用程序的程序员和开发人员准备的参考资料。 <br><br>
                <li><a href="http://penguinppc.org/"><font color=#0000ff><u>penguinppc.org</u></font></a> 是专为 PowerPC 系统上的 Linux 用户准备的一个社区站点。 <br><br>
                <li>在 <a href="http://www.ibm.com/developerworks/cn/linux/"><font color=#0000ff><u>developerWorks Linux 专区</u></font></a> 中可以找到为 Linux 开发人员准备的更多参考资料。 <br><br>
                <li>随时关注 <a href="http://www.ibm.com/developerworks/offers/techbriefings/?S_TACT=105AGX52&amp;S_CMP=cn-a-l"><font color=#0000ff><u>developerWorks 技术事件和网络广播</u></font></a>。 </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/tommyyan/aggbug/30386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2007-08-19 22:54 <a href="http://www.cppblog.com/tommyyan/articles/30386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CVS, Automake与Autoconf简介</title><link>http://www.cppblog.com/tommyyan/articles/7664.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Thu, 25 May 2006 16:11:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/7664.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/7664.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/7664.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/7664.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/7664.html</trackback:ping><description><![CDATA[第一部分 CVS简介<br />cvs （ Concurrent Version System ）是一个版本控制系统，什么是版本控制系统呢？简单的说，它可以记录程序代码修改的过程，有一个完整的历史记录（ history ）。辟如说，当你在修改程序代码的时候， 不小心写出了一个 bug，但是你可能很久以后才发现多出了这个 bug， 这个时候，cvs 就能很有效的帮助你找出到底是在哪一次的修改中，出现了这个 bug。<br />也许你会说, 那我每次都把程序保存起来, 用tar 做好备份不就行了，当然, 你可以这样做, 但是这太浪费空间了！ cvs 在版本更改间, 只储存不同的部分, 这样就可以省下很多空间。<br />在另一个场合里, 更能显示出 cvs 的好处 ，比如多人一起开发软件的时候。 cvs支持远程访问, 用户可以对他要修改的文件加上正在编辑的标志, 让别人知道他要修改这个文件了。 当然, 一个较大的开发队伍，一般还会需要一个 mailing list 用来沟通。毕竟cvs 只是一个管理程序代码的工具, 他并不扮演沟通的角色。 cvs的同类软件还有rcs和sccs。RCS ( Revision Control System ) 可以从FSF获得。SCCS ( Source Code Control System ) 由AT&amp;T在SystemV中引入，现在已经被加入X/Open标准（ Unix 98? ）。比起这些软件，CVS的要优秀得多，特别是在支持多人远程开发方面。由于CVS出现较新，所以使用上反而没有它们普及。当然，如果您熟悉rcs,您会发现学习cvs非常容易。<br /><br />名词<br />repository： 意为仓库。在 cvs 里, 它就是你真正存放各历史版本的地方。 pserver： cvs 远程服务器，cvs 有两种工作模式, 一种是 local, 一种是 remote。 一般通过inetd启动pserver。<br />CVSROOT： 当使用 cvs 的时候, 要设定 CVSROOT这个环境变量, 或是用 -d 选项来指定该参数,该参数指明你的仓库放在哪里。<br /><br />本地（ local ）cvs<br />首先, 确定一个 cvsroot，比如：<br />export CVSROOT="/home/joe/cvsroot/" 建立该目录：<br />mkdir /home/joe/cvsroot<br />接着，运行cvs init ：<br />cvs init<br />cvs init 会帮你把 cvsroot 初始化。接着, 建立一个要放文件的目录 ( 相当于一个Project )： mkdir /home/joe/cvsroot/cvsdoc<br />cd /home/joe/work<br />cvs checkout cvsdoc（ 或者简写为： cvs co cvsdoc ） 你会看到下面的信息： cvs checkout: Updating cvsdoc cvs checkout 会把当前最新的版本拷贝到你的当前目录下。<br />记住, 不要自己建立 /home/joe/work/cvsdoc, 该目录下还会有一些用于管理的 cvs 相关的信息。<br />接着, 进入 cvsdoc 目录, 编辑 cvs.doc 这个文件档案，输入一些信息。<br />然后，运行：<br />cvs add cvs.txt cvs commit -m "Initial revision." cvs add 就会把 cvs.txt 加入 cvs 维护的文件列表中去。<br />cvs commit 检查当前目录下所有的在文件列表中的文件，并把对他们的改动加入到仓库中。-m 表示这次 commit 的 message，一般说明此次修改的相关信息。<br />现在修改一下 cvs.txt，并且，在文件档案的最上面加上 $Id$ 的字样。<br />改完之后, 再 commit 一次：<br />cvs commit -m "Adding new stuff."<br />现在看看我们所做的修改：<br />cvs log cvs.txt<br />可以看到：<br />RCS file: /home/joe/cvsroot/cvsdoc/cvs.txt,v<br />Working file: cvs.txt<br />head: 1.2<br />branch:<br />locks: strict<br />access list:<br />symbolic names:<br />keyword substitution: kv<br />total revisions: 2; selected revisions: 2<br />description:<br />----------------------------<br />revision 1.2<br />date: 2000/09/11 11:55:06; author: joe; state: Exp; lines: +2 -0<br />i<br />----------------------------<br />revision 1.1<br />date: 2000/09/11 11:52:32; author: joe; state: Exp;<br />initial version<br />==================================================================<br />你会看到每次修改加进去的 message。这对开发者，特别是一个大的项目的开发者，其帮助是不言而喻的。<br />cvs diff -r 1.1 -r 1.2 cvs.txt<br />可以看到：<br />Index: cvs.txt<br />================================================================== RCS file: /home/joe/cvsroot/cvsdoc/cvs.txt,v<br />retrieving revision 1.1<br />retrieving revision 1.2<br />diff -r1.1 -r1.2<br />0a1<br />&gt; $Id: cvs.txt,v 1.2 2000/09/11 11:55:06 joe Exp $<br />1a3<br />&gt; hehe,sencond time edit it!<br />这样会显示 1.1 和 1.2 版的 diff, 原本有 1.1 版的人, 只需要用这个 patch 就可以了升级到1.2了！<br />再编辑 cvs.txt, 可以发现最上面的 Id 变长了? 加了一代串文字：<br />$Id: cvs.txt,v 1.2 2000/09/11 11:55:06 joe Exp $ 这显示这个版本的一些相关信息。<br />远程（ remote ）cvs<br />如果我们要做一个比较大的项目，上面讲的本地cvs服务就太简单了，我们要让众多的人可以远程开发程序！ 比如我们要用cvs组织起我们的minigui项目。 检查 /etc/services 有没有这两行，没有请加入：<br />cvspserver 2401/tcp #CVS network server cvspserver 2401/udp #CVS network server<br />在 /etc/inetd.conf 加入：<br />cvspserver stream tcp nowait root /usr/local/bin/cvs cvs --allow-root=/home/minigui pserver<br />mkdir /home/minigui<br />要是该设置生效，请重启inetd。<br />添加用户anoncvs, 这是要给匿名cvs 用户使用的帐号，其组为nogroup。 新加一个名为 minigui的 group。 添加参与 minigui开发的用户的帐号, 当然, 把他们的 group 设为 minigui。<br />cvs -d /home/minigui init<br />cd /root/minigui, 这是原来已经存在的版本, 现在我们要把它的东西放进 cvs 仓库里： 比如，我们把minigui的库minigui03放到仓库中：<br /><br />cd minigui03;cvs import –m “the lib” minigui03 joe start<br /><br />会看到cvs把一个个文件放到仓库中。<br />cvs import 的语法为：<br /><br />cvs import -m "log msg" projname vendortag releasetag<br /><br />vendortag 和releasetag 一般不需要关心，我们这里使用一个用户名和一个start 标志。<br />我们把其它相关的project也放到cvs仓库中：<br /><br />cd miniguiapps03 ; cvs import –m “the apps” miniguiapps03 joe start<br />cd miniguiexec03 ; cvs import –m “the demos” miniguiexec03 joe start<br /><br />这样，我们就把minigui的一个cvs服务器建立好了。<br />注意, 一个 user 要远程访问某些project, 他必须拥有适当的权限。比如，minigui03这个目录应该属于组minigui，且组可写。才能使minigui组里的用户可以远程参与minigui库的开发。<br /><br />现在试试看从远程访问 cvs 服务器。<br />首先, 在你的机器上建立一个工作目录, 譬如是 /home/joe/work<br />cd /home/joe/work<br />cvs -d :pserver:joe@www.minigui.org:/home/minigui login<br />cvs -d :pserver:joe@www.minigui.org:/home/minigui co minigui03<br />cvs -d :pserver:joe@www.minigui.org:/home/minigui co miniguiapps03<br />cvs -d :pserver:joe@www.minigui.org:/home/minigui co miniguiexec03<br />cvs -d :pserver:joe@www.minigui.org:/home/minigui logout<br /><br />当你敲入login行时，系统会提示你输入password, 打进去。 www.minigui.org是cvs服务器所在的机器。 该指定被执行后，该 cvsroot<br />(:pserver:joe@www.minigui.org:/home/minigui) 和加密后的密码会被存在 ~/.cvspass 里。<br />底下几行取出各个project。最后logout。<br /><br />cd minigui03<br /><br />做了一些修改后，可以commit出去：<br /><br />cvs commit -m "little change"<br />上面是一般开发者的登陆方法，对于匿名cvs, 可以让其不需要输入口令即可登陆，但是不能让其commint。这需要：<br />1． 将要开放的project设为全局可读写，因为cvs服务器在操作时要在相应目录下设置读写琐（即需要创建一些临时文件），所以即使是check out 操作，也需要目录可写。<br />2． 为了让匿名用户只有check out权限，可以在CVSROOT目录下建立一个readers文件，其中每一行是一个用户，这些用户只具有只读权限。比如：<br />anonymous<br />anoncvs<br />guest<br />jbrowse<br />3. 利用passwd文件，使匿名用户不能用其它方式登陆。典型为：<br />在文件CVSROOT/passwd 中：<br />anoncvs:XR4EZcEs0szik<br />在文件/etc/passwd 中为：<br />anoncvs:!:1729:105:Anonymous CVS User:/home/minigui:/bin/false<br />CVSROOT/passwd文件是cvs提供的一个专用于存放cvs密码的文件。它的典型格式为：<br />joe:XR4EZcEs0szik:jane<br />表示cvs用户joe其实是内部用户jane,其cvs密码加密后被存放在第二个字段，这样就将cvs服务与系统的其它部分分离开来，大大地提高了系统的安全性。<br />上面介绍的是使用需要严格的安全认证的pserver服务器，如果您在局域网内开发程序，则可以使用rsh或者ssh,设置非常简单，服务器端只要开放着 rsh或ssh服务器，客户端设置两个环境变量：CVS_RSH与CVSROOT,可以将它们的设置写入预处理脚本，比如使用ssh连接：<br /><br />$export CVS_RSH="ssh"<br />$export CVSROOT=":ext:joe@www.minigui.org:/home/minigui"<br /><br />$ cvs co miniguiexec03<br />joe@192.9.200.75's password:<br /><br />输入密码，就可以得到一份miniguiexec03的拷贝了。<br /><br /><br />总结<br />以上只是一个简介，cvs还有很多高级功能，如果您需要更详细的信息，请看cvs 的info或者到gnu上下载html版本的manual。<br /><br />第二部分 使用Automake,Autoconf生成Makefile<br />在Unix上写过程序的人尤其是用 C 来开发程序的人一般都遇到过 Makefile，用 make 来开发和编译程序的确很方便，可是要写出一个Makefile就不那么简单了。GNU Make 那份几百页的文件，让许多人害怕。当然，现在关于make的文档比较多，不过写一个Makefile总是一件很烦人的事情，GNU Autoconf 及 Automake 这两个软件就是帮助程序开发者轻松产生Makefile 文件的。现在的GNU软件如Apache, MySQL Minigui等都是利用Autoconf,Automake实现自动编译的。用户只要使用 “./configure”, “make”, “make install” 就可以把程序安裝到系统中。<br /><br />简介<br />Makefile 基本上就是『目标』(target), 『关联』(dependencies) 和『动作』三者所组成的一系列规则。而 make 就是根据 Makefile 的规则决定如何编译 (compile) 和连接 (link) 程序或者其它动作。当然，make 可做的不只是编译和连接程序，例如 FreeBSD 的 port collection 中，Makefile还可以做到自动下载远程程序，解压缩 (extract) ， 打补丁 (patch)，设定，然后编译，安装到系统中。<br /><br />Makefile 基本结构虽然很简单，但是妥善运用这些规则就可以变换出许多不同的花样。却也因为这样，许多人刚开始学写Makefile 时会觉得没有规范可以遵循，每个人写出来的Makefile都不大一样，不知道从哪里下手，而且常常会受到开发环境的限制，只要环境参数不同或者路径更改，可能 Makefile 就得跟着修改。虽然有GNU Makefile Conventions (GNU Makefile惯例)制订出一些在进行 GNU 程序设计时写 Makefile 的一些标准和规范，但是其内容很长而且很复杂，并且经常作一些调整，为了减轻程序开发人员维护Makefile 的负担，就出现了Automake。<br /><br />利用Automake,编程者只需要写一些预先定义好的宏 (macro)，提交给Automake处理，就会产生一个可以供 Autoconf 使用的 Makefile.in文件。再配合使用 Autoconf产生的自动配置文件 configure 即可产生一份符合 GNU Makefile 惯例的 Makeifle 了。<br /><br /><br />　<br /><br />需要的软件<br />在开始使用 Automake 之前，首先确认你的系统安装有如下软件：<br /><br />1. GNU Automake<br />2. GNU Autoconf<br />3. GNU m4<br />4. perl<br />5. GNU Libtool (如果你需要产生 shared library)<br /><br />最好也使用 GNU C/C++ 编译器 、GNU Make 以及其它 GNU 的工具程序来作为开发的环境，这些工具都是属于 Open Source Software 不但免费而且功能强大。如果你是使用 Red Hat Linux 可以找到所有上述软件的 rpm 文件。　<br /><br />一个简单的例子<br />Automake 所产生的 Makefile 除了可以做到程序的编译和连接，也可以用来生成文档(如 manual page, info 文件等)，还可以有把源码文件包装起来以供发布，所以程序源代码所存放的目录结构最好符合GNU 的标准惯例，接下来就用一个hello.c ?碜鑫印?br /&gt; <br />在工作目录下建立一个新的子目录devel，再在 devel 下建立一个"hello"' 的子目录，这个目录将<br />作为存放 hello这个程序及其相关文件的地方：<br /><br />% mkdir devel;cd devel;mkdir hello;cd hello<br /><br />用编辑器写一个hello.c文件，<br /><br />#include &lt;stdio.h&gt;<br />int main(int argc, char** argv)<br />{<br />printf(“Hello, GNU!n”);<br />return 0;<br />}<br /><br />接下来就要用 Autoconf 及 Automake ?聿?Makefile 文件了，<br /><br />1. 用 autoscan 产生一个 configure.in 的原型，执行autoscan 后会产生一个configure.scan 的文件，可以用它作为 configure.in文件的蓝本。<br />　<br />% autoscan<br />% ls<br />configure.scan hello.c<br /><br />2. 编辑 configure.scan文件，如下所示，?K且改名为configure.in<br /><br />dnl Process this file with Autoconf to produce a configure script.<br />AC_INIT(hello.c)<br />AM_INIT_AUTOMAKE(hello, 1.0)<br />dnl Checks for programs.<br />AC_PROG_CC<br />dnl Checks for libraries.<br />dnl Checks for header files.<br />dnl Checks for typedefs, structures, and compiler characteristics.<br />dnl Checks for library functions.<br />AC_OUTPUT(Makefile)<br /><br />3. 执行 aclocal 和 Autoconf ，分別会产生 aclocal.m4 及 configure 两个文件<br /><br />% aclocal<br />% Autoconf<br />% ls<br />aclocal.m4 configure configure.in hello.c<br /><br />4. 编辑 Makefile.am 文件，內容如下<br /><br />AUTOMAKE_OPTIONS= foreign<br />bin_PROGRAMS= hello<br />hello_SOURCES= hello.c<br /><br />5. 执行 Automake --add-missing ，Automake 会根据Makefile.am 文件产生一些文件，包含最重要的Makefile.in<br /><br />% Automake --add-missing<br />Automake: configure.in: installing `./install-sh'<br />Automake: configure.in: installing `./mkinstalldirs'<br />Automake: configure.in: installing `./missing'<br /><br />6. 最后执行 ./configure:<br /><br />% ./configure<br />creating cache ./config.cache<br />checking for a BSD compatible install... /usr/bin/install -c<br />checking whether build environment is sane... yes<br />checking whether make sets ${MAKE}... yes<br />checking for working aclocal... found<br />checking for working Autoconf... found<br />checking for working Automake... found<br />checking for working autoheader... found<br />checking for working makeinfo... found<br />checking for gcc... gcc<br />checking whether the C compiler (gcc ) works... yes<br />checking whether the C compiler (gcc ) is a cross-compiler... no<br />checking whether we are using GNU C... yes<br />checking whether gcc accepts -g... yes<br />updating cache ./config.cache<br />creating ./config.status<br />creating Makefile<br /><br />$ ls<br />Makefile aclocal.m4 config.status hello.c mkinstalldirs<br />Makefile.am config.cache configure install-sh<br />Makefile.in config.log configure.in missing<br /><br />現在你的目录下已经产生了一个 Makefile 文件，输入make指令就可以编译 hello.c 了！<br /><br />% make<br />gcc -DPACKAGE="hello" -DVERSION="1.0" -I. -I. -g -O2 -c hello.c<br />gcc -g -O2 -o hello hello.o<br /><br />你还可以试试 “make clean“，”make install“，”make dist“：<br />[root@localhost hello]# make clean<br />test -z "hello " || rm -f hello<br />rm -f *.o core *.core<br />[root@localhost hello]# make install<br />gcc -DPACKAGE="hello" -DVERSION="1.0" -I. -I. -g -O2 -c hello.c<br />gcc -g -O2 -o hello hello.o<br />make[1]: Entering directory `/home/joe/devel/hello'<br />/bin/sh ./mkinstalldirs /usr/local/bin<br />/usr/bin/install -c hello /usr/local/bin/hello<br />make[1]: Nothing to be done for `install-data-am'.<br />make[1]: Leaving directory `/home/joe/devel/hello'<br />[root@localhost hello]# make dist<br />rm -rf hello-1.0<br />mkdir hello-1.0<br />chmod 777 hello-1.0<br />here=`cd . &amp;&amp; pwd`;<br />top_distdir=`cd hello-1.0 &amp;&amp; pwd`;<br />distdir=`cd hello-1.0 &amp;&amp; pwd`;<br />cd .<br />&amp;&amp; Automake --include-deps --build-dir=$here --srcdir-name=. --output-dir=$top_distdir --foreign Makefile<br />chmod -R a+r hello-1.0<br />GZIP=--best gtar chozf hello-1.0.tar.gz hello-1.0<br />rm -rf hello-1.0<br />一切工作得很好! 当然，在make install时由于需要向系统目录拷贝文件，您需要有root权限。<br /><br />更进一步<br />上述产生Makefile 的过程和以往自行编写的方式非常不一样，使用 Automake 只需用到一些已经定义好的宏就可以了。我们把宏及目标 (target)写在Makefile.am 文件内，Automake 读入 Makefile.am 文件后会把这一串已经定义好的宏展开并产生相对应的<br />Makefile.in 文件，然后再由configure这个 shell script 根据 Makefile.in 产生合适的Makefile。<br />具体流程如下所示：<br />代码 --&gt; [autoscan*] --&gt; [configure.scan] --&gt; configure.in<br />configure.in --. .------&gt; Autoconf* -----&gt; configure<br />+---+<br />[aclocal.m4] --+ `---.<br />[acsite.m4] ---' |<br />+--&gt; [autoheader*] -&gt; [config.h.in]<br />[acconfig.h] ----. |<br />+-----'<br />[config.h.top] --+<br />[config.h.bot] --'<br /><br />Makefile.am -- [Autoconf*] -------&gt; Makefile.in<br /><br />.-------------&gt; config.cache<br />configure* ------------+-------------&gt; config.log<br />|<br />[config.h.in] -. v .-&gt; [config.h] -.<br />+--&gt; config.status* -+ +--&gt; make*<br />Makefile.in ---' `-&gt; Makefile ---'<br /><br />上图表示在整个过程中要使用的文件及产生出来的文件，有星号 (*) 代表可执行文件。在此示例中可由 Autoconf 及 Automake 工具所产生的额外文件有 configure.scan、aclocal.m4、configure、Makefile.in，需要加入设置的有configure.in 及 Makefile.am。开发者要书写的文件集中为confiugre.in和Makefile.am,在minigui项目中，我们把一系列的命令集中到一个批处理文件中： autogen.sh:<br /><br />#!/bin/sh<br />aclocal<br />autoheader<br />Automake --add-missing<br />Autoconf<br /><br />只要执行该批处理文件，结合configure.in和Makefile.am，就可以生成需要的Makefile了。<br /><br />编辑 configure.in 文件<br />Autoconf 是用来产生 'configure'文件的工具。'configure' 是一个 shell script，它可以自动设定一些编译参数使程序能够条件编译以符合各种不同平台的Unix 系统。Autoconf会读取configure.in 文件然后产生'configure' 这个 shell script。<br /><br />configure.in 文件内容是一系列GNU m4 的宏，这些宏经Autoconf处理后会变成检查系统特性的shell scripts。 configure.in文件中宏的顺序并没有特别的规定，但是每一个configure.in 文件必须在所有其它宏前加入 AC_INIT 宏，然后在所有其它宏的最后加上 AC_OUTPUT宏。一般可先用 autoscan 扫描原始文件以产生一个 configure.scan 文件，再对 configure.scan 做些修改成 configure.in 文件。在例子中所用到的宏如下：<br /><br />dnl<br />这个宏后面的内容不会被处理，可以视为注释<br /><br />AC_INIT(FILE)<br />该宏用来检查源代码所在路径，autoscan 会自动产生，一般无须修改它。<br /><br />AM_INIT_AUTOMAKE(PACKAGE,VERSION)<br />这个是使用 Automake 所必备的宏，PACKAGE 是所要产生软件的名称，VERSION 是版本编号。<br /><br />AC_PROG_CC<br />检查系统可用的C编译器，若源代码是用C写的就需要这个宏。<br /><br />AC_OUTPUT(FILE)<br />设置 configure 所要产生的文件，若是Makefile ，configure 便会把它检查出来的结果填充到Makefile.in 文件后产生合适的 Makefile。<br /><br />实际上，在使用 Automake 时，还需要一些其他的宏，这些额外的宏我们用 aclocal来帮助产生。执行 aclocal会产生aclocal.m4 文件，如果没有特别的用途，不需要修改它，用 aclocal 所产生的宏会告诉 Automake如何动作。<br /><br />有了 configure.in 及 aclocal.m4两个文件以后，便可以执行 Autoconf来产生 configure 文件了。<br /><br />编辑Makefile.am 文件<br />接下来要编辑Makefile.am 文件，Automake 会根据 configure.in 中的宏并在perl的帮助下把Makefile.am 转成 Makefile.in 文件。 Makefile.am 文件定义所要产生的目标：<br /><br />AUTOMAKE_OPTIONS<br />设置 Automake 的选项。Automake 主要是帮助开发 GNU 软件的人员来维护软件，所以在执行Automake 时，会检查目录下是否存在标准 GNU 软件中应具备的文件，例如 'NEWS'、'AUTHOR'、<br />'ChangeLog' 等文件。设置为foreign 时，Automake 会改用一般软件的标准来检查。<br /><br />bin_PROGRAMS<br />定义要产生的执行文件名。如果要产生多个执行文件，每个文件名用空白符隔开。<br /><br />hello_SOURCES<br />定义 'hello' 这个执行程序所需要的原始文件。如果 'hello'这个程序是由多个原始文件所产生，<br />必須把它所用到的所有原始文件都列出来，以空白符隔开。假设 'hello' 还需要 'hello.c'、'main.c'、'hello.h' 三个文件的话，则定义<br />hello_SOURCES= hello.c main.c hello.h<br />如果定义多个执行文件，则对每个执行程序都要定义相对的filename_SOURCES。<br /><br />编辑好 Makefile.am 文件，就可以用 Automake --add-missing来产生 Makefile.in。加上 --add-missing 选项来告诉 Automake顺便加入包装一个软件所必须的文件，如果你不使用该选项，Automake可能会抱怨缺少了什么文件。Automake产生出?淼?Makefile.in 文件是完全符合 GNU Makefile 惯例的，只要执行 configure这个shell<br />script 便可以产生合适的 Makefile 文件了。<br /><br />使用 Makefile<br />利用 configure 所产生的 Makefile文件有几个预先设定的目标可供使用，这里只用几个简述如下：<br /><br />make all<br />产生设定的目标，既范例中的可执行文件。只敲入make 也可以，此时会开始编译源代码，然后连接并产生执行文件。<br /><br />make clean<br />清除之前所编译的可执行文件及目标文件(object file, *.o)。<br /><br />make distclean<br />除了清除可执行文件和目标文件以外，也把 configure 所产生的 Makefile 清除掉。 通常在发布软件前执行该命令。<br /><br />make install<br />将程序安装到系统中，若源码编译成功，且执行结果正确，便可以把程序安装到系统预先设定的执行文件存放路径中，若用 bin_PROGRAMS 宏的话，程序会被安装到 /usr/local/bin下。<br /><br />make dist<br />将程序和相关的文档包装为一个压缩文档以供发布 (distribution) 。执行完在目录下会产生一个以<br />PACKAGE-VERSION.tar.gz 为名称的文件。PACKAGE 和 VERSION 这两个参数是根据 configure.in 文中<br />AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定义。在我们的例子中会产生 'hello-1.0.tar.gz' 的文件。<br /><br />make distcheck<br />和 make dist 类似，但是加爰觳榘耙院蟮难顾跷募欠裾＃飧瞿勘瓿税殉绦蚝拖喙匚牡蛋俺?tar.gz 文件外，还会自动把这个压缩文件解开，执行 configure，并执行 make all ，确认编译无错误以后，方显示这个 tar.gz 文件已经准备好并可以发布了。当你看到：<br />==========================================<br />hello-1.0.tar.gz is ready for distribution<br />==========================================<br /><br />就可以放心地发布您的软件了，检查过关的套件，基本上可以给任何具备 GNU 开发环境的人去重新编译成功。<br />要注意的是，利用 Autoconf 及 Automake 所产生出?淼娜砑准强梢栽诿挥邪沧?Autoconf 及 Automake 的环境使用的，因为 configure 是一个 shell script，它己被设计为可以在一般 Unix 的 sh 这个 shell 下执行。但是如果要修改 configure.in 及 Makefile.am 文件再产生新的 configure 及 Makefile.in 文件时就一定要有 Autoconf 及 Automake 了。<br /><br />相关资料<br />通常我们掌握了一些入门知识就可以开始实践了，在有新的需求时，参照相关的文档和别人的例子解决问题，在实践中不断提高。<br />Autoconf 和 Automake 功能十分强大，可以从它们附带的 info 文档中找到详细的使用说明。或者您喜欢html,可以从gun站点上下载hmtl版本。你也可以从许多现有的GNU 软件或 Open Source 软件如Minigui中找到相关的 configure.in 或 Makefile.am 文件，他们是学习 Autoconf 及 Automake 更多技巧的最佳范例。<br /><img src ="http://www.cppblog.com/tommyyan/aggbug/7664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2006-05-26 00:11 <a href="http://www.cppblog.com/tommyyan/articles/7664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>APT and Dpkg 快速参考表</title><link>http://www.cppblog.com/tommyyan/articles/7588.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Wed, 24 May 2006 10:32:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/7588.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/7588.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/7588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/7588.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/7588.html</trackback:ping><description><![CDATA[Matthew Danish ( pye,quanliking合译 )<br /><br /><br />普通 APT 用法<br /><br />apt-get install &lt;package&gt;<br />下载 &lt;package&gt; 以及所有倚赖的包裹,同时进行包裹的安装或升级.如果某个包裹被设置了 hold (停止标志,就会被搁在一边(即不会被升级).更多 hold 细节请看下面.<br /><br />apt-get remove [--purge] &lt;package&gt;<br />移除 &lt;package&gt; 以及任何倚赖这个包裹的其它包裹.<br />--purge 指明这个包裹应该被完全清除 (purged) ,更多信息请看 dpkg -P .<br /><br />apt-get update<br />升级来自 Debian 镜像的包裹列表,如果你想安装当天的任何软件,至少每天运行一次,而且每次修改了<br />/etc/apt/sources.list 后,必须执行.<br /><br />apt-get upgrade [-u]<br />升级所以已经安装的包裹为最新可用版本.不会安装新的或移除老的包裹.如果一个包改变了倚赖关系而需要安装一个新的包裹,那么它将不会被升级,而是标志为hold .apt-get update 不会升级被标志为 hold 的包裹 (这个也就是 hold 的意思).请看下文如何手动设置包裹为 hold .我建议同时使用 \'-u\' 选项,因为这样你就能看到哪些包裹将会被升级.<br /><br />apt-get dist-upgrade [-u]<br />和 apt-get upgrade 类似,除了 dist-upgrade 会安装和移除包裹来满足倚赖关系.因此具有一定的危险性.<br /><br />apt-cache search &lt;pattern&gt;<br />搜索满足 &lt;pattern&gt; 的包裹和描述.<br /><br />apt-cache show &lt;package&gt;<br />显示 &lt;package&gt; 的完整的描述.<br /><br />apt-cache showpkg &lt;package&gt;<br />显示 &lt;package&gt; 许多细节,以及和其它包裹的关系.<br /><br />dselect<br />console-apt<br />aptitude<br />gnome-apt<br />APT 的几个图形前端(其中一些在使用前得先安装).这里 dselect 无疑是最强大的,也是最古老,最难驾驭.<br /><br />普通 Dpkg 用法<br />dpkg -i &lt;package.deb&gt;<br />安装一个 Debian 包裹文件;如你手动下载的文件.<br /><br />dpkg -c &lt;package.deb&gt;<br />列出 &lt;package.deb&gt; 的内容.<br /><br />dpkg -I &lt;package.deb&gt;<br />从 &lt;package.deb&gt; 中提取包裹信息.<br /><br />dpkg -r &lt;package&gt;<br />移除一个已安装的包裹.<br /><br />dpkg -P &lt;package&gt;<br />完全清除一个已安装的包裹.和 remove 不同的是, remove 只是删掉数据和可执行文件, purge 另外还删除所有的配制文件.<br /><br />dpkg -L &lt;package&gt;<br />列出 &lt;package&gt; 安装的所有文件清单.同时请看 dpkg -c 来检查一个 .deb 文件的内容.<br /><br />dpkg -s &lt;package&gt;<br />显示已安装包裹的信息.同时请看 apt-cache 显示 Debian 存档中的包裹信息,以及 dpkg -I 来显示从一个<br />.deb 文件中提取的包裹信息.<br /><br />dpkg-reconfigure &lt;package&gt;<br />重新配制一个已经安装的包裹,如果它使用的是 debconf (debconf 为包裹安装提供了一个统一的配制界面).你能够重新配制 debconf 它本身,如你想改变它的前端或提问的优先权.例如,重新配制 debconf ,使用一个 dialog 前端,简单运行:<br /><br />dpkg-reconfigure --frontend=dialog debconf (如果你安装时选错了,这里可以改回来哟<br /><br />echo \"&lt;package&gt; hold\" | dpkg --set-selections<br />设置 &lt;package&gt; 的状态为 hlod (命令行方式)<br /><br />dpkg --get-selections \"&lt;package&gt;\"<br />取的 &lt;package&gt; 的当前状态 (命令行方式)<br /><br />支持通配符,如:<br />Debian:~# dpkg --get-selections *wine*<br />libwine hold<br />libwine-alsa hold<br />libwine-arts hold<br />libwine-dev hold<br />libwine-nas hold<br />libwine-print hold<br />libwine-twain hold<br />wine hold<br />wine+ hold<br />wine-doc hold<br />wine-utils hold<br /><br />例如:<br />大家现在用的都是 gaim-0.58 + QQ-plugin,为了防止 gaim 被升级,我们可以采用如下方法:<br /><br />方法一:<br />Debian:~# echo \"gaim hold\" | dpkg --set-selections<br />然后用下面命令检查一下:<br />Debian:~# dpkg --get-selections \"gaim\"<br />gaim hold<br />现在的状态标志是 hold,就不能被升级了.<br /><br />如果想恢复怎么办呢?<br />Debian:~# echo \"gaim install\" | dpkg --set-selections<br />Debian:~# dpkg --get-selections \"gaim\"<br />gaim install<br />这时状态标志又被重置为 install,可以继续升级了.<br /><br />同志们会问,哪个这些状态标志都写在哪个文件中呢?<br />在 /var/lib/dpkg/status 里,你也可以通过修改这个文件实现 hold.<br /><br />有时你会发现有的软件状态标志是 purge,不要奇怪.<br />如:事先已经安装了 amsn, 然后把它卸了.<br />apt-get remove --purge amsn<br />那么状态标志就从 install 变成 purge.<br /><br />方法二:<br />在/etc/apt 下手动建一个 preferences 文件<br />内容：<br />Package: gaim<br />Pin: version 0.58*<br />保存<br />更详细内容请看:<br />http://linuxsir.com/bbs/showthread....&amp;threadid=22601<br /><br />dpkg -S &lt;file&gt;<br />在包裹数据库中查找 &lt;file&gt;,并告诉你哪个包裹包含了这个文件.(注:查找的是事先已经安装的包裹)<br /><br />从源码建立deb packages<br /><br />apt-get source [-b] &lt;package&gt; <br />下载一个源码的包并解开。<br />你必须在你的/etc/apt/sources.list文件里写入一条 deb-src 的记录才能完成这项工作。<br />如果你输入了一个-b参数，并且是以root的身份，deb包会被自动的创建。<br /><br />apt-get build-dep &lt;package&gt; <br />自动下载并安装通过源码创建 &lt;package&gt; 时需要的包。<br />只有apt 0.5以上版本才支持这个功能。<br />现在woody和以上版本包含了这个功能。<br />如果你使有一个旧版本的apt，查找依赖性最简单的方法是查看源码包中 debian/control 这个文件，<br />注意这个路径是相对的，是包内的路径。<br /><br />普通的用法，结合 apt-get source -b,例子 (as root)：<br /><br />apt-get build-dep &lt;package&gt;<br />apt-get source -b &lt;package&gt;<br /><br />会下载源码包，建立依赖性，然后尝试编译源码。<br /><br />dpkg-source -x &lt;package.dsc&gt;<br />如果你手工下载了一个程序的源码包，其中包含了几个类似 .orig.tar.gz , .dsc ,<br />以及 .diff.gz 之类的文件，<br />那么你就可以对 .dsc 文件使用这个命令来 unpack 源码包。<br /><br />dpkg-buildpackage<br />从 Debian 源码树建立一个deb包。你必须在source tree的主目录才能生效。例如：<br /><br />dpkg-buildpackage -rfakeroot -uc -b<br /><br />这里 \'-rfakeroot\' 指定命令使用 fakeroot 程序来模仿 root 权限 (来实现所有者(ownership)目的)，<br />\'-uc\' 表示 \"Don\'t cryptographically sign the changelog\", \'-b\' 代表只建立二进制包.<br /><br />debuild<br />一个快速打包脚本类似 dpkg-buildpackage ,能自动的识别是否使用 fakeroot,<br />同时为你运行 lintian 和 gpg <br /><br />修正倚赖关系<br /><br />dpkg --configure --pending<br />如果dpkg在apt-get install upgrade dist-uptradeing 的时候出错退出，<br />尝试使用此命令来配置已经unpack的包。<br />然后再用 apt-get install ，upgrade, or dist-upgrade -f ，<br />然后再用 apt-get install, upgrade, or dist-upgrade.<br /><br />可能会重复多次，这样通常可以解决大多数的依赖性问题。<br />(同时,如果提示由于某种原因需要某个特定的包裹,你可以常识安装或卸载这个包)<br /><br />apt-get install -f<br />apt-get upgrade -f<br />apt-get dist-upgrade -f <br />尝试修正上述过程中出现依赖性关系<br />注意 apt-get install -f 不需要 &lt;package&gt; 作为参数。<img src ="http://www.cppblog.com/tommyyan/aggbug/7588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2006-05-24 18:32 <a href="http://www.cppblog.com/tommyyan/articles/7588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Linux]常用命令</title><link>http://www.cppblog.com/tommyyan/articles/5120.html</link><dc:creator>星仁</dc:creator><author>星仁</author><pubDate>Thu, 06 Apr 2006 16:14:00 GMT</pubDate><guid>http://www.cppblog.com/tommyyan/articles/5120.html</guid><wfw:comment>http://www.cppblog.com/tommyyan/comments/5120.html</wfw:comment><comments>http://www.cppblog.com/tommyyan/articles/5120.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tommyyan/comments/commentRss/5120.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tommyyan/services/trackbacks/5120.html</trackback:ping><description><![CDATA[
		<strong>1、<font color="#2f3192">查看目录的大小</font></strong> du -sh dirname   <br />-s 仅显示总计   <br />-h 以k、m、g为单位，提高信息的可读性。kb、mb、gb是以1024为换算单 位， -h以1000为换算单位  <br />以下是刚装好的RH9.0(全部) Linux目录大小参考：  <br />/usr        4.5G  /usr/share  2.2G  /usr/src     189M   /usr/games 3.9M <br />/usr/X11R6  173M  /usr/lib    1.5G  /usr/include  91M  <br />/var        250M  /var/www    130M  /usr/bin     258M <img src ="http://www.cppblog.com/tommyyan/aggbug/5120.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tommyyan/" target="_blank">星仁</a> 2006-04-07 00:14 <a href="http://www.cppblog.com/tommyyan/articles/5120.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>