<?xml version="1.0" encoding="GBK" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dcterms="http://purl.org/dc/terms/">
 <channel>
  	  <title><![CDATA[Pan Ant]]></title>
	  <link>http://pannsp.blog.163.com</link>
	  <description><![CDATA[ 人生就象小蚂蚁一样的不懈的努力，奋勇向前]]></description>
	  <language>zh-CN</language>
	  <pubDate>Fri, 8 May 2009 10:19:27 +0800</pubDate>
	  <lastBuildDate>Fri, 8 May 2009 10:19:27 +0800</lastBuildDate>
	  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
	  <generator><![CDATA[NetEase Space]]></generator>
	  <managingEditor><![CDATA[pannsp]]></managingEditor>
	  <webMaster><![CDATA[pannsp]]></webMaster>
		  <ttl>120</ttl>
	  <image>
	  	<title><![CDATA[Pan Ant]]></title>
	  	<url>http://ava.bimg.126.net/photo/Sbc5DySyW3ltbkvc-Vv9mA==/213076557370107277.jpg</url>
	  	<link>http://pannsp.blog.163.com</link>
	  </image>
  <item>
  	<title><![CDATA[Tslib的编译和触摸屏测试]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200898102717592</link>
    <description><![CDATA[<div><P>1.编译<BR>前段时间非常的郁闷…因为在运行生成校准程序ts_calibrate时总是出现一个错误：ts_open:Inappropriate ioctol for device<BR>后来无数折腾后经过nanfansky指点才知道是自己板子的触摸屏驱动不支持ioctl操作，狂汗…<BR>&nbsp;<BR>重新编译tslib<BR>&nbsp;<BR>cd tslib-1.3<BR>&nbsp;<BR>export CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc&nbsp;&nbsp; //指定交叉编译器<BR>&nbsp;<BR>./autogen.sh&nbsp;&nbsp; //生成config文件<BR>&nbsp;<BR>export PATH=/usr/local/arm/2.95.3/bin:$PATH<BR>&nbsp;<BR>echo "ac_cv_func_malloc_0_nonnull=yes" &gt;arm-linux.cache <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>./configure --host=arm-linux --cache-file=arm-linux.cache --enable-inputapi=no <BR>&nbsp;<BR>vi src/ts_read_raw.c //修改内容如下<BR>&nbsp;<BR>make<BR>&nbsp;<BR>&nbsp;<BR>****************************************************<BR>在make之前，为了支持触摸屏,打开src/ts_read_raw.c文件，查看触摸屏驱动程序数据结构，看与ts_read_raw.c结构中的哪个一样，就将代码中的 char *defaulttseventtype="UCB1x00"; 修改为 自己板子上对应的驱动结构。<BR>因为我的驱动对应的是h3600_ts_event结构<BR>typedef struct {<BR>&nbsp;unsigned short pressure;<BR>&nbsp;unsigned short x;<BR>&nbsp;unsigned short y;<BR>&nbsp;unsigned short pad;<BR>} TS_RET; <BR>所以修改为：<BR>&nbsp;&nbsp; char *defaulttseventtype="H3600"; <BR>&nbsp;<BR>************************************<BR>如果不修改源代码，也可以在后面的测试中重新指定环境变量<BR>export TSLIB_TSEVENTTYPE=H3600 //通过这个对tslib中的设备结构体定义 <BR>*****************************************************<BR>&nbsp;<BR>如果你触摸屏驱动程序支持ioctl操作，上面的configure操作中的--enable-inputapi=no］你可以删除。<BR>然后就可以make了<BR>&nbsp;<BR>*************************************************<BR>&nbsp;<BR>&nbsp;<BR>2.测试：<BR>2.1 我在/root/share下新建了一个tslib目录,只copy了一些需要的文件 <BR>&nbsp;<BR>mkdir /root/share/tslib<BR>&nbsp;<BR>mkdir /root/share/tslib/tests<BR>&nbsp;<BR>mkdir /root/share/tslib/plugins<BR>&nbsp;<BR>mkdir /root/share/tslib/lib<BR>&nbsp;<BR>mkdir /root/share/tslib/etc<BR>&nbsp;<BR>&nbsp;<BR>cp /root/2410s/tslib-1.3/tests/.libs/ts_* /root/share/tslib/tests/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //几个所需的测试文件，比如生成的校准文件，测试文件等等<BR>&nbsp;&nbsp; <BR>cp /root/2410s/tslib-1.3/src/.libs/libts-0.0.so.0* /root/share/tslib/lib/&nbsp;&nbsp;&nbsp; //几个所需的库文件<BR>&nbsp; <BR>cp /root/2410s/tslib-1.3/src/.libs/libts.so /root/share/tslib/lib/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //几个所需的库文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp; <BR>cp /root/2410s/tslib-1.3/plugins/*.so /root/share/tslib/plugins/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //触摸屏插件模块库<BR>&nbsp;<BR>cp /root/2410s/tslib-1.3/etc/ts.conf /root/share/tslib/etc/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //配置文件&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;<BR>&nbsp;<BR>2.2 连接板子<BR>执行minicom<BR>&nbsp;<BR>mount –t nfs –o nolock 192.168.0.155:/root/share /mnt/nfs使板子mount上PC，共享路径/root/share<BR>&nbsp;<BR>2.3 做链接<BR>ln -s /dev/fb/0 /dev/fb0<BR>&nbsp;<BR>//帧缓冲设备板子上为/dev/fb/0,但程序默认为/dev/fb0,所以做了一个链接/dev/fb0到/dev/fb/0<BR>&nbsp;<BR>ln -sf /dev/touchscreen/0raw /dev/ts<BR>&nbsp;<BR>//qtopia要打开/dev/ts,你没有这个文件, 所以 dev下边应该有触摸平的节点, <BR>相当于, qtopia启动要找 /dev/ts, 但是你只有/dev/touchscreen/0raw,<BR>所以你把ts链接到你的触摸屏的文件就可以了!<BR>我得触摸屏设备节点文件为/dev/touchscreen/0raw<BR>&nbsp;所以,建立链接 /dev/ts 到/dev/touchscreen/0raw<BR>（这里要自己针对自己板子具体的文件进行设置，要不然也会报错）<BR>&nbsp;<BR>&nbsp;<BR>2.4 指定环境变量<BR>export QWS_MOUSE_PROTO=TPanel:/dev/touchscreen/0raw<BR>&nbsp;<BR>export T_ROOT=/mnt/nfs/tslib<BR>&nbsp;<BR>export LD_LIBRARY_PATH=$T_ROOT/lib //指定tslib库文件路径<BR>&nbsp;<BR>export TSLIB_CONSOLEDEVICE=none //tslib运行需要的控制台，这里就是LCD屏幕 ,设定控制台设备为none，否则默认为/dev/tty, <BR>&nbsp;<BR>export TSLIB_FBDEVICE=/dev/fb0&nbsp;&nbsp;&nbsp; //指定帧缓冲设备<BR>&nbsp;<BR>export TSLIB_TSDEVICE=/dev/touchscreen/0raw&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<BR></P>
<P>n&gt;指定触摸屏设备节点文件<BR>&nbsp;<BR>export TSLIB_CALIBFILE=$T_ROOT/etc/pointercal&nbsp;&nbsp;&nbsp;&nbsp; //指定触摸屏校准文件pintercal的存放位置<BR>&nbsp;<BR>&nbsp;<BR>********************************************************************<BR>注：qte的/src/kernel/qwsmouse_qws.cpp里面校准文件默认打开是在/etc下面为/etc/pointercal，<BR>可是我得板子的根文件系统为只读，所以我放在/mnt/nfs/tslib/etc下面了，<BR>所以在交叉编译qte的时候需要修改qwsmouse_qws.cpp<BR>**************************************************<BR>&nbsp;<BR>&nbsp;<BR>export TSLIB_CONFFILE=$T_ROOT/etc/ts.conf&nbsp;&nbsp; //指定TSLIB配置文件的位置<BR>&nbsp;<BR>export TSLIB_PLUGINDIR=$T_ROOT/plugins&nbsp;&nbsp;&nbsp; //指定触摸屏插件所在路径<BR>&nbsp;<BR>2.5 校准<BR>运行校准程序校准屏幕（5点校准）<BR>cd $T_ROOT/tests<BR>&nbsp;<BR>./ts_calibrate&nbsp;&nbsp; //板子上陆续出现5个光标，点击完毕后会生成校准文件pintercal存放在$T_ROOT/etc/下面<BR>&nbsp;<BR>********************************************<BR>&nbsp;<BR>ts_calibrate是一个应用程序，在屏幕上画几个按钮，将用户点击后从ts驱动获得的数据和<BR>屏上的坐标位置通过一套算法来获得校准数据写到一个校准文件里。 <BR>******************************************<BR>&nbsp;<BR>&nbsp;<BR>3. 可能遇到的错误分析：<BR>在测试的时候，运行./ts_calibrate又出现了令人十分之郁闷的错误：<BR>ts_config: Success<BR>追查后应该是在打开ts_config中出现了错误（居然报Success，无欲至极）<BR>在网上发现多是这个错误（这是1.4版本的错）：<BR>Couldnt load module input <BR>No raw modules loaded<BR>tsconfig: Success<BR>我没有上面那两行的错误，不过应该是一样的错误原因<BR>&nbsp;<BR>&nbsp;<BR>那么错误就定位在 ts_config 里。并且可以进一步确定是在加载插件模块时出的错<BR>查询了ts_load_module.c这个文件发现网上和自己的不太一样（网上公布的源码是1.4或者是0.1.1的吧）我的是1.3的<BR>我下载了tslib-0.1.1的后重新实验 就发现错误的是这样子的(第一个错误是由ts.conf所决定的)<BR>Couldnt load module pthres <BR>No raw modules loaded<BR>tsconfig: Success<BR>&nbsp;<BR>&nbsp;<BR>阅读了tslib 的原代码，知道了cstdlib 库里的一个函数： getenv <BR>是用来得到指定系统环境变量的值。是为了测试 tslib 是否得到正确的环境变量。<BR>其环境变量默认的值在readme中有注明。<BR>&nbsp;<BR>&nbsp;<BR>加载插件模块时出出错分析：<BR>ts_calibrate会打开ts_config<BR>ts_config函数里首先会读取 tslib 配置文件（ts.conf，由 TSLIB_CONFFILE环境变量指定,在tslib/etc下面），<BR>然后根据这个文件逐个加载插件库<BR>&nbsp;<BR>1.3版本的ts.conf内容为<BR>module mousebuts<BR>moudle variance xlimit=50 ylimit=50 pthreshold=3<BR>moudle dejitter xdelta=1 ydelta=1 pthreshold=3<BR>moudle linear<BR>&nbsp;<BR>&nbsp;<BR>ts_config又会调用ts_load_module加载库。从这个函数里，程序先是得到配置文件中指定加载的模块名，<BR>然后根据模块名构造了一个 so 文件文件名，然后调用了系统函数 dlopen 加载库！<BR>&nbsp;<BR>Linux 下的加载dlopen 类似于 Windows 下动态链接库的函数：dlopen<BR>错误就应该出在构造的库文件名是错误的---其指定的文件不存在<BR>---从而导致 dlopen无法加载。所以才提示找不到文件或目录！<BR>&nbsp;<BR>那么这样就是应该把需要的mousebuts.so variance.so dejitter.so linear.so应该复制到/tslib/plugins中<BR>（上面修正后作了这一步，就可以拉，就不会出现错误拉）<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>**************************************<BR>&nbsp;<BR>这里来谈一谈tslib-1.4,和1.3有一点点不一样，主要是配置文件的差别<BR>一般来说，tsllib-1.4种一个完整的ts.conf配置文件如下所示： <BR>module_raw input <BR>module pthres <BR>module variance delta=30 <BR>module dejitter delta=100 <BR>module linear <BR>&nbsp;<BR>&nbsp;<BR>出现这个错误<BR>Couldnt load module input <BR>No raw modules loaded<BR>tsconfig: Success<BR>&nbsp;<BR>第一行告诉tslib从linux的输入设备读取数据，需要用到input这个模块，也就是plugin目录下的input.so文件，<BR>所以你的TSLIB_PLUGINDIR一定要配置正确，让tslib能够找到模块文件。<BR>其他参数分别控制触摸点的连续下压、变化宽度、轨迹变化和线性校准。 <BR>也是要把其对应的需要的几个库文件复制到/tslib/plugins中<BR>&nbsp;<BR>第二行导致"No raw modules loaded."的原因有两个：<BR>注意：一是你的ts.conf中没有指定module_raw，自带的ts.conf的所有module_raw都被注释掉了，<BR># Uncomment if you wish to use the linux input layer event interface<BR># module_raw input<BR>&nbsp;<BR># Uncomment if you''re using a Sharp Zaurus SL-5500/SL-5000d<BR># module_raw collie<BR>&nbsp;<BR># Uncomment if you''re using a Sharp Zaurus SL-C700/C750/C760/C860<BR># module_raw corgi<BR>&nbsp;<BR># Uncomment if you''re using a device with a UCB1200/1300/1400 TS interface<BR># module_raw ucb1x00<BR>&nbsp;<BR># Uncomment if you''re using an HP iPaq h3600 or similar<BR>#module_raw h3600<BR>&nbsp;<BR># Uncomment if you''re using a Hitachi Webpad<BR># module_raw mk712<BR>&nbsp;<BR># Uncomment if you''re using an IBM Arctic II<BR># module_raw arctic2 <BR>&nbsp;<BR>你应该打开至少一个module_raw选项，有人就选择了input，去掉了它的注释<BR>得到module_raw input<BR>&nbsp;<BR>另一个原因就是你没有正确配置TSLIB_PLUGINDIR，tslib从你指定的目录中没有找到plugin需要的模块文件，<BR>请检查你的路径和文件。<BR>文章出处：<A href="http://www.diybl.com/course/6_system/linux/Linuxjs/20071129/89010_2.html">http://www.diybl.com/course/6_system/linux/Linuxjs/20071129/89010_2.html</A></P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200898102717592</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200898102717592</guid>
    <pubDate>Wed, 8 Oct 2008 22:27:17 +0800</pubDate>
    <dcterms:modified>2008-10-08T22:27:17+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Arm-Linux嵌入式QT/E环境的建立(qt/e 3.x系列)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/920232008979443979</link>
    <description><![CDATA[<div>QT/E 3.x系列比QT/E 2.x系列有非常大的改进，大大提高了开发进度，不再使用tmake,安装也更简单。但目前在网上关于QT/E 3.x系列的介绍还是比较少，所以本文介绍一下QT/E 3.x系列的安装。
<p>一、建立arm交叉编译工具链</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在安装QT/E之前，应确保arm-linux交叉编译工具链已经建立，如果还没有可以参考以下步骤建立。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1、下载交叉编译工具cross-2.95.3.tar.bz2(或其他版本如:cross-3.4.4.tar.bz2),这是已经制作好的arm交叉编译工具链，只需解压及建交环境变量即可使用。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 2、把文件cross-2.95.3.tar.bz2拷贝到一个文件夹，这里我用：/usr/local/arm这个目录。 注意后面建立环境变量时要与之对应。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、解压 tar&nbsp; &nbsp;-xjvf&nbsp;&nbsp;&nbsp; cross-2.95.3.tar.bz2</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、建立环境变量 export&nbsp;&nbsp;&nbsp; PATH=/usr/local/arm/2.95.3/bin:$PATH</p>
<p>或者也可以写进文件 ~/.bashrc中，这样就不用每次开机都export啦。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vi&nbsp;&nbsp;&nbsp;&nbsp; ~/.bashrc</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在后面加上 export&nbsp;&nbsp;&nbsp; PATH=/usr/local/arm/2.95.3/bin:$PATH</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 到此arm-linux交叉编译工具链就已经建好了。</p>
<p>二、编译QT</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、QT/E自由版可到官网ftp下载。网址是：<a href="ftp://ftp.trolltech.com/qt/source/">ftp://ftp.trolltech.com/qt/source/</a>&nbsp;。
可自己选择一个版本下载，个人认为QT/E 3.x系列比较好用，不过QT/E 2.x系列在网上的资料比较多。但建议不用qt/e 3.3.x
的版本，因为在本人开发的过程当中试用过qt/e 3.3.4和qt/e3.3.8，发现它们在ARM开发板上占CPU的资源特高，一直占cpu
98%左右，现在我还没找到原因，不知道有没有哪位朋友也遇到这个问题。推荐用qt/e 3.1.0版本，我正在用，没遇到什么问题。</p>
<p>(注：问题已经得到解决，原来是键盘接口没做好，等有空与大家分享一下移植键盘接口的过程) </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、在这里，本人假设用的是 qt-embedded-free-3.1.0.tar.bz2 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、把文件qt-embedded-free-3.1.0.tar.bz2 拷贝到一个文件夹，这里我用：/usr/local/arm这个目录。 注意后面建立环境变量时要与之对应。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、解压 tar&nbsp;&nbsp; -xjvf&nbsp;&nbsp; qt-embedded-free-3.1.0.tar.bz2&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把解压后的文件夹qt-embedded-free-3.1.0改为qte。（可以不改，这里是为了方便，注意后面建立环境变量时要与之对应）&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; mv&nbsp;&nbsp;&nbsp;&nbsp; qt-embedded-free-3.1.0&nbsp;&nbsp;&nbsp;&nbsp; qte</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5、建立环境变量</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;vi&nbsp;&nbsp;&nbsp;&nbsp; ~/.bashrc</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在后面加上</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;export QTDIR=/usr/local/arm/qte<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;export QTEDIR=$QTDIR<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; export PATH=$QTDIR/bin:$PATH<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （请重新登陆，以使得环境变量生效）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6、配置QT</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进入QT/E目录:&nbsp;&nbsp;&nbsp;&nbsp; cd&nbsp; &nbsp; $QTDIR</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;输入:&nbsp;&nbsp; ./configure &nbsp;-embedded&nbsp; arm&nbsp;&nbsp; -thread&nbsp; -no-cups -qvfb -depths 4,8,16,32</p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上述选项： -embedded&nbsp; arm 指目标平台为arm； -thread
表示支持qt线程，本人开发当中用到； -qvfb 表示支持虚拟缓冲帧工具qvfb；-depths 4,8,16,32
表示支持4，8，16，32 位的显示颜色深度。还有很多选项就不一一列举，请查看 ./configure&nbsp; -help。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此外还有一个选项我没用的是 -qconfig
&nbsp;local，你可以把一些开关变量写到一个文件qconfig-local.h
中，并把它放到$QTDIR/src/tools下。可参考这个目录下的qconfig-small.h、qconfig-medium.h
、qconfig-large.h等文件，直接使用它们也行，如：&nbsp; -qconfig&nbsp;
small&nbsp;。通过这些开关变量，可以把一些开发当中用不着的构件去掉，减少qt库的大小。这里要对QT比较熟练，初学者可先不理。</p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （本人在家里编译到这里曾出现编译 $QTDIR/include/qvaluestack.h 这个文件的时候出错，后来把qt3.3.8对应的文件拷贝过来覆盖便通过了，估计是与gcc的版本不兼容的问题，我在公司里没出现过这种问题）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7、编译</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make sub-src&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;指定按精简方式编译开发包，也就是说有些Qt 类未被编<br>译。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8、测试</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至此编译工作完成，最后测试一下是否能正常使用。我们可以用QT自带的例子来测试，如:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd&nbsp; $QTDIR/examples/aclock&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //或你自己新建一个QT工程也行</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make clean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //把原来的清掉</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rm&nbsp;&nbsp;&nbsp; *.pro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Makefile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //删掉，重新建立工程文件</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qmake&nbsp;&nbsp; -project</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qmake&nbsp;&nbsp; -spec&nbsp; $QTDIR/mkspecs/qws/linux-arm-g++&nbsp; &nbsp;-o&nbsp; Makefile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -spec指定目标板的配置文件，这里我做的是linux
arm平台，注意在这里，$QTDIR/mkspecs/qws/linux-arm-g++&nbsp;它不是编译器，是一个配置文件，而编译时用的编译器是我们
在第一步建立的arm交叉编译工具链里面的编译器。&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果没出错就表示你的QT/E环境已经成功建立。如果提示说cannot&nbsp;&nbsp; find&nbsp;&nbsp; -lqte，
那么你试一下修改Makefile文件，找到-lqte
,把它改为-lqte-mt再make一次一般就行了。这是因为如果用到QT线程或其它一些原因，它生成的库不再是libqte.so.3.1.0，而是
libqte-mt.so.3.1.0，所以它便找不到了。</p>
<p>三、移植到开发板（以下都是在目标机环境下）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、新建一个目录，如：/qt/lib。进入此目录 cd&nbsp;&nbsp; /qt/lib</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、通过 ftp&nbsp; 把上面生成的qt库文件libqte-mt.so.3.1.0下载到开发板/qt/lib/目录下。（注意：不要用wget 下载，会破坏库文件，从而出现&nbsp; <font size="2"><font color="#c60a00">ld.so</font>: dynamic-<font color="#c60a00">link</font>.h:
62: elf_get_dynamic_info: Assertion `! "bad dynamic
tag"''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
failed!.这种错误</font>）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、创建qt库连接：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ln&nbsp;&nbsp; -s&nbsp; &nbsp;libqte-mt.so.3.1.0&nbsp;&nbsp;&nbsp;&nbsp; libqte-mt.so</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ln&nbsp;&nbsp; -s&nbsp;&nbsp; libqte-mt.so.3.1.0&nbsp;&nbsp;&nbsp;&nbsp; libqte-mt.so.3</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ln&nbsp;&nbsp; -s&nbsp;&nbsp; libqte-mt.so.3.1.0&nbsp;&nbsp;&nbsp;&nbsp; libqte-mt.so.3.1</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、建立环境变量</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;vi&nbsp;&nbsp;&nbsp;&nbsp; ~/.bashrc</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在后面加上</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;export QTDIR=/qt<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;export QTEDIR=$QTDIR<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、到此目标板的环境已经建好。现在可以把上面的例子aclock下载到目标板上试一下能不能跑起来！</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在开发板控制台下输入:&nbsp; ./aclock&nbsp; -qws&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果能跑起来但是键盘用不了，那是正常的情况，因为键盘、鼠标等设备的接口还没加进QT/E的原因，而这个不是一两句话能说清的，所以留到以后再另外补充！</p>
补充一点:如果有类似这样的提示:&nbsp; "./aclock: error while loading shared libraries:
libstdc++.so.6: cannot load shared object file: No such file or
directory."
你可以从我们第一步建立的arm交叉编译工具链里的/usr/local/arm/2.95.3/arm-linux/lib/目录下找到相应的库文件下
载到开发板的 /lib 目录下即可。</div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/920232008979443979</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/920232008979443979</guid>
    <pubDate>Tue, 7 Oct 2008 21:04:43 +0800</pubDate>
    <dcterms:modified>2008-10-07T21:04:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[ARM的嵌入式Linux移植体验之操作系统]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320089751411974</link>
    <description><![CDATA[<div><P>　　4.文件系统移植</P>
<P>　　文件系统是基于被划分的存储设备上的逻辑上单位上的一种定义文件的命名、存储、组织及取出的方法。如果一个Linux没有根文件系统，它是不能被正确的启动的。因此，我们需要为Linux创建根文件系统，我们将其创建在K9S1208 NAND FLASH上。</P>
<P>　　Linux的根文件系统可能包括如下目录（或更多的目录）：</P>
<P>　　（1）/bin (binary)：包含着所有的标准命令和应用程序； </P>
<P>　　（2）/dev (device)：包含外设的文件接口，在Linux下，文件和设备采用同种地方法访问的，系统上的每个设备都在/dev里有一个对应的设备文件；</P>
<P>　　（3）/etc (etcetera)：这个目录包含着系统设置文件和其他的系统文件，例如/etc/fstab(file system table)记录了启动时要mount 的filesystem；</P>
<P>　　（4）/home：存放用户主目录；</P>
<P>　　（5）/lib(library)：存放系统最基本的库文件；</P>
<P>　　（6）/mnt：用户临时挂载文件系统的地方；</P>
<P>　　（7）/proc：linux提供的一个虚拟系统，系统启动时在内存中产生，用户可以直接通过访问这些文件来获得系统信息； </P>
<P>　　（8）/root：超级用户主目录；</P>
<P>　　（9）/sbin：这个目录存放着系统管理程序，如fsck、mount等；</P>
<P>　　（10）/tmp(temporary)：存放不同的程序执行时产生的临时文件；</P>
<P>　　（11）/usr(user)：存放用户应用程序和文件。</P>
<P>　　采用BusyBox是缩小根文件系统的好办法，因为其中提供了系统的许多基本指令但是其体积很小。众所周知，瑞士军刀以其小巧轻便、功能众多而闻名世界，成为各国军人的必备工具，并广泛应用于民间，而BusyBox也被称为嵌入式Linux领域的"瑞士军刀"。</P>
<P>　　此地址可以下载BusyBox：<A href="http://www.busybox.net">http://www.busybox.net</A>，当前最新版本为1.1.3。编译好busybox后，将其放入/bin目录，若要使用其中的命令，只需要建立link，如：</P>
<P>ln -s ./busybox ls<BR>ln -s ./busybox mkdir</P>
<P>　　4.1 cramfs</P>
<P>　　在根文件系统中，为保护系统的基本设置不被更改，可以采用cramfs格式，它是一种只读的闪存文件系统。制作cramfs文件系统的方法为：建立一个目录，将需要放到文件系统的文件copy到这个目录，运行"mkcramfs 目录名 image名"就可以生成一个cramfs文件系统的image文件。例如如果目录名为rootfs，则正确的命令为：</P>
<P>mkcramfs rootfs rootfs.ramfs</P>
<P>　　我们使用下面的命令可以mount生成的rootfs.ramfs文件，并查看其中的内容：</P>
<P>mount -o loop -t cramfs rootfs.ramfs /mount/point</P>
<P>　　此地址可以下载mkcramfs工具：<A href="http://sourceforge.net/projects/cramfs/">http://sourceforge.net/projects/cramfs/</A>。</P>
<P>　　4.2 jfss2</P>
<P>　　对于cramfs闪存文件系统，如果没有ramfs的支持则只能读，而采用jfss2（The Journalling Flash File System version 2）文件系统则可以直接在闪存中读、写数据。jfss2 是一个日志结构(log-structured)的文件系统，包含数据和原数据(meta-data)的节点在闪存上顺序地存储。jfss2记录了每个擦写块的擦写次数，当闪存上各个擦写块的擦写次数的差距超过某个预定的阀值，开始进行磨损平衡的调整。调整的策略是，在垃圾回收时将擦写次数小的擦写块上的数据迁移到擦写次数大的擦写块上以达到磨损平衡的目的。 </P>
<P>　　与mkcramfs类似，同样有一个mkfs.jffs2工具可以将一个目录制作为jffs2文件系统。假设把/bin目录制作为jffs2文件系统，需要运行的命令为：</P>
<P>mkfs.jffs2 -d /bin -o jffs2.img</P>
<P>　　4.3 yaffs</P>
<P>　　yaffs 是一种专门为嵌入式系统中常用的闪存设备设计的一种可读写的文件系统，它比jffs2 文件系统具有更快的启动速度，对闪存使用寿命有更好的保护机制。为使Linux支持yaffs文件系统，我们需要将其对应的驱动加入到内核中fs/yaffs/，并修改内核配置文件。使用我们使用mkyaffs工具可以将NAND FLASH中的分区格式化为yaffs格式（如/bin/mkyaffs /dev/mtdblock/0命令可以将第1个MTD块设备分区格式化为yaffs），而使用mkyaffsimage（类似于mkcramfs、mkfs.jffs2）则可以将某目录生成为yaffs文件系统镜像。</P>
<P>　　嵌入式Linux还可以使用NFS（网络文件系统）通过以太网挂接根文件系统，这是一种经常用来作为调试使用的文件系统启动方式。通过网络挂接的根文件系统，可以在主机上生成ARM 交叉编译版本的目标文件或二进制可执行文件，然后就可以直接装载或执行它，而不用频繁地写入flash。</P>
<P>　　采用不同的文件系统启动时，要注意通过第二章介绍的BootLoader修改启动参数，如广州友善之臂的demo提供如下三种启动方式：</P>
<P>　　（1）从cramfs挂接根文件系统：root=/dev/bon/2()； <BR>　　 <BR>　　（2）从移植的yaffs挂接根文件系统：root=/dev/mtdblock/0；</P>
<P>　　（3）从以太网挂接根文件系统：root=/dev/nfs。</P>
<P>　　5.小结</P>
<P>　　本章介绍了嵌入式Linux的背景、移植项目、init进程修改和文件系统移植，通过这些步骤，我们可以在嵌入式系统上启动一个基本的Linux。</P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320089751411974</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320089751411974</guid>
    <pubDate>Tue, 7 Oct 2008 17:14:11 +0800</pubDate>
    <dcterms:modified>2008-10-07T17:14:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Qt各个版本的介绍]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320089643617565</link>
    <description><![CDATA[<div>网上找到的两个介绍<br>1.关于Qt，Qt/E，Qtopia Core, Qtopia这些版本之间的区别和联系，似乎没有看到一个比较有价值的讨论，本人现在总结一下个人的理解：<br><br>　　Qt泛指Qt的所有桌面版本，比如Qt/X11，Qt Windows，Qt Mac等。由于Qt最早是在Linux中随着KDE流行开来的，因此通常很多人说的Qt都指用于Linux/Unix的Qt/X11。<br><br>　　Qt/E（Qt/Embedded）是用于嵌入式Linux系统的Qt版本。Qt/E去掉了X Lib的依赖而直接工作于Frame Buffer上，因而效率更高，但它并不是Qt的子集，而应该是超集，部分机制（如QCOP等）不能用于Qt/X11中。<br><br>　　Qtopia是一个构建于Qt/E之上的类似桌面系统的应用环境，目前看来就是Qtopia Phone Editon(QPE)。相比之下，Qt/E是基础类库。<br><br>　　Qtopia Core：就是原来的Qt/E，大概从Qt 4开始改名，把Qtopia Core并到Qtopia的产品线中去了。但实际上Qtopia Core就相当于原来的Qt/E，仍然作为基础类库。<br><br>　　另外，似乎奇趣最近又把Qtopia Core改名叫做Qt for Embedded Linux了，不知道是不是因为Qtopia Core搞得大家都很糊涂，没人来买的缘故。 <br><br><br>2.Qt/Embedded <br>Qt/Embedded是Qt的嵌入式版本，他在原始Qt的基础上，做了许多出色的调整以适合嵌入式环境。同Qt/X11相比，<br>Qt/Embedded很节省内存，因为他无需X<br>server或是Xlib库，他在底层摒弃了Xlib，采用framebuffer作为底层图像接口。Qt/Embedded的应用程式能够直接写内核帧<br>缓冲，因此他在嵌入式linux系统上的应用很广泛。 <br>最后再了解下Qtopia<br>在Qt/Embedded版本4之前，Qt/Embedded和Qtopia是两套不同的程式，Qt/Embedded是基础类库，Qtopia<br>是构建于Qt/Embedded之上的一系列应用程式。但从版本4开始，Trolltech将Qt/Embedded并入了Qtopia，并推出了新的<br>Qtopia4。在该版中，原来的Qt/Embedded被称为Qtopia<br>Core，作为嵌入式版本的核心，既能够和Qtopia配合，也能够单独使用。原来的Qtopia则被分成几层，核心的应用框架和插件系统被称为<br>Qtopia Platform，上层的应用程式则按照不同的目标用户分为不同的包，如Qtopai PDA，Qtopia Phone等。 <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>trolltech.com我到现在就没能打开过，长什么样都不知道</div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320089643617565</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320089643617565</guid>
    <pubDate>Mon, 6 Oct 2008 16:36:17 +0800</pubDate>
    <dcterms:modified>2008-10-06T16:36:17+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Qt的移植（转载）]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/920232008947444796</link>
    <description><![CDATA[<div><P>HOST主机&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp; Red Hat 9 完全安装<BR>交叉编译器&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp; freescale提供的arm-926ejs-linux 版本 gcc-4.1.1-glibc-2.4-nptl-sf-1<BR>需要用到的软件包 :&nbsp; tmake-1.13.tar.gz&nbsp;&nbsp; qt-x11-2.3.2.tar.gz&nbsp;&nbsp;&nbsp; qt-embedded-2.3.10-free.tar.gz</P>
<P>一. 安装与建立Qt 桌面运行环境</P>
<P>第一步，解压安装包并设置环境变量<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tar –xzvf tmake-1.13.tar.gz<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tar –xzvf qt-x11-2.3.2.tar.gz<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tar –xzvf&nbsp; qt-embedded-2.3.10-free.tar.gz<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mv&nbsp; qt-2.3.10 qt-2.3.10-host<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export TMAKEDIR=$PWD/tmake-1.13<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QT2DIR=$PWD/qt-2.3.2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTEDIR=$PWD/qt-2.3.10-host</P>
<P>&nbsp;环境变量的设置是非常重要的，它关系到能否正确的安装及编译这些安装包.<BR>&nbsp;<BR>&nbsp;注意: 在以下安装中,make命令执行前先执行一下make clean命令.</P>
<P>第二步，编译Qt/Embedded</P>
<P>1. Build Qt2.3.2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd $QT2DIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export TMAKEPATH=$TMAKEDIR/lib/linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTDIR=$QT2DIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export PATH=$QTDIR/bin:$PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make clean<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./configure -no-xft<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mkdir $QTEDIR/bin<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp bin/uic $QTEDIR/bin/</P>
<P><BR>&nbsp;2. Build Qvfb<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export TMAKEPATH=$TMAKEDIR/lib/linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTDIR=$QT2DIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export PATH=$QTDIR/bin:$PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd $QTEDIR/tools/qvfb<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make&nbsp; clean<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmake -o Makefile qvfb.pro<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mv qvfb $QTEDIR/bin/</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这一步build qvfb 并建立了从Qt/Embedded 2.3.10 到Qt 2.3.2 的静态库的链接。其中qvfb 工具用来生成Virtual framebuffer，这是一个非常有用的工具，它可以模拟在开发板上的显示情况，如果在Virtual framebuffer 中运行没有问题的话，可以直接通过交叉编译在开发板上运行。</P>
<P><BR>&nbsp;3. Build Qt/Embedded<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd $QTEDIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export TMAKEPATH=$TMAKEDIR/lib/qws/linux-x86-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTDIR=$QTEDIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export PATH=$QTDIR/bin:$PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make clean<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./configure -no-xft -qvfb -depths 4,8,16,32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此时我选择的5<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make<BR>&nbsp;<BR>第三步，查看运行结果<BR>&nbsp;&nbsp;&nbsp;&nbsp; 如果上面各步都能够成功的编译通过，下面就可以通过运行Qt/Embedded 自带的demo 来查看运行结果。</P>
<P>&nbsp; 在Virtual framebuffer 上运行：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTDIR=$QTEDIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export PATH=$QTEDIR/bin:$PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export LD_LIBRARY_PATH=$QTEDIR/lib:$QT2DIR/lib:$LD_LIBRARY_PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd $QTEDIR/examples/launcher<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qvfb -width 640 -height 480 &amp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep 10<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./launcher -qws</P>
<P><BR>二&nbsp; Qt/E 的交叉编译</P>
<P><BR>&nbsp;1. Build Qt/Embedded<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tar –xzvf qt-embedded-2.3.10-free.tar.gz<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mv&nbsp; qt-2.3.10&nbsp; qt-2.3.10-target<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export PATH=/opt/freescale/usr/local/gcc-4.1.1-glibc-2.4-nptl-sf-1/arm-926ejs-linux/bin:$PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export TMAKEDIR=$PWD/tmake-1.13<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QT2DIR=$PWD/qt-2.3.2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTEDIR=$PWD/qt-2.3.10-target<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cd $QTEDIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export TMAKEPATH=$TMAKEDIR/lib/qws/linux-arm-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export QTDIR=$QTEDIR<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export PATH=$QTDIR/bin:$PATH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH<BR>&nbsp; <BR>&nbsp; 修改tmake配置文件及qt-embedded配置</P>
<P>&nbsp;&nbsp; vi $TMAKEDIR/lib/qws/linux-arm-g++/tmake.conf<BR>&nbsp;&nbsp;&nbsp; 将&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_CXX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_LINK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_LINK_SHLIB&nbsp; = arm-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_AR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-ar cqs<BR>&nbsp;&nbsp;&nbsp; 改为<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_CXX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_LINK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_LINK_SHLIB&nbsp; = arm-926ejs-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; TMAKE_AR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-ar cqs</P>
<P>&nbsp;&nbsp; vi $QTEDIR/configs/linux-arm-g++-shared<BR>&nbsp;&nbsp;&nbsp; 将<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_CXX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_LINK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_LINK_SHLIB&nbsp; = arm-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_AR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-linux-ar cqs<BR>&nbsp;&nbsp;&nbsp; 改为<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_CXX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-gcc<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_LINK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_LINK_SHLIB&nbsp; = arm-926ejs-linux-g++<BR>&nbsp;&nbsp;&nbsp;&nbsp; SYSCONF_AR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = arm-926ejs-linux-ar cqs<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; vi $QTEDIR/configs/linux-arm-g++-shared-debug<BR>&nbsp;&nbsp; vi $QTEDIR/configs/linux-arm-g++-static<BR>&nbsp;&nbsp; vi $QTEDIR/configs/linux-arm-g++-static-debug<BR>&nbsp;&nbsp; 这三个文件修改的地方同$QTEDIR/configs/linux-arm-g++-shared相同</P>
<P>&nbsp; make clean<BR>&nbsp; ./configure -xplatform linux-arm-g++ -no-xft -no-qvfb -depths 4,8,16,32<BR>&nbsp; make</P>
<P>/**********************************************************************************************************************/<BR>&nbsp; 出现错误：<BR>&nbsp;&nbsp;&nbsp; error: ‘QWSInputMethod’ has not been declared<BR>&nbsp; <BR>&nbsp; 修改方法：<BR>&nbsp;&nbsp;&nbsp; cd $QTDIR/src/kernel<BR>&nbsp;&nbsp;&nbsp; vim qwindowsystem_qws.h</P>
<P>&nbsp;&nbsp;&nbsp; 在前面增加以下两行</P>
<P>&nbsp;&nbsp;&nbsp; class QWSInputMethod;<BR>&nbsp;&nbsp;&nbsp; class QWSGestureMethod;</P>
<P>/**********************************************************************************************************************/<BR>&nbsp; <BR>&nbsp; 出现错误：<BR>&nbsp;&nbsp;&nbsp; qvaluestack.h:57: 错误：不能从 ‘QValueListIterator&lt;QString&gt;’ 转换到 ‘const char*’，为实参 ‘1’(属于 ‘int remove(const char*)’)</P>
<P>&nbsp; 修改方法：<BR>&nbsp;&nbsp;&nbsp; vim $QTDIR/include/qvaluestack.h</P>
<P>&nbsp;&nbsp;&nbsp; 将remove( this-&gt;fromLast() );改为this-&gt;remove( this-&gt;fromLast() );</P>
<P>/**********************************************************************************************************************/</P>
<P>&nbsp;这两个错误是由于编译器的版本太高导致的<BR>&nbsp;&nbsp; <BR>&nbsp;交叉编译成功！！&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哈哈</P>
<P>&nbsp;</P>
<P>三 在ARM上运行</P>
<P>&nbsp;1. 编译在arm上运行程序时需要的环境变量<BR>&nbsp; <BR>&nbsp; export TMAKEDIR=/work/tmake-1.13<BR>&nbsp; export TMAKEPATH=$TMAKEDIR/lib/qws/linux-arm-g++<BR>&nbsp; export PATH=/opt/freescale/usr/local/gcc-4.1.1-glibc-2.4-nptl-sf-1/arm-926ejs-linux/bin:$PATH<BR>&nbsp; export QTEDIR=/work/qt-2.3.10-target<BR>&nbsp; export QTDIR=$QTEDIR </P>
<P>&nbsp;</P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/920232008947444796</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/920232008947444796</guid>
    <pubDate>Sat, 4 Oct 2008 19:04:44 +0800</pubDate>
    <dcterms:modified>2008-10-04T19:04:44+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[qtopia-2.2.0移植到ARM上(转载)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/920232008944580190</link>
    <description><![CDATA[<div><P>一、开发Qtopia的所需的工具<BR>整个GUI系统的构建需要对Qt/Embedded、Qtopia依次分别编链，然后有机地整合在一起。Qt/Embedded为Qtopia提供 <BR>了底层支持，GUI系统的图形库窗口组建都由Qt/Embedded实现。<BR>在构建GUI时用于Qt开发的典型工具如下：<BR>tmake：跨平台的Makefile生成器。<BR>moc：用于Qt C++扩展的metra-object编译器。<BR>uic：uic是for x86的文件，从XML文件生成代码的用户界面编译器。即uic用来把.ui文件转换成.h和.cpp文件。<BR>designer：用于设计窗口组建的应用程序。<BR>Qtopia的开发工具包SDK（Software Development Kit）是Qtopia开发环境的核心部分，编译后得到创建应用程序所 <BR>需的软件包如下：<BR>qvfb(virtual frame buffer)：X窗口用来运行和测试Qtopia应用程序的系统程序 。<BR>qpe(Qtopia executable)：是Trolltech公司所推出的针对PDA软件的整体解决方案，包含了从底层的GUI系统、 <BR>Window Manager、Soft Keyboard到上层的PIM、浏览器、多媒体等方面，用来处理所有的用户程序界面。 </P>
<P>二、交叉编译qtopia的过程<BR>1、编译qtopia的准备工作<BR>1.1、所需的软件压缩包：<BR>cross-2.95.3.tar.bz2,<BR>e2fsprogs-1.39.tar.gz.tar.gz，<BR>jpegsrc.v6b.tar.gz，<BR>libpng-1.2.18.tar.bz2，<BR>zlib-1.2.3.tar.bz2,<BR>qtopia-free-src-2.2.0.tar.gz<BR>1.2、建立所需目录<BR>/---usr ---/local/arm<BR>/---root---/yizhi<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /armlib<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /arminclude<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /qtopia-free-2.2.0<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /libpng-1.2.18<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /zlib-1.2.3<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /e2fsprogs-1.39<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /jpeg-6b<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /qt-2.3.10<BR>.&nbsp; .&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp; /host/qtopia-free-2.2.0<BR>1.3、各个目录的功能作用：<BR>arm：存放PC机上交叉编译的工具<BR>yizhi：下载的软件包全部存放到这里<BR>armlib：编译软件得到qtopia所需要的库文件全部放在这里<BR>arminclude：编译软件得到qtopia所需要的头文件全部放在这里<BR>qtopia-free-2.2.0：qtopia的源代码<BR>jpeg-6b：一个jpeg图形编码解码程序库<BR>libpng-1.2.18：一个png图形编码解码程序库<BR>zlib-1.2.3：一个压缩解压程序库<BR>e2fsprogs-1.39：可以提供uuid支持<BR>qt-2.3.10：qt-embeddedd的文件夹路径<BR>host/qtopia-free-2.2.0：qtopia的源代码<BR>2、编译QTOPIA所依赖的库文件<BR>2.1、安装交叉编译工具<BR>将cross-2.95.3.tar.bz2放到/usr/local/arm文件夹下解压，<BR># tar –zxvf cross-2.95.3.tar.bz2<BR>这个命令会在你的/usr/local/arm/2.95.3目录下安装 arm-linux-gcc 交叉编译程序，然后在PATH变量中添加一项 <BR>：<BR>export PATH=/usr/local/arm/2.95.3/bin:$PATH<BR>测试<BR># arm-linux-gcc -v<BR>2.2、得到本机运行的uic工具<BR>qtopia-2.2.0版本里面集成了qt\tmake\qtopia。<BR>编译Qt/X11的唯一目的就是为编译QTE提供uic（用户接口编译器）以及基于X Windows系统的FrameBuffer设备模拟 <BR>器qvfb。<BR>解压qtopia-free-src-2.2.0.tar.gz,将qtopia-free-2.2.0复制到 /root/yizhi/host<BR># cd /root/host/qtopia-free-2.2.0<BR>要生成Makefile<BR># ./configure<BR># make<BR>解压qtopia-free-src-2.2.0.tar.gz 将其复制至 /root/yizhi/&nbsp;&nbsp; <BR># cp /root/yizhi/host/qtopia-free-2.2.0/qt2/bin/uic /root/yizhi/qtopia-free-2.2.0/qt2/bin/<BR>2.3、编译e2fsprogs-1.39<BR>要得到qtopia 所需的二個文件，uuid.h 及 libuuid.so。<BR># cd /root/yizhi/e2fsprogs-1.39<BR>设置环境变量<BR># export PATH=/usr/local/arm/2.95.3/bin:$PATH<BR># export CC= /usr/local/arm/2.95.3/bin/arm-linux-gcc<BR># ./configure --enable-elf-shlibs --host=arm-linux<BR>&nbsp;--with-cc=/usr/local/arm/2.95.3/bin/arm-linux-gcc<BR>&nbsp;--with-linker=/usr/local/arm/2.95.3/bin/arm-linux-ld<BR>&nbsp;--prefix=/usr/local/arm/2.95.3/arm-linux<BR># make<BR>将e2fsprogs-1.39/lib/目录下uuid的文件夹复制到yizhi/arminclude下<BR># cp -r /lib/uuid /root/yizhi/arminclude<BR># cp lib/libuuid.so* /root/yizhi/armlib /<BR>2.4、交叉编译jpeg库<BR>解压jpegsrc.v6b.tar.gz到/root/yizhi<BR># cd jpeg-6b<BR>设置环境变量<BR># export QTDIR=/root/yizhi/qtopia-free-2.2.0/<BR># export QTEDIR=/root/yizhi/qtopia-free-2.2.0/qtopia/<BR># export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH<BR># export PATH=/usr/local/arm/2.95.3/bin:$PATH<BR># export CC= /usr/local/arm/2.95.3/bin/arm-linux-gcc<BR># ./configure --enable-shared<BR>修改生成的Makefile文件<BR>prefix = /root/yizhi/qt-2.3.10<BR>CC= /usr/local/arm/2.95.3/bin/arm-linux-gcc<BR>AR= /usr/local/arm/2.95.3/bin/arm-linux-ar rc<BR>AR2= /usr/local/arm/2.95.3/bin/arm-linux-ranlib <BR>保存<BR># cp jconfig.doc jconfig.h<BR>在你的qt-embedded中建立man/man1文件夹,否则安装jpeg库时会出错<BR># mkdir -p qt-2.3.10/man/man1 <BR>最后<BR># make<BR># make install –lib<BR>报错,但是在/root/2410s/qt-2.3.10-arm/lib目录下生成了文件夹fonts和libjpeg.so*<BR># cp jpeglib.h /root/yizhi/arminclude<BR># cp lib/libjpeg.so* /yizhi/yizhi/armlib<BR>就可以给qt-embedded添加好for arm的libjpeg库放到交叉编译的Lib一份<BR># cp lib/libuuid.so* /usr/local/arm/2.95.3/arm-linux/lib<BR>2.5、编译libpng库<BR>将libpng-1.2.18.tar.bz2解压到/root/yizhi目录下<BR># cd /root/yizhi/libpng-1.2.18<BR># cp&nbsp; scripts/makefile.linux&nbsp; ./Makefile<BR>注意，这里的makefile不是用./configure生成，而是直接从scripts/里拷一个<BR># vi Makefile<BR>修改:<BR>[begin]<BR>&nbsp;...<BR>AR_RC=/usr/local/arm/2.95.3/bin/arm-linux-ar rc<BR>CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc<BR>RANLIB=/usr/local/arm/2.95.3/bin/arm-linux-ranlib<BR>prefix=/usr/local/arm/2.95.3/arm-linux<BR>&nbsp;...<BR>[end]<BR>保存<BR># make<BR># cp libpng12.so*&nbsp; /root/yizhi/armlib<BR># cp *.h /root/yizhi/arminclude<BR>2.6、编译zlib<BR># cd /root/yizhi/zlib-1.2.3<BR>设置环境变量<BR># export PATH=/usr/local/arm/2.95.3/bin:$PATH<BR># export LD_LIBRARY_PATH= /usr/local/arm/2.95.3/arm-linux/lib:$LD_LIBRARY_PATH<BR># export CC= /usr/local/arm/2.95.3/bin/arm-linux-gcc<BR># ./configure –shared<BR># vi Makefile<BR>修改:<BR>[begin]<BR>CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc<BR>&nbsp;...<BR>LDSHARED=/usr/local/arm/2.95.3/bin/arm-linux-gcc -shared-Wl,-soname,libz.so.1<BR>CPP=/usr/local/arm/2.95.3/bin/arm-linux-gcc -E&nbsp;&nbsp; <BR>&nbsp;...<BR>AR=/usr/local/arm/2.95.3/bin/arm-linux-ar rc<BR>RANLIB=/usr/local/arm/2.95.3/bin/arm-linux-ranlib<BR>&nbsp;...<BR>prefix =/usr/local/arm/2.95.3/arm-linux<BR>&nbsp;...<BR>[end]<BR>保存<BR># make<BR>将编译生成的动态库及相关的头文件分别复制到armlib和arminclude目录下<BR># cp libz.so* /root/yizhi/armlib<BR># cp *.h /root/yizhi/arminclude <BR>3、交叉编译qtopia<BR>3.1、编译修改工作<BR>①、vi /root/yizhi/qtopia-free-2.2.0/qtopia/mkspecs/qws<BR>/linux-arm-g++/qmake.conf<BR>将此行<BR>QMAKE_LIBS_QT = -lqte<BR>修改为<BR>QMAKE_LIBS_QT = -lqte -lpng -lz -luuid -ljpeg<BR>②、 如果想让Qtopia支持鼠标，需要修改$QPEDIR/src/qt/qconfig-qpe.h文件<BR>注释如下部分<BR>/*<BR>#ifndef QT_NO_QWS_CURSOR<BR>#define QT_NO_QWS_CURSOR<BR>#endif<BR>#ifndef QT_NO_QWS_MOUSE_AUTO<BR>#define QT_NO_QWS_MOUSE_AUTO<BR>#endif<BR>#ifndef QT_NO_QWS_MOUSE_PC<BR>#define QT_NO_QWS</P>
<P>_MOUSE_PC<BR>#endif<BR>*/<BR>③、# cp /root/yuzhi/qtopia-free-2.2.0/qtopia/src/qt/Qconfig-qpe.h<BR>/root/yizhi/qtopia-free-2.2.0/qt2/src/tools<BR># cd $QPEDIR/src/libraries/qtopia<BR># cp custom-linux-ipaq-g++.cpp custom-linux-arm-g++.cpp<BR># cp custom-linux-ipaq-g++.h custom-linux-arm-g++.h<BR>④、将/usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3/../../<BR>../../arm-linux/sys-include/linux/videodev.h文件中的#include&lt;linux/<BR>version.h&gt;一行屏蔽<BR>3.2、设置环境变量，编译及安装<BR>①设置编译qtopia的环境变量<BR># export QTDIR=/root/yizhi/qtopia-free-2.2.0/qt2<BR># export QPEDIR=/root/yizhi/qtopia-free-2.2.0/qtopia<BR># export LD_LIBRARY_PATH=$QTDIR/lib:$QPEDIR/lib:$LD_LIBRARY_PATH<BR># export TMAKEDIR=/root/yizhi/qtopia-free-2.2.0/tmake<BR># export TMAKEPATH=$TMAKEDIR/lib/qws/linux-arm-g++<BR># export PATH=/usr/local/arm/2.95.3/bin:$PATH<BR>②创建交叉编译后的qtopia文件夹<BR># mkdir /root/yizhi/qtopia<BR>③生成Makefile文件（注释2）<BR># ./configure -qte "-embedded -xplatform linux-arm-g++ -qconfig qpe -no-qvfb -depths 8,16,24,32&nbsp;&nbsp; <BR>-no-xft -system-jpeg&nbsp; -system-libpng -system-zlib -gif -thread –release -&nbsp; <BR>I/root/yizhi/arminclude -L/root/yizhi/armlib -lpng -lz –luuid -ljpeg" -qpe&nbsp; '-xplatform linux- <BR>arm-g++ -edition pda –displaysize 640x480 -I/root/yizhi/arminclude&nbsp; -L/root/yizhi/armlib - <BR>prefix=/root/yizhi/qtopia'<BR>④编译qtopia<BR># make<BR>⑤安装qtopia的交叉编译环境<BR># make install<BR>编译完成以后/root/yizhi后出现一个qtopia的目录，在/root/yizhi/qtopia/lib/目录下面看到libqte.so、 <BR>libqte.so.2 libqte.so.2.3、libqte.so.2.3.12 这四个文件. 这是编译qte的库文件.<BR>将所有需要支持的库文件都放到新生成的qtopia/lib中<BR># cp /root/yizhi/armlib/*.so* /root/yizhi/qtopia/lib&nbsp; <BR>4、将qtopia挂在到目标板上<BR>4.1、建立宿主机和开发板的通讯<BR>以/root/share 为共享文件夹，目标板可通过nfs来访问这个共享文件夹。<BR>将qtopia复制到共享文件夹/root/share/<BR># cp -r /root/yizhi/qtopia&nbsp; /root/share/<BR>设置共享文件夹：<BR>①、修改/etc/export指定/root/share文件夹为共享可访问的<BR>最后一行加上&nbsp;&nbsp;&nbsp; /root/share 192.168.0.* (rw)<BR>②、没有关闭防火墙<BR>4.2、启动nfs服务<BR># service nfs restart&nbsp; （或nfs /etc/rc.d/init.d/nfs&nbsp; start）<BR>设置本机的ip 地址为192.168.0.105<BR># ifconfig eth0 192.168.0.105 up<BR>4.3、测试qtopia是否正常运行<BR>配置串口的波特率为115200，启动目标板。<BR># minicom<BR># ifconfig -t nfs eth0 192.168.0.16 up<BR>检测目标板和PC机是否建立了连接<BR>#ping 192.168.0.105<BR>如果建立了连接，将文件复制到目标板上<BR># mount 192.168.0.105:/root/share /mnt/ext2<BR># cd /mnt/ext2/qtopia<BR>设置环境变量<BR># export QTDIR=$PWD<BR># export QPEDIR=$PWD<BR># export LD_LIBRARY_PATH=$PWD/lib<BR>我的根文件系统为只读文件系统cramfs，下句是指定一个可读写的文件，作为环境变量HOME<BR># export HOME=/etc/tmp<BR>帧缓冲设备板子上为/dev/fb/0,但程序默认为/dev/fb0,所以做了一个链，接/dev/fb0到/dev/fb/0<BR># ln -s /dev/fb/0 /dev/fb0&nbsp;&nbsp;&nbsp; <BR>指定键盘和鼠标为输入设备<BR># export QWS_KEYBOARD_PROTO="USB:/dev/input/event1"<BR># export QWS_MOUSE_PROTO="USB:/dev/input/mouse0"<BR>在qtopia下可能没有pointercal文件可以自创一个其内容是1 0 1 0 1 1&nbsp; 65536<BR># cp pointercal /etc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR># cp pointercal /etc/tmp<BR>运行PDA<BR># cd bin<BR># ./qpe<BR>出现 Tap anywhere on the screen to continue&nbsp;&nbsp; <BR>用鼠标点击一下桌面，就进入配置显示使用的语言和所在地区的时区，点击finish键，这样就可以在显示终端上看 <BR>到qtopia桌面环境了</P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/920232008944580190</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/920232008944580190</guid>
    <pubDate>Sat, 4 Oct 2008 16:58:00 +0800</pubDate>
    <dcterms:modified>2008-10-04T16:58:00+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[建立ARM平台上的交叉调试器gdb和gdbserver(转载)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320089343724228</link>
    <description><![CDATA[<div><P><FONT color=#ff0000 size=4>(有的时候执行环境的权限真的是很重要的)</FONT></P>
<P>gdb-6.6使用了autoconf/automake，因此通过设置configure脚本的--target，--host,--prefix参数就可以方便的移植到别的平台。</P>
<P><FONT color=#ff0000>--target </FONT>指定编译后的文件针对的是什么目标板，一般设置为交叉编译器的前缀，比如--target=arm-linux, --target=mips-linux，--target=armv5-linux-uclibc, --target的缺省值为i386-linux, 也就是PC机。 </P>
<P><FONT color=#ff0000>--host</FONT> 指定编译后的文件的运行环境，取值可以是i386-linux或者交叉编译器的前缀，缺省为i386-linux，</P>
<P><FONT color=#ff0000>--prefix</FONT> 指定要安装的目录。</P>
<P><FONT color=#0000ff>1、</FONT>到<A href="http://www.gnu.org/software/gdb">http://www.gnu.org/software/gdb</A>下载gdb-6.6.tar.gz到/tmp解压到/opt下<BR>&nbsp;&nbsp; #cd /opt<BR>&nbsp;&nbsp; #tar xzvf /tmp/gdb-6.6.tar.gz</P>
<P><FONT color=#0000ff>2、</FONT>建立配置文件、编译<BR>&nbsp;&nbsp; gdb允许把编译配置和编译结果放到任意的目录，因此可以在gdb目录之外建立一个专门放编译文件的目录。<BR>&nbsp;&nbsp; #cd /opt<BR>&nbsp;&nbsp; #mkdir -p arm-gdb/build<BR>&nbsp;&nbsp; #cd arm-gdb/build</P>
<P>&nbsp;&nbsp; #/opt/gdb-6.6/configure --host=i386-linux --target=armv5-linux-uclibc --prefix=/opt/arm-gdb<BR>&nbsp;&nbsp; #make<BR>&nbsp;&nbsp; #make install<BR>其中：host指定了运行环境为i386机器，target指定了需要调试的目标机环境（<FONT color=#ff0000>我使用的ARM toolchain是armv5-linux-uclibc-gcc，因此这样指定，如果是用arm-linux-gcc，则 --target=arm-linux</FONT>），prefix指定了编译后的结果存放的位置，也就是安装目录。<BR>&nbsp;&nbsp; 如果在编译arm-linux-low.c这个文件时提示找不到“sys/reg.h”, 则修改arm-linux-low.c，注释掉#include "sys/reg.h"。</P>
<P>&nbsp;&nbsp;&nbsp; 可以在/opt/arm-gdb/bin下找到可执行的armv5-linux-uclibc-gdb, armv5-linux-uclibc-gdbtui, armv5-linux-uclibc-run。</P>
<P>3、gdbserver的移植<BR>&nbsp;&nbsp; gdbserver要用到gdb源码目录下的一些头文件，因此无法在gdb源码目录之外建立编译文件。<BR>&nbsp;<BR>&nbsp;&nbsp; #cd /opt/gdb-6.6/gdb/gdbserver<BR>&nbsp;&nbsp; #vi build.arm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; 内容如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./configure --target=armv5-linux-uclibc --host=armv5-linux-uclibc --prefix=/opt/arm-gdb/gdbserver<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make install<BR>&nbsp;&nbsp; #chmod +x build.arm<BR>&nbsp;&nbsp; #./build.arm</P>
<P>&nbsp;&nbsp; 注意：此处target参数和host参数都要设置为armv5-linux-uclibc，因为gdbserver是放在目标板上运行的。<BR>&nbsp;&nbsp; 编译后，可以在/opt/arm-gdb/gdbserver/bin下找到armv5-linux-uclibc-gdbserver，下载该文件到目标板并重命名为gdbserver，<BR>&nbsp;&nbsp; 同时要下载gdbserver需要的库文件libthread_db-x.x.x.so，再建立两个符号链接libthread_db.so和libthread_db.so.1。<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; <BR>4、使用gdbserver<BR>&nbsp;&nbsp; 在目标板上运行gdbserver<BR>&nbsp;&nbsp; #./gdbserver 192.168.0.2:2345 hello<BR>&nbsp; <BR>&nbsp;&nbsp; 其中192.168.0.2为目标板的IP，可以写localhost，也可以不写。2345为gdbserver打开的端口，可以自己设置。<BR>&nbsp;&nbsp; #./gdbserver :2345 hello<BR>&nbsp;<BR>&nbsp;&nbsp; 在宿主机上运行<BR>&nbsp;&nbsp; #armv5-linux-uclibc-gdb hello<BR>&nbsp;&nbsp; (gdb)target remote 192.168.0.2:2345<BR>&nbsp;&nbsp; (gdb)b main<BR>&nbsp;&nbsp; (gdb)continue</P>
<P>&nbsp;&nbsp; 使用X-Windows下的DDD<BR>&nbsp;&nbsp; #ddd --debugger armv5-linux-uclibc-gdb</P>
<P>&nbsp;&nbsp; 在DDD的GDB终端控制窗口中健入: <BR>&nbsp;&nbsp; (gdb) target 192.168.0.2:2345</P>
<P>6、问题<BR>&nbsp;&nbsp; 移植的gdbserver可以和Host上的mips-linux-gdb连接上，但是run的时候gdbserver出现<BR>&nbsp;&nbsp; Killing inferior错误<BR>&nbsp;&nbsp; 解决方法：因为执行完target命令后，目标板程序已经在运行，所有应该用continue命令而不是run命令。</P>
<P><BR>7、附1：GDB的基本指令：</P>
<P>&nbsp;&nbsp; load：装入一个程序<BR>&nbsp;&nbsp; symbol-file：装入符号库文件，可以是用-g参数编译的可执行文件。<BR>&nbsp;&nbsp; f(ile)：指定一个可执行文件进行调试，gdb将读取些文件的调试讯息，如f a.exe<BR>&nbsp;&nbsp; l(ist)：列程序出源文件<BR>&nbsp;&nbsp; r(un) ：装载完要调试的可执行文件后，可以用run命令运行可执行文件<BR>&nbsp;&nbsp; b(reak)：设置断点（break point），如b 25，则在源程序的第25行设置一个断点，当程序执行到第25行时，就会产生中断；也可以使用b funcname，funcname为函数的名称，</P>
<P>当程序调用些函数时，则产生中断<BR>&nbsp;&nbsp; c(ontinue)：c命令可以另中断的程序继续执行，直到下一个中断点或程序结束<BR>&nbsp;&nbsp; p(rint)：输入某个变量的值，如程序定义了一个int aa的就是，p aa就会输出aa的当前值<BR>&nbsp;&nbsp; n(ext)：程序执行到断点时中断执行，可以用n指令进行单步执行<BR>&nbsp;&nbsp; s(tep)：程序执行到断点时中断执行，可以用s指令进行单步执行进某一函数<BR>&nbsp;&nbsp; q(uit)：退出GDB</P>
<P>8、附2：调试驱动程序和共享库</P>
<P>&nbsp; (1)调试LKM(Loadable Kernel Module)<BR>&nbsp; .在目标板上插入模块并输出map信息，查看.text入口地址：<BR>&nbsp;&nbsp; #insmod -m hello.ko &gt; map<BR>&nbsp;&nbsp; #grep .text map&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 比如为0xc68c0060<BR>&nbsp; .在gdb中转入LKM的调试信息：<BR>&nbsp;&nbsp; (gdb) add-symbol-file hello.ko 0xc68c0060&nbsp; /*注意必须是LKM .text的入口地址）<BR>&nbsp; .正常调试</P>
<P>&nbsp; (2)调试共享库<BR>&nbsp;&nbsp;&nbsp; .样例程序：&nbsp; <BR>&nbsp;&nbsp;&nbsp; test.c:<BR>&nbsp;&nbsp;&nbsp; #include &lt;stdio.h&gt;<BR>&nbsp;&nbsp;&nbsp; int test(int a, int b)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp; int s = a b;<BR>&nbsp;&nbsp;&nbsp; printf("%d\n", s);<BR>&nbsp;&nbsp;&nbsp; return s;<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; main.c:<BR>&nbsp;&nbsp;&nbsp; #include &lt;stdio.h&gt;<BR>&nbsp;&nbsp;&nbsp; extern int test(int a, int b);<BR>&nbsp;&nbsp;&nbsp; int main(int argc, char* argv[])<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp; int s = test(10, 20);<BR>&nbsp;&nbsp;&nbsp; return s;<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; Makefile:<BR>&nbsp;&nbsp;&nbsp; all: so main<BR>&nbsp;&nbsp;&nbsp; so:<BR>&nbsp;&nbsp;&nbsp; armv5-linux-uclibc-gcc -g test.c -shared -o libtest.so<BR>&nbsp;&nbsp;&nbsp; main:<BR>&nbsp;&nbsp;&nbsp; armv5-linux-uclibc-gcc -g main.c -L./ -ltest -o test.exe<BR>&nbsp;&nbsp;&nbsp; clean:<BR>&nbsp;&nbsp;&nbsp; rm -f *.exe *.so<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; .编译并设置环境变量<BR>&nbsp;#make</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在目标板上：<BR>&nbsp;#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./<BR>&nbsp;#gdbserver localhost:2345 ./test.exe</P>
<P>&nbsp;&nbsp;&nbsp; .运行gdb客户端<BR>&nbsp;#armv5-linux-uclibc-gdb<BR>&nbsp;(gdb)symbol-file test.exe<BR>&nbsp;(gdb)target remote 192.168.0.2:2345<BR>&nbsp;(gdb)b main<BR>&nbsp;(gdb)c</P>
<P>&nbsp;&nbsp;&nbsp; .查看libtest.so的代码在内存中的位置。<BR>&nbsp;&nbsp;&nbsp;&nbsp; (从gdbserver的输出或者用ps可以得到test.exe的进程ID，这里假设PID是11547)<BR>&nbsp;&nbsp;&nbsp;&nbsp; 在目标板上：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #cat /proc/11547/maps<BR>&nbsp;输出：</P>
<P>.........<BR>&nbsp;0076a000-0076c000 rwxp 0076a000 00:00 0 <BR>&nbsp;00bbe000-00bbf000 r-xp 00bbe000 00:00 0 <BR>&nbsp;00fcc000-00fcd000 r-xp 00000000 03:01 1238761 /root/test/gdbservertest/libtest.so<BR>&nbsp;00fcd000-00fce000 rwxp 00000000 03:01 1238761 /root/test/gdbservertest/libtest.so<BR>&nbsp;08048000-08049000 r-xp 00000000 03:01 1238765 /root/test/gdbservertest/test.exe<BR>&nbsp;08049000-0804a000 rw-p 00000000 03:01 1238765 /root/test/gdbservertest/test.exe<BR>&nbsp;........<BR>&nbsp;<BR>&nbsp;由此可以知道：libtest.so的代码在00fcc000-00fcd000之间。</P>
<P>&nbsp;&nbsp;&nbsp; .查看libtest.so的.text段在内存中的偏移位置：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; armv5-linux-uclibc-objdump -h libtest.so |grep .text<BR>&nbsp;输出：<BR>&nbsp;&nbsp; .text 00000130 00000450 00000450 00000450 2**4<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 即偏移位置为0x00000450</P>
<P>&nbsp;&nbsp;&nbsp; .回到板子上的gdb窗口，加载libtest.so的符号表。<BR>&nbsp;(gdb)add-symbol-file libtest.so 0x00fcc450<BR>&nbsp; (这里0x00fcc450 = 0x00fcc000 0x00000450)</P>
<P>&nbsp;&nbsp;&nbsp; .在共享库的函数中设置断点<BR>&nbsp;(gdb)b test</P>
<P>&nbsp;&nbsp;&nbsp; .继续调试共享库<BR></P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320089343724228</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320089343724228</guid>
    <pubDate>Fri, 3 Oct 2008 16:37:24 +0800</pubDate>
    <dcterms:modified>2008-10-04T14:08:49+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Qtopia Core 4移植过程(转)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320088445652391</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em">S3C2410 + linux 2.4.x</P>
<P style="TEXT-INDENT: 2em">Qtopia Core 4。2.2 是QT/embedded的最新版本，</P>
<P style="TEXT-INDENT: 2em">下面是Qtopia Core 4移植过程：</P>
<P style="TEXT-INDENT: 2em">&nbsp; &nbsp; &nbsp; &nbsp; 1. 下载交叉编译链<A href="ftp://ftp.handhelds.org/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2">ftp://ftp.handhelds.org/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2</A>。不要用cross-2.95.3，Qtopia Core 4指明要3.2以上的版本。网上的教程大多就拿cross-2.95.3编译QT/embedded 2的...解压缩到/usr/local/arm目录下</P>
<P style="TEXT-INDENT: 2em">tar xjvf linux-gcc-3.4.1.tar.bz2 -C /</P>
<P style="TEXT-INDENT: 2em">设置交叉编译的环境变量：</P>
<P style="TEXT-INDENT: 2em">export set PATH=/usr/local/arm/3.4.1/bin:$PATH</P>
<P style="TEXT-INDENT: 2em">&nbsp; &nbsp; &nbsp; &nbsp; 2. 下载Qtopia Core 4的源代码qtopia-core-opensource-src-4.2.2.tar.gz，解压</P>
<P style="TEXT-INDENT: 2em">tar zxvf qtopia-core-opensource-src-4.2.2.tar.gz</P>
<P style="TEXT-INDENT: 2em">cd qtopia-core-opensource-src-4.2.2</P>
<P style="TEXT-INDENT: 2em">./configure -embedded arm -xplatform qws/linux-arm-g++ -depths 4,8,12,16 -no-qt3support </P>
<P style="TEXT-INDENT: 2em">注：详细了解参数./configure --help , 其中带*号选项为安装默认值，基中有-KBD等选项，方便嵌入式开发。</P>
<P style="TEXT-INDENT: 2em">gmake VM上约一个半小时</P>
<P style="TEXT-INDENT: 2em">gmake install (需root 权限)</P>
<P style="TEXT-INDENT: 2em">设置Qt的环境变量：</P>
<P style="TEXT-INDENT: 2em">export PATH=/usr/local/Trolltech/QtopiaCore-4.2.2-arm/bin:$PATH</P>
<P style="TEXT-INDENT: 2em">注：环境变量通过/etc/profile可系统启动自动设置。</P>
<P style="TEXT-INDENT: 2em">3.&nbsp; 编译Hello World，代码参考Qt的文档，保存未 hello.ccp 。</P>
<P style="TEXT-INDENT: 2em">&nbsp; &nbsp; qmake -project</P>
<P style="TEXT-INDENT: 2em">&nbsp; &nbsp; qmake</P>
<P style="TEXT-INDENT: 2em">&nbsp; &nbsp; make</P>
<P style="TEXT-INDENT: 2em">得到相应ELF文件。</P>
<P style="TEXT-INDENT: 2em">&nbsp; &nbsp; 4.&nbsp; 移植到目标平台：</P>
<P style="TEXT-INDENT: 2em">A,建立运行库及环境设置。</P>
<P style="TEXT-INDENT: 2em">注：程序运行相关库文件可利用LDD命令得到：ldd ./***** （X86平台可用lsof命令，朋友说的，TKS）</P>
<P style="TEXT-INDENT: 2em">B,COPY 应用程序 TO ARM板。 </P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320088445652391</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320088445652391</guid>
    <pubDate>Thu, 4 Sep 2008 16:56:52 +0800</pubDate>
    <dcterms:modified>2008-09-04T16:56:52+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[QTOPIA4.2.1在2410上面的移植（转） ]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200884113854356</link>
    <description><![CDATA[<div><P><FONT color=#000000>经过几天的努力，这几天很累，熬夜和查找资料。总之，虽然是自学的嵌入式，可是效果还可以，费了很大劲。</FONT></P>
<P><FONT color=#000000>爱你，又想说恨你。可是要想以后有一份不错的工作来养家糊口，只能坚持不懈的努力。正如我一个中兴的朋友说的好：人都会有目标，可是要坚持不懈的努力那就很难。</FONT></P>
<P><FONT color=#000000>这几天一直在忙着QTOPIA4.2.1在2410上面的移植，平台的差异，编译器的问题，可是我最后万万没有想到，还是得到一个论坛大哥的帮助，还得以解决。问题出在make的前提是一定要是原来的源代码，不管你是make clean过，还是怎么讲都不行。至少我在red hat linux 9上面是这样的。</FONT></P>
<P><FONT color=#000000>&nbsp;教程是这样的：</FONT></P>
<P><FONT color=#000000>一．硬件平台</FONT></P>
<P><FONT color=#000000>1．主机： PC机，512M内存以上。</FONT></P>
<P><FONT color=#000000>2．目标机： UP-NetARM2410-S实验平台。</FONT></P>
<P><FONT color=#000000>二．移植软件资源</FONT></P>
<P><FONT color=#000000>1．Red Hat Linux 9.0（主机操作系统）</FONT></P>
<P><FONT color=#000000>2．gcc-3.4.1.tar.gz（主机编译器）</FONT></P>
<P><FONT color=#000000>3．arm-linux-gcc-3.4.1.tar.bz2（交叉编译器）</FONT></P>
<P><FONT color=#000000>4．tslib-1.3.tar.bz2（管理目标平台的触摸屏）</FONT></P>
<P><FONT color=#000000>5．qtopia-opensource-src-4.2.1.tar.gz(包含Qt，Qtopia core)</FONT></P>
<P><FONT color=#000000>2． GUI(QT)的移植过程</FONT></P>
<P><FONT color=#000000>编译前的约定：</FONT></P>
<P><FONT color=#000000>1）我的工作目录为：/mnt/nfs。</FONT></P>
<P><FONT color=#000000>2）qtopia-opensource-src-4.2.1.tar.gz 软件包放在/mnt/nfs/qtopia4目录下。</FONT></P>
<P><FONT color=#000000>一．编译主机编译器 gcc-3.4.1.tar.gz</FONT></P>
<P><FONT color=#000000>步骤如下：</FONT></P>
<P><FONT color=#000000># tar –zxvf gcc-3.4.1.tar.gz</FONT></P>
<P><FONT color=#000000># ./configure&nbsp;&nbsp;&nbsp; (默认安装目录为：/usr/local)</FONT></P>
<P><FONT color=#000000># make</FONT></P>
<P><FONT color=#000000># make install</FONT></P>
<P><FONT color=#000000>安装完成后，可执行文件放在/usr/local/bin目录下，库文件放在/usr/local/lib目录下。</FONT></P>
<P><FONT color=#000000>二．安装交叉编译器 arm-linux-gcc-3.4.1.tar.bz2</FONT></P>
<P><FONT color=#000000>步骤如下：</FONT></P>
<P><FONT color=#000000># tar jxvf arm-linux-gcc-3.4.1.tar.bz2</FONT></P>
<P><FONT color=#000000>解压后的文件为 usr目录,其已包括可执行文件，直接将usr拷贝到根目录下。然后</FONT></P>
<P><FONT color=#000000># vi /etc/profile</FONT></P>
<P><FONT color=#000000>在里边添加：</FONT></P>
<P><FONT color=#000000>export PATH=$PATH:/usr/local/arm/3.4.1/bin</FONT></P>
<P><FONT color=#000000>保存退出，执行：</FONT></P>
<P><FONT color=#000000># source /etc/profile</FONT></P>
<P><FONT color=#000000>三．编译tslib-1.3.tar.bz2</FONT></P>
<P><FONT color=#000000>详细步骤如下：</FONT></P>
<P><FONT color=#000000># tar jxvf tslib-1.3.tar.bz2</FONT></P>
<P><FONT color=#000000>解压后的目录为tslib-1.3。</FONT></P>
<P><FONT color=#000000># cd tslib-1.3</FONT></P>
<P><FONT color=#000000># export CC=arm-linux-gcc</FONT></P>
<P><FONT color=#000000># export CXX= arm-linux-g++</FONT></P>
<P><FONT color=#000000># ./autogen.sh</FONT></P>
<P><FONT color=#000000># ./configure --prefix=/mnt/nfs/tslib1.3-install --host=arm-linux</FONT></P>
<P><FONT color=#000000>（ 配置目标平台为ARM-linux,在主机上的安装目录为/mnt/nfs/tslib1.3-install ）</FONT></P>
<P><FONT color=#000000># make</FONT></P>
<P><FONT color=#000000># make install<BR>Qtopia4移植过程(二)2007-06-27 22:24四．编译 qtopia-opensource-src-4.2.1.tar.gz</FONT></P>
<P><FONT color=#000000>编译前约定：</FONT></P>
<P><FONT color=#000000>安装目录为：/mnt/nfs/qtopia4/qtopiatslibinstall</FONT></P>
<P><FONT color=#000000>目标目录为：/mnt/nfs/qtopia4/qtopiatslibtarget</FONT></P>
<P><FONT color=#000000>下面解压软件包：</FONT></P>
<P><FONT color=#000000># tar zxvf qtopia-opensource-src-4.2.1.tar.gz</FONT></P>
<P><FONT color=#000000>然后重命名解压后的包：</FONT></P>
<P><FONT color=#000000># mv qtopia-opensource-4.2.1 qtopiatslibinstall</FONT></P>
<P><FONT color=#000000># cd qtopiatslibinstall</FONT></P>
<P><FONT color=#000000>在此目录下，文件夹为qtopiacore的目录即是Qt，QtopiaCore所在目录，里边包含了开发所需的Designer,qmake,uic,moc等工具，也包含了面向嵌入式平台的Qt库。</FONT></P>
<P><FONT color=#000000>编译前，首先建立定位到安装目录和目标目录的环境变量：</FONT></P>
<P><FONT color=#000000># export QTOPIAINST=/mnt/nfs/qtopia4/qtopiatslibinstall</FONT></P>
<P><FONT color=#000000># export QTOPIATARG=/mnt/nfs/qtopia4/qtopiatslibtarget</FONT></P>
<P><FONT color=#000000>为了让编译适应于目标平台和去除编译中将出现的错误，我们需要对源码进行修改和裁减。因此，编译的详细过程如下：</FONT></P>
<P><FONT color=#000000>1． 修改源码包</FONT></P>
<P><FONT color=#000000>1）</FONT></P>
<P><FONT color=#000000># cd src/libraries/qtopiabase/</FONT></P>
<P><FONT color=#000000># cp custom-linux-cassiopeia-g++.h custom-linux-arm-g++.h</FONT></P>
<P><FONT color=#000000># cp custom-linux-cassiopeia-g++.cpp custom-linux-arm-g++.cpp</FONT></P>
<P><FONT color=#000000>2）修改3.4.1版的arm编译器的文件</FONT></P>
<P><FONT color=#000000># cd /usr/local/arm/3.4.1/</FONT></P>
<P><FONT color=#000000># vi arm-linux/include/linux/videodev2.h</FONT></P>
<P><FONT color=#000000>在其中添加如下内容：</FONT></P>
<P><FONT color=#000000>#define V4L2_PIX_FMT_SBGGR8&nbsp; v4l2_fourcc('B','A','8','1') </FONT></P>
<P><FONT color=#000000>/*&nbsp; 8&nbsp; BGBG.. GRGR.. */</FONT></P>
<P><FONT color=#000000>保存退出。</FONT></P>
<P><FONT color=#000000># vi arm/3.4.1/arm-linux/sys_include/linux/videodev2.h</FONT></P>
<P><FONT color=#000000>在其中添加如下内容：</FONT></P>
<P><FONT color=#000000>#define V4L2_PIX_FMT_SBGGR8&nbsp; v4l2_fourcc('B','A','8','1') </FONT></P>
<P><FONT color=#000000>/*&nbsp; 8&nbsp; BGBG.. GRGR.. */</FONT></P>
<P><FONT color=#000000>保存退出。</FONT></P>
<P><FONT color=#000000>3) 修改时区信息</FONT></P>
<P><FONT color=#000000># vi src/libraries/qtopia/qtimezone.cpp</FONT></P>
<P><FONT color=#000000>将114行的 /usr/share/zoneinfo/ 改为/mnt/nfs/qtopia4/qtopiatslibtarget/zoneinfo/ ,保存退出。</FONT></P>
<P><FONT color=#000000># vi src/settings/systemtime/settime.cpp</FONT></P>
<P><FONT color=#000000>将318行的 /usr/share/zoneinfo/ 改为/mnt/nfs/qtopia4/qtopiatslibtarget/zoneinfo/ ,保存退出。</FONT></P>
<P><FONT color=#000000>4) 裁减Qtopia core的库</FONT></P>
<P><FONT color=#000000># vi qtopiacore/qconfig-qpe.h</FONT></P>
<P><FONT color=#000000>首先注释掉关于鼠标光标的宏定义，让程序运行时，触摸屏中央有光标出现：</FONT></P>
<P><FONT color=#000000>// Qtopia Core</FONT></P>
<P><FONT color=#000000>/*</FONT></P>
<P><FONT color=#000000>#ifndef QT_NO_QWS_CURSOR</FONT></P>
<P><FONT color=#000000>#&nbsp; define QT_NO_QWS_CURSOR</FONT></P>
<P><FONT color=#000000>#endif</FONT></P>
<P><FONT color=#000000>*/</FONT></P>
<P><FONT color=#000000>/*</FONT></P>
<P><FONT color=#000000>#ifndef QT_NO_QWS_MOUSE</FONT></P>
<P><FONT color=#000000>#&nbsp; define QT_NO_QWS_MOUSE</FONT></P>
<P><FONT color=#000000>#endif</FONT></P>
<P><FONT color=#000000>#ifndef QT_NO_QWS_MOUSE_AUTO</FONT></P>
<P><FONT color=#000000>#&nbsp; define QT_NO_QWS_MOUSE_AUTO</FONT></P>
<P><FONT color=#000000>#endif</FONT></P>
<P><FONT color=#000000>*/</FONT></P>
<P><FONT color=#000000>其它宏定义根据需要进行注释。</FONT></P>
<P><FONT color=#000000>保存后将qconfig-qpe.h拷贝到global目录。</FONT></P>
<P><FONT color=#000000># cp qtopiacore/qconfig-qpe.h qtopiacore/qt/src/corelib/</FONT></P>
<P><FONT color=#000000>global/qconfig-qpe.h</FONT></P>
<P><FONT color=#000000>5）注释掉其他文件里的QT_NO_QWS_CURSOR的定义</FONT></P>
<P><FONT color=#000000># vi qtopiacore/qt/src/corelib/global/qfeatures.h</FONT></P>
<P><FONT color=#000000>注释掉如下内容：</FONT></P>
<P><FONT color=#000000>/*</FONT></P>
<P><FONT color=#000000>#if !defined(QT_NO_QWS_CURSOR) &amp;&amp; (defined(QT_NO_CURSOR))</FONT></P>
<P><FONT color=#000000>#define QT_NO_QWS_CURSOR</FONT></P>
<P><FONT color=#000000>#endif</FONT></P>
<P><FONT color=#000000>*/</FONT></P>
<P><FONT color=#000000>保存退出。</FONT></P>
<P><BR><FONT color=#000000># vi qtopiacore/qt/src/corelib/global/qglobal.h</FONT></P>
<P><FONT color=#000000>注释掉以下内容：</FONT></P>
<P><FONT color=#000000>//#&nbsp;&nbsp;&nbsp; define QT_NO_QWS_CURSOR<BR>Qtopia4移植过程(三)2007-06-27 22:252．配置源码包</FONT></P>
<P><FONT color=#000000>首先，确定目录为： /mnt/nfs/qtopia4/qtopiatslibinstall</FONT></P>
<P><FONT color=#000000>然后进行配置，执行如下命令 ：</FONT></P>
<P><FONT color=#000000># ./configure -silent -release </FONT></P>
<P><FONT color=#000000>-image /mnt/nfs/qtopia4/qtopiatslibtarget </FONT></P>
<P><FONT color=#000000>-prefix /mnt/nfs/qtopia4/qtopiatslibtarget </FONT></P>
<P><FONT color=#000000>-xplatform linux-arm-g++ -arch arm -no-qvfb </FONT></P>
<P><FONT color=#000000>-displaysize 640x480 -no-modem </FONT></P>
<P><FONT color=#000000>-extra-qtopiacore-config "-release -xplatform qws/linux-arm-g++ -embedded arm -opengl -qconfig qpe -qt-sql-sqlite </FONT></P>
<P><FONT color=#000000>-depths 4,8,16,32 -qt-kbd-usb -no-kbd-tty -no-mouse-linuxtp </FONT></P>
<P><FONT color=#000000>-qt-mouse-tslib -I/mnt/nfs/tslib1.3-install/include -L/mnt/nfs/tslib1.3-install/lib" 2&gt;../qtopiaconfgureERR.txt</FONT></P>
<P><BR><FONT color=#000000>主要配置选项解说如下：</FONT></P>
<P><FONT color=#000000>-xplatform linux-arm-g++ -arch arm</FONT></P>
<P><FONT color=#000000>目标平台为arm-linux,体系结构为arm。</FONT></P>
<P><BR><FONT color=#000000>-no-qvfb </FONT></P>
<P><FONT color=#000000>目标平台已支持framebuffer,因而不使用虚拟帧缓冲。</FONT></P>
<P><BR><FONT color=#000000>-extra-qtopiacore-config</FONT></P>
<P><FONT color=#000000>为Qtopia core 配置选项。</FONT></P>
<P><BR><FONT color=#000000>-xplatform qws/linux-arm-g++ -embedded arm</FONT></P>
<P><FONT color=#000000>目标平台编译配置文件使用qtopiacore/qt/mkspecs/qws/linux-arm-g++目录下的配置文件，嵌入式平台为arm。</FONT></P>
<P><BR><FONT color=#000000>-qconfig qpe</FONT></P>
<P><FONT color=#000000>使用配置文件qconfig-qpe.h，若使用qconfig-large.h配置文件，则使用-qconfig large选项。</FONT></P>
<P><BR><FONT color=#000000>-qt-sql-sqlite</FONT></P>
<P><FONT color=#000000>数据库支持Sqlite。</FONT></P>
<P><BR><FONT color=#000000>-qt-kbd-usb</FONT></P>
<P><FONT color=#000000>键盘支持usb协议。</FONT></P>
<P><BR><FONT color=#000000>-no-mouse-linuxtp -qt-mouse-tslib</FONT></P>
<P><FONT color=#000000>-I/mnt/nfs/tslib1.3-install/include -L/mnt/nfs/tslib1.3-install/lib</FONT></P>
<P><FONT color=#000000>触摸屏协议不支持linuxtp，支持tslib，并在后面添加上刚才编译的tslib的头文件和库。</FONT></P>
<P><BR><FONT color=#000000>2&gt;../qtopiaconfgureERR.txt</FONT></P>
<P><FONT color=#000000>最后将配置过程中的错误输出到qtopiaconfgureERR.txt文件中。</FONT></P>
<P><FONT color=#000000>3．编译源码包</FONT></P>
<P><FONT color=#000000>执行如下命令：</FONT></P>
<P><FONT color=#000000># make 2&gt;../qtopiamakeERR.txt</FONT></P>
<P><FONT color=#000000>4．安装编译后源码包</FONT></P>
<P><FONT color=#000000># make install</FONT></P>
<P><FONT color=#000000>编译安装完成后，在/mnt/nfs/qtopia4/qtopiatslibtarget目录下产生各个目标文件。</FONT></P>
<P><FONT color=#000000>5．建立时区信息</FONT></P>
<P><FONT color=#000000># cd $QTOPIATARG</FONT></P>
<P><FONT color=#000000># mkdir zoneinfo</FONT></P>
<P><FONT color=#000000># cp -a /usr/share/zoneinfo/* $QTOPIATARG/zoneinfo/</FONT></P>
<P><FONT color=#000000>五．编译后的处理</FONT></P>
<P><FONT color=#000000>完成上面的步骤后，所有软件包已编译完成。下面建立环境变量，进行后期处理，建立开发环境。</FONT></P>
<P><FONT color=#000000>1）将designer,qmake 等工具拷贝到$QTOPIATARG/bin/目录下。</FONT></P>
<P><FONT color=#000000># cp $QTOPIAINST/qtopiacore/host/bin/* $QTOPIATARG/bin/</FONT></P>
<P><FONT color=#000000>2）建立环境变量：</FONT></P>
<P><FONT color=#000000># vi /etc/profile</FONT></P>
<P><FONT color=#000000>添加如下内容：</FONT></P>
<P><FONT color=#000000>QTOPIA="/mnt/nfs/qtopia4/qtopiatslibtarget"</FONT></P>
<P><FONT color=#000000>LD_LIBRARY_PATH="/usr/lib:/usr/local/lib:/usr/X11R6/lib"</FONT></P>
<P><FONT color=#000000>LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$QTOPIA/lib"</FONT></P>
<P><FONT color=#000000>PATH="$PATH:$QTOPIA/bin"</FONT></P>
<P><FONT color=#000000>QMAKESPEC=/mnt/nfs/qtopia4/qtopiatslibinstall/qtopiacore/qt/mkspecs/qws/linux-arm-g++</FONT></P>
<P><FONT color=#000000>export QTOPIA PATH LD_LIBRARY_PATH QMAKESPEC</FONT></P>
<P><FONT color=#000000>保存退出。</FONT></P>
<P><FONT color=#000000>#source /etc/profile</FONT></P>
<P><FONT color=#000000>3）修改ts.conf</FONT></P>
<P><FONT color=#000000># cd /mnt/nfs/tslib1.3-install/etc</FONT></P>
<P><FONT color=#000000># vi ts.conf</FONT></P>
<P><FONT color=#000000>原文件内容如下：</FONT></P>
<P><FONT color=#000000>#module mousebuts</FONT></P>
<P><FONT color=#000000>module variance xlimit=50 ylimit=50 pthreshold=3</FONT></P>
<P><FONT color=#000000>module dejitter xdelta=1 ydelta=1 pthreshold=3</FONT></P>
<P><FONT color=#000000>module linear</FONT></P>
<P><FONT color=#000000>将第一行的“#”去掉，让触摸屏起作用。</FONT></P>
<P><FONT color=#000000>到此为止，开发环境建立完毕。 <BR>&nbsp;3 移植成果演示</FONT></P>
<P><FONT color=#000000>在这里，我们以Qtopia自带的例子程序为例，来演示应用程序运行步骤。首先在/mnt/nfs/qtopia4/目录下用VI编辑器建立qtopiatslib.sh文件：</FONT></P>
<P><FONT color=#000000>export TSLIB_TSEVENTTYPE=event0</FONT></P>
<P><FONT color=#000000>export TSLIB_TSDEVICE=/dev/input/event0</FONT></P>
<P><FONT color=#000000>export TSLIB_CONFFILE=/mnt/nfs/tslib1.3-install/etc/ts.conf</FONT></P>
<P><FONT color=#000000>export TSLIB_CONSOLEDEVICE=none</FONT></P>
<P><FONT color=#000000>export TSLIB_CALIBFILE=/mnt/yaffs/tmp/pointercal</FONT></P>
<P><FONT color=#000000>export TSLIB_PLUGINDIR=/mnt/nfs/tslib1.3-install/share/ts/plugins</FONT></P>
<P><FONT color=#000000>export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/nfs</FONT></P>
<P><FONT color=#000000>/tslib1.3-install/lib</FONT></P>
<P><FONT color=#000000>export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/nfs</FONT></P>
<P><FONT color=#000000>/qtopia4/qtopiatslibtarget/lib</FONT></P>
<P><FONT color=#000000>export QWS_SIZE=640x480</FONT></P>
<P><FONT color=#000000>export QWS_MOUSE_PROTO="Tslib:/dev/input/event0"</FONT></P>
<P><FONT color=#000000>export POINTERCAL_FILE=/mnt/yaffs/tmp/pointercal</FONT></P>
<P><BR><FONT color=#000000>insmod /mnt/yaffs/touchscreen/ts-uptech.o</FONT></P>
<P><FONT color=#000000>cd /mnt/nfs/tslib1.3-install/bin</FONT></P>
<P><FONT color=#000000>./ts_calibrate</FONT></P>
<P><BR><FONT color=#000000>cd /mnt/nfs/qtopia4/qtopiatslibtarget/bin</FONT></P>
<P><FONT color=#000000>if [ -f "$TSLIB_CALIBFILE" ]; then</FONT></P>
<P><FONT color=#000000>./qpe -qws</FONT></P>
<P><FONT color=#000000>else</FONT></P>
<P><FONT color=#000000>/mnt/nfs/tslib1.3-install/bin/ts_calibrate</FONT></P>
<P><FONT color=#000000>./qpe -qws</FONT></P>
<P><FONT color=#000000>fi</FONT></P>
<P><FONT color=#000000>保存退出，修改用户使用权限：</FONT></P>
<P><FONT color=#000000># chmod 777 qtopiatslib.sh</FONT></P>
<P><FONT color=#000000>然后启动目标平台，打开minicom终端,进入目标平台的系统。在主机上启动NFS服务，将主机的/mnt/nfs目录挂载到目标机的/mnt/nfs目录。</FONT></P>
<P><FONT color=#000000>在终端里执行：</FONT></P>
<P><BR><FONT color=#000000># ifconfig eth0 192.168.0.1</FONT></P>
<P><FONT color=#000000># mount -t nfs (主机IP地址):/mnt/nfs /mnt/nfs</FONT></P>
<P><FONT color=#000000># cd /mnt/yaffs</FONT></P>
<P><FONT color=#000000># mkdir tmp</FONT></P>
<P><FONT color=#000000># cd /mnt/nfs/qtopia4</FONT></P>
<P><FONT color=#000000># ./qtopiatslib.sh</FONT></P>
<P><BR><FONT color=#000000>执行qtopiatslib.sh文件，首先校准触摸屏,依次点击屏幕上出现的五个点，完成后，会在/mnt/yaffs/tmp目录下生成pointercal校准文件。接下来就会启动qpe应用程序，进入Qtopia Phone的界面。 </FONT></P>
<P><FONT color=#000000>在实验的过程中可能会出现下面的错误：</FONT></P>
<P><FONT color=#000000>“在make的时候，遇到了一个错误。/usr/bin/ld .....debug-shared/moc.o提示could't read symbols :File in wrong format”</FONT></P>
<P><FONT color=#000000>只要重新用新的源代码来做才能通过。</FONT></P>
<P><FONT color=#000000>有时候嵌入式的问题真的很难说。总之，出现问题不要紧，能学到东西。努力吧，嵌入式的新人们。<BR></FONT></P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200884113854356</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200884113854356</guid>
    <pubDate>Thu, 4 Sep 2008 11:38:54 +0800</pubDate>
    <dcterms:modified>2008-09-04T11:50:36+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[滤波器与色彩转换(转载)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200883935589</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em"><A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvIntegral">cvIntegral</A> 计算积分图像。 
</P><LI>CV_BLUR (simple blur) - 对每个象素邻域 
<P></P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">×</P>
<P style="TEXT-INDENT: 2em">param2</P>
<P style="TEXT-INDENT: 2em">求和并做尺度变换 1/(</P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">?</P>
<P style="TEXT-INDENT: 2em">param2</P>
<P style="TEXT-INDENT: 2em">). </P>
</LI><LI>CV_GAUSSIAN (gaussian blur) - 对图像进行核大小为 
<P></P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">×</P>
<P style="TEXT-INDENT: 2em">param2</P>
<P style="TEXT-INDENT: 2em">的高斯卷积 </P>
</LI><LI>CV_MEDIAN (median blur) - 发现邻域 
<P></P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">×</P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">的中值 (i.e. 邻域是方的). </P>
</LI><LI>CV_BILATERAL (双滤波) - 应用双向 3x3 滤波，彩色 sigma=
<P></P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">，空间 sigma=</P>
<P style="TEXT-INDENT: 2em">param2</P>
<P style="TEXT-INDENT: 2em">. 关于双向滤波，可参考 <A href="http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html">http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html</A> </P></LI>
<UL></UL>
<DT>param1 
</DT><DD>平滑操作的第一个参数. 
</DD><DT>param2 
</DT><DD>平滑操作的第二个参数. 
<P></P>
<P style="TEXT-INDENT: 2em">param2</P>
<P style="TEXT-INDENT: 2em">为零对应简单的尺度变换和高斯模糊。 </P>
</DD><DT>param3 
</DT><DD>对应高斯参数的 Gaussian sigma (标准差). 如果为零，这由下面的核尺寸计算：
<P></P>
<P style="TEXT-INDENT: 2em">sigma = (n/2 - 1)*0.3 + 0.8, 其中 n=param1 对应水平核, n=param2 对应垂直核. 对小的卷积核 (3×3 to 7×7) 使用标准 sigma 速度会快。如果 </P>
<P style="TEXT-INDENT: 2em">param3</P>
<P style="TEXT-INDENT: 2em">不为零，而 </P>
<P style="TEXT-INDENT: 2em">param1</P>
<P style="TEXT-INDENT: 2em">和 </P>
<P style="TEXT-INDENT: 2em">param2</P>
<P style="TEXT-INDENT: 2em">为零，则核大小有 sigma 计算 (以保证足够精确的操作). </P></DD>
<DL></DL>
<P></P>
<P style="TEXT-INDENT: 2em">函数 <A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvSmooth">cvSmooth</A> 可使用上面任何一种方法平滑图像。每一种方法都有自己的特点以及局限。</P>
<P style="TEXT-INDENT: 2em">没有缩放的图像平滑仅支持单通道图像，并且支持8位、16位、32位和32位浮点格式。</P>
<P style="TEXT-INDENT: 2em">简单模糊和高斯模糊支持 1- 或 3-通道, 8-比特 和 32-比特 浮点图像。这两种方法可以（in-place）方式处理图像。</P>
<P style="TEXT-INDENT: 2em">中值和双向滤波工作于 1- 或 3-通道， 8-位图像，但是不能以 in-place 方式处理图像.
</P><HR>

<P></P>
<P style="TEXT-INDENT: 2em"><A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cxcore.htm#decl_cvSplit">cvSplit</A> 函数分解图像到单个色彩通道上，然后单独处理。 
</P><DT>anchor 
</DT><DD>核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。 </DD>
<DL></DL>
<P></P>
<P style="TEXT-INDENT: 2em">函数 <A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvFilter2D">cvFilter2D</A> 对图像进行线性滤波，支持 In-place 操作。当开孔部分位于图像外面时，函数从最近邻的图像内部象素差值得到边界外面的象素值。 
</P><HR>

<P></P>
<P style="TEXT-INDENT: 2em"><A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvIntegral">cvIntegral</A> 计算一次或高次积分图像：</P>
<P style="TEXT-INDENT: 2em">sum(X,Y)=sumx&lt;X,y&lt;Yimage(x,y)sqsum(X,Y)=sumx&lt;X,y&lt;Yimage(x,y)2tilted_sum(X,Y)=sumy&lt;Y,abs(x-X)&lt;yimage(x,y)</P>
<P style="TEXT-INDENT: 2em">利用积分图像，可以方便得到某个区域象素点的和、均值、标准方差或在 0（1） 的选择角度。例如：</P>
<P style="TEXT-INDENT: 2em">sumx1&lt;=x&lt;x2,y1&lt;=y&lt;y2image(x,y)=sum(x2,y2)-sum(x1,y2)-sum(x2,y1)+sum(x1,x1)</P>
<P style="TEXT-INDENT: 2em">因此可以在变化的窗口内做快速平滑或窗口相关。 
</P><HR>

<P></P>
<P style="TEXT-INDENT: 2em"><A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvCvtColor">cvCvtColor</A> 将输入图像从一个色彩空间转换为另外一个色彩空间。函数忽略 </P>
<P style="TEXT-INDENT: 2em">IplImage</P>
<P style="TEXT-INDENT: 2em">头中定义的 </P>
<P style="TEXT-INDENT: 2em">colorModel</P>
<P style="TEXT-INDENT: 2em">和 </P>
<P style="TEXT-INDENT: 2em">channelSeq</P>
<P style="TEXT-INDENT: 2em">域，所以输入图像的色彩空间应该正确指定 (包括通道的顺序，对RGB空间而言，BGR 意味着 24-位格式，其排列为 B0 G0 R0 B1 G1 R1 ... 层叠，而 RGB 意味着 24-位格式，其排列为 R0 G0 B0 R1 G1 B1 ... 层叠). 函数做如下变换： 
</P><UL>
<LI>RGB 空间内部的变换，如增加/删除 alpha 通道，反相通道顺序，16位&nbsp; RGB彩色变换(Rx5:Gx6:Rx5),以及灰度图像的变换，使用： 
<P></P>
<P style="TEXT-INDENT: 2em">RGB[A]-&gt;Gray: Y=0.212671*R + 0.715160*G + 0.072169*B + 0*AGray-&gt;RGB[A]: R=Y G=Y B=Y A=0</P>
<P style="TEXT-INDENT: 2em">所有可能的图像色彩空间的相互变换公式列举如下：</P>
<P style="TEXT-INDENT: 2em"></P>
</LI><LI>RGB&lt;=&gt;XYZ (CV_BGR2XYZ, CV_RGB2XYZ, CV_XYZ2BGR, CV_XYZ2RGB): 
<P></P>
<P style="TEXT-INDENT: 2em">|X| |0.412411 0.357585 0.180454| |R||Y| = |0.212649 0.715169 0.072182|*|G||Z| |0.019332 0.119195 0.950390| |B||R| | 3.240479 -1.53715 -0.498535| |X||G| = |-0.969256 1.875991 0.041556|*|Y||B| | 0.055648 -0.204043 1.057311| |Z|</P>
<P style="TEXT-INDENT: 2em"></P>
</LI><LI>RGB&lt;=&gt;YCrCb (CV_BGR2YCrCb, CV_RGB2YCrCb, CV_YCrCb2BGR, CV_YCrCb2RGB) 
<P></P>
<P style="TEXT-INDENT: 2em">Y=0.299*R + 0.587*G + 0.114*BCr=(R-Y)*0.713 + 128Cb=(B-Y)*0.564 + 128R=Y + 1.403*(Cr - 128)G=Y - 0.344*(Cr - 128) - 0.714*(Cb - 128)B=Y + 1.773*(Cb - 128)</P>
<P style="TEXT-INDENT: 2em"></P>
</LI><LI>RGB=&gt;HSV (CV_BGR2HSV,CV_RGB2HSV) 
<P></P>
<P style="TEXT-INDENT: 2em">V=max(R,G,B)S=(V-min(R,G,B))*255/V if V!=0, 0 otherwise (G - B)*60/S, if V=RH= 180+(B - R)*60/S, if V=G 240+(R - G)*60/S, if V=Bif H&lt;0 then H=H+360</P>
<P style="TEXT-INDENT: 2em">使用上面从 0° 到 360° 变化的公式计算色调（hue）值，确保它们被 2 除后能试用于8位。 </P>
<P style="TEXT-INDENT: 2em"></P>
</LI><LI>RGB=&gt;Lab (CV_BGR2Lab, CV_RGB2Lab) 
<P></P>
<P style="TEXT-INDENT: 2em">|X| |0.433910 0.376220 0.189860| |R/255||Y| = |0.212649 0.715169 0.072182|*|G/255||Z| |0.017756 0.109478 0.872915| |B/255|L = 116*Y1/3 for Y&gt;0.008856L = 903.3*Y for Y&lt;=0.008856a = 500*(f(X)-f(Y))b = 200*(f(Y)-f(Z))where f(t)=t1/3 for t&gt;0.008856 f(t)=7.787*t+16/116 for t&lt;=0.008856上面的公式可以参考 <A href="http://www.cica.indiana.edu/cica/faq/color_spaces/color.spaces.html">http://www.cica.indiana.edu/cica/faq/color_spaces/color.spaces.html</A> </P>
<P style="TEXT-INDENT: 2em"></P>
</LI><LI>Bayer=&gt;RGB (CV_BayerBG2BGR, CV_BayerGB2BGR, CV_BayerRG2BGR, CV_BayerGR2BGR,
<P></P>
<P style="TEXT-INDENT: 2em">CV_BayerBG2RGB, CV_BayerRG2BGR, CV_BayerGB2RGB, CV_BayerGR2BGR,</P>
<P style="TEXT-INDENT: 2em">CV_BayerRG2RGB, CV_BayerBG2BGR, CV_BayerGR2RGB, CV_BayerGB2BGR) </P>
<P style="TEXT-INDENT: 2em">Bayer 模式被广泛应用于 CCD 和 CMOS 摄像头. 它允许从一个单独平面中得到彩色图像，该平面中的 R/G/B 象素点被安排如下：</P>
<P style="TEXT-INDENT: 2em">
<TABLE width=400 border=0>
<TBODY>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD></TR>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD bgColor=pink>
<P></P>
<P style="TEXT-INDENT: 2em">B</P></TD>
<TD bgColor=pink>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">B</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD></TR>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD></TR>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">B</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">B</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD></TR>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">R</P></TD></TR>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">B</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">B</P></TD>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">G</P></TD></TR></TBODY></TABLE></P>
<P style="TEXT-INDENT: 2em">The output RGB components of a pixel are interpolated from 1, 2 or 4 neighbors of the pixel having the same color. There are several modifications of the above pattern that can be achieved by shifting the pattern one pixel left and/or one pixel up. The two letters C1 and C2 in the conversion constants CV_BayerC1C22{BGR|RGB} indicate the particular pattern type - these are components from the second row, second and third columns, respectively. For example, the above pattern has very popular "BG" type.</P></LI></UL>
<HR>

<P></P>
<P style="TEXT-INDENT: 2em"><A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvThreshold">cvThreshold</A> 对单通道数组应用固定阈值操作。典型的是对灰度图像进行阈值操作得到二值图像。(<A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cxcore.htm#decl_cvCmpS">cvCmpS</A> 也可以达到此目的) 或者是去掉噪声，例如过滤很小或很大象素值的图像点。有好几种对图像取阈值的方法，本函数支持的方法由 </P>
<P style="TEXT-INDENT: 2em">threshold_type 确定</P>
<P style="TEXT-INDENT: 2em">:</P>
<P style="TEXT-INDENT: 2em">threshold_type=CV_THRESH_BINARY:dst(x,y) = max_value, if src(x,y)&gt;threshold 0, otherwisethreshold_type=CV_THRESH_BINARY_INV:dst(x,y) = 0, if src(x,y)&gt;threshold max_value, otherwisethreshold_type=CV_THRESH_TRUNC:dst(x,y) = threshold, if src(x,y)&gt;threshold src(x,y), otherwisethreshold_type=CV_THRESH_TOZERO:dst(x,y) = src(x,y), if (x,y)&gt;threshold 0, otherwisethreshold_type=CV_THRESH_TOZERO_INV:dst(x,y) = 0, if src(x,y)&gt;threshold src(x,y), otherwise</P>
<P style="TEXT-INDENT: 2em">下面是图形化的阈值描述：</P>
<P style="TEXT-INDENT: 2em"><IMG src="file:///D:/程序/OpenCV/docs/ref/pics/threshold.png" border=0> 
</P><HR>

<P></P>
<P style="TEXT-INDENT: 2em"><A href="file:///D:/程序/OpenCV/docs/ref/opencvref_cv.HTM#decl_cvAdaptiveThreshold">cvAdaptiveThreshold</A> 将灰度图像变换到二值图像，采用下面公式：</P>
<P style="TEXT-INDENT: 2em">threshold_type=</P>
<P style="TEXT-INDENT: 2em">CV_THRESH_BINARY</P>
<P style="TEXT-INDENT: 2em">:dst(x,y) = max_value, if src(x,y)&gt;T(x,y) 0, otherwisethreshold_type=</P>
<P style="TEXT-INDENT: 2em">CV_THRESH_BINARY_INV</P>
<P style="TEXT-INDENT: 2em">:dst(x,y) = 0, if src(x,y)&gt;T(x,y) max_value, otherwise</P>
<P style="TEXT-INDENT: 2em">其中 TI 是为每一个象素点单独计算的阈值</P>
<P style="TEXT-INDENT: 2em">对方法 CV_ADAPTIVE_THRESH_MEAN_C，它是 block_size × block_size 块中的象素点，被参数 param1 所减，得到的均值，</P>
<P style="TEXT-INDENT: 2em">对方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C 它是 block_size × block_size 块中的象素点，被参数 param1 所减，得到的加权和(gaussian)。</P>
<P style="TEXT-INDENT: 2em"></P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200883935589</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200883935589</guid>
    <pubDate>Wed, 3 Sep 2008 09:03:55 +0800</pubDate>
    <dcterms:modified>2008-09-03T09:03:55+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[gcc与obj文件，动态链接文件和ELF文件(转载)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200882840851</link>
    <description><![CDATA[<div>1、obj文件 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;程序员编写程序，其实就是编写出一个2进制（binary）文件。假如我们声明一个变量char&nbsp;c，也就是声明需要一个8bit的空间，那么就需要向系统声明豫留8bit的空间，怎么做到这一点呢？就是编译一个特殊的2进制文件--obj文件，用gcc编译的C语言得到的执行文件，里面不仅包含CPU指令，还有很多别的信息在里面，它有很多格式COFF、ELF……等等，在最后一道编译过程中，链接器（linker）ld会加载一堆信息进入可执行文件。例如，当有多个编译后等待链接的.o这种可重定位（relocatable）文件，既然这些文件里面参数或者函数名的相对位置只是本身所在.o文件的相对位置，就有一些信息要告诉链接编辑器（link&nbsp;editor）怎么修改section的内容，来做relocate，也就是做地址的重新参照以便合成一个新的可执行文件。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个obj文件有两个重要时期，一个是正在链接（link）的时候，也就是处在 <BR>硬盘（disk）里的时候；一个是正在执行的时候，当然这时它位于内存里。我们平时说的ld&nbsp;linker其实叫link&nbsp;editor，最后编译的步骤ld把该有的信息写进可执行文件。如果是static&nbsp;link就会去找libxxx.a的函数库文件，把想要的程序代码片段拷贝一份进可执行文件，并且做成relocation后，把跳来跳去的参照写进可执行文件，这个文件就可以执行。 <BR>2、动态链接文件 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;相对于静态链接（static&nbsp;link）拷贝原有的程序代码进可执行文件，动态链接不那样做，link&nbsp;editor把一些信息写进可执行文件而已。例如，需要的程序库名、函数名等，最后执行的时候，必须呼叫dynamic&nbsp;linker來做program <BR>intepreter，dynamic&nbsp;linker会根据需要的函数库名称，把想要的函数名字创造一个可执行的image放到内存，所以执行有动态链接的执行文件，最后通常都是由OS的exec系列的system&nbsp;call与dynamic&nbsp;linker如ld.so联合完成。 <BR>dynamic&nbsp;linker通常会做如下工作： <BR>（1）把可执行文件的内容加载到process&nbsp;image <BR>（2）把shared&nbsp;obj需要的东西加载到process&nbsp;image <BR>（3）完成relocation <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本来这些obj文件里面的虚拟地址应该和文件的地址有相对应的偏移（offset），而文件首地址通常是0x08040800，这是绝对虚拟地址，但它只适合可执行文件，例如Linux&nbsp;extuable&nbsp;file通常是： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file&nbsp;offset&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;&nbsp;address <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-----------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------------- <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x08048000 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x08048100 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shared&nbsp;obj函数库里的程序代码必须为位置无关代码Position <BR>Independent&nbsp;Code&nbsp;(PIC)，也就是说它的地址可能会随不同process而有不同，例如，一个程序只用了libc.so、ld-linux.so，通常这时候lib.so是从0x40017000开始的，但如果另一个程序多用一个libm.so，那么libc.so从0x40034000开始两个的printf参照（reference），就会有不同的地址，所以这种动态函数库的内部资料就要说明这些code是PIC。 <BR>3、ELF文件 <BR>（1）简介 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在最常用的是一种叫ELF格式（executable&nbsp;and&nbsp;linkable&nbsp;format)的执行文件，ELF定义了一些变量与信息使得动态链接更有弹性，一个ELF的2进制文件按照spec&nbsp;1.1版的说法有6种，下列是较常见的： <BR><BR>relocatable：它就是编译时产生的.o文件，包含了代码和数据（这些数据是和其&nbsp;他&nbsp;重定位文件和共享的object文件一起连接时使用的） <BR><BR>executable：它就是最后的可执行文件，包含了代码和数据shared&nbsp;obj：它就是在/lib&nbsp;/usr/lib下那些可动态链接的函数库文件，包含了代码和数据（这些数据是在连接时候被连接器ld和运行时动态连接器使用的） <BR><BR>core：Core&nbsp;Dump时产生的文件，包含了一堆garbage数据 <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意：这些ELF文件已经是广义的2进制文件，不单指可执行文件。 <BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>（2）ELF组成 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个ELF&nbsp;obj文件随它存在的时期有不一样的需求和组成名字，在要链接linking时期位于硬盘，包含了： <BR>ELF&nbsp;header <BR>program&nbsp;header&nbsp;table&nbsp;(可以不要) <BR>section&nbsp;0 <BR>section&nbsp;1 <BR>section&nbsp;2 <BR>section&nbsp;3 <BR>section&nbsp;... <BR>section&nbsp;n <BR>section&nbsp;header&nbsp;table&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ELF&nbsp;header放了ELF定义的一些ELF格式识别字串（俗称magic&nbsp;number），还有obj文件（shared&nbsp;obj,relocatable或者executable）这些一般（general）的信息；program&nbsp;header&nbsp;table是描述了段（segment）信息的结构数组和一些为程序运行准备的信息。segement和section不大一样，是属于程序执行时期的元素，所以在程序执行时期是必要的，在链接时期是不必要的，所以如果程序不做链接动作，只要有program&nbsp;header&nbsp;table就可以；section&nbsp;header&nbsp;table就是一个索引表，来记录各个section的索引，sections就是把需要的资料根据属性用途分门别类后的小集合，有.bss&nbsp;.data&nbsp;.init&nbsp;.debug&nbsp;.dynamic&nbsp;.fini&nbsp;.text………，其中比较重要的有： <BR>.text <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;里面保存真的CPU指令 <BR>.bss <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;保存没有initialize的data <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主要是声明的global与static变量 <BR>.data <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;保存initialize的data <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;写程序用到的函数名，变量名分布在多个source&nbsp;code目录里时，需要一个 <BR>参照（reference）的信息做连接这些名字，symbol是着被给linker来做连接用的，因为obj文件分散存在，要把这些obj文件的代码集合起来，就要靠symbol <BR>来辨别，string&nbsp;table存有很多行字串，每行字串用NULL来分开，每行字串就是symbol和section的名字。symbol&nbsp;table是一张表，存有将来要定址或重新定址所要的symbol定义和参照信息。shared&nbsp;lib的obj文件还有.dynsym这个section，里面存有dynamic&nbsp;symbol&nbsp;table，动态链接的时候使用。另外，如果将来的程序要用debug工具调试，编译时要加-g这个选项，它会根据sumbol <BR>和string&nbsp;table放进debug多需要的信息给obj文件，这样的信息现在大都用一种叫stab的格式存放，这同时也会让执行文件大小增加到将近3倍。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在ELF不同的文件型态里，ELF定义的信息该有的都有，header&nbsp;section……只是里面的值或有不同而已。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unix/Linux通常从一个_start函数开始而不是从main开始，_start后来会调用main,所以如果要精简程序，就不要用gcc编译，直接汇编用_start就可以了（^_^）。另外像section&nbsp;header&nbsp;table如果不需要做链接也可以不要，还有可执行文件的symbol&nbsp;table等，其实这些可以全部不要，不过要用汇编并同GAS来生成可执行文件。其实还有很多东西，这就是为什么即使根本没有调用任何函数，做成的动态文件，用ldd看一定有ld-linux.so&nbsp;libc.so了。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而一个存在内存中的process&nbsp;image，如下所示： <BR>ELF&nbsp;header <BR>program&nbsp;header&nbsp;table <BR>segment&nbsp;0 <BR>segment&nbsp;1 <BR>segment&nbsp;2 <BR>segment&nbsp;... <BR>segment&nbsp;n <BR>section&nbsp;header&nbsp;table&nbsp;(可以不要) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Segment有Text，Data等，根据OS定义不同，Text根据存在硬盘文件里的.txt&nbsp;.fini等section来的，Data段根据.data&nbsp;.bss等section来的，一个segment通常包含了&nbsp;一个或一个以上的section，这些section在程序员角度来看更显的重要。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在支持ELF的系统上，一个程序是由可执行文件或者加上一些shared&nbsp;obj文件组成。为了执行这样的程序，系统使用那些文件创建进程的内存映像。为了使一个ELF文件装载到内存，必须有一个program&nbsp;header&nbsp;table(该program&nbsp;header&nbsp;table&nbsp;是一个描述段信息的结构数组和一些为程序运行准备的信息)。这里有几个在ELF文档中定义的比较特别的sections。以下这些是对程序特别有用的： <BR>.fini <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;保存进程终止代码指令 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此，当一个程序正常退出时，系统安排执行这个section中的代码 <BR>.init <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;保存可执行指令，它构成了进程的初始化代码 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此，当一个程序开始运行时，在main函数被调用前（C语言称为main）, <BR>系统安排执行这个section中的代码 <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.init和.fini&nbsp;sections的存在有着特别的目的。假如一个函数放到.init&nbsp;section，在main函数执行前系统就会执行它。同理，假如一个函数放到.fini&nbsp;section，在main函数返回后该函数就会执行。该特性被C++编译器使用，完成全局的构造和析构函数功能。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当ELF可执行文件被执行，系统将在把控制权交给可执行文件前装载所以相关 <BR>的共享object文件。构造正确的.init和.fini&nbsp;sections,构造函数和析构函数将以正确的次序被调用。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unix/Linux的虚拟内存使用有这样的范围： <BR><BR>user&nbsp;area <BR><BR>0x0&nbsp;~&nbsp;0x0bffffff&nbsp;&nbsp;-&gt;;&nbsp;3GB <BR><BR>kernel&nbsp;area <BR><BR>0x0c000000&nbsp;~&nbsp;0xffffffff&nbsp;&nbsp;-&gt;;&nbsp;1GB <BR><BR>以下面程序代码为例： <BR>int&nbsp;global; <BR><BR>static&nbsp;int&nbsp;func1&nbsp;(void) <BR>{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;b; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;*c; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;d; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func2(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;1; <BR>} <BR>int&nbsp;func2&nbsp;(void) <BR>{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;c; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;d; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;2; <BR>} <BR>int&nbsp;main(void) <BR>{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;b; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;init&nbsp;=&nbsp;3; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func1(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;3; <BR>} <BR><BR>那么从一个Linux执行文件在内存中看起来是这个样子： <BR><BR>i386&nbsp;Linux的执行image <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Virtual&nbsp;&nbsp;&nbsp;Address&nbsp;&nbsp;Allocation <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|----------------------------------|0x0&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|-----------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;Thread&nbsp;&nbsp;stack&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|------------------------------|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|------------------------------|&nbsp;&nbsp;|0x08048000&nbsp;Text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;executable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;…… <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|------------------------------|&nbsp;&nbsp;|0x40000000&nbsp;ld-linux.so <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libm.so <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;shared&nbsp;&nbsp;&nbsp;&nbsp;LIB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libc.so <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;Stack&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3GB|&nbsp;|-----------------------------&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|------------------------------|&nbsp;&nbsp;|0xc0000000 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;Kernel&nbsp;Code&nbsp;and&nbsp;Data&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|-------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4GB|---------------------------------&nbsp;&nbsp;&nbsp;|0xffffffff <BR><BR>其中0x08048000&nbsp;~&nbsp;0x40000000&nbsp;~&nbsp;0xc0000000是这样存在的。 <BR><BR>从C角度看的image: <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x08048000 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--------------------------------------------------------| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|--------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;main()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xxxx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;func1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（instrction）&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xxxx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;func2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xxxx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;int&nbsp;global&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;b(main)&nbsp;&nbsp;static&nbsp;int&nbsp;b(func1)&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;c(func2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;malloc(int)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Heap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\|/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--------------------------------------------------------| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;0x40000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--------------------------------------------------------| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/|\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;func2&nbsp;int&nbsp;c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stack&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;func1&nbsp;int&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stack&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;main()&nbsp;&nbsp;argv[0]&nbsp;&nbsp;argv[1]&nbsp;&nbsp;…&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|-------------------------------------------------|&nbsp;&nbsp;| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--------------------------------------------------------| <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0xbfffffff <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;所以可以清楚的知道不同变量（global，static&nbsp;or&nbsp;auto）的生命周期（storage&nbsp;class），和不同变量的有效范围（scope）。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kernel&nbsp;code和data当然存在内存中，所以实际上都还要经过page&nbsp;table <BR>转成实际地址。在0x0~&nbsp;0xbfffffff中的page&nbsp;table，每个process有不同page <BR>table，但在0xc0000000以下的page&nbsp;table，则都一样。<BR></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200882840851</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200882840851</guid>
    <pubDate>Tue, 2 Sep 2008 08:40:08 +0800</pubDate>
    <dcterms:modified>2008-09-02T08:40:08+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[勤快]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320087309733800</link>
    <description><![CDATA[<div>勤动手、勤动脑<br>勤动脑举例，如果，你的蚊帐破了，你会去想到补起来，大多数人就到此为止。但是勤动脑的人会想，蚊帐为什么会破，我的蚊帐破了，别人的蚊帐也会破的，怎么补更快更好，就会想到一个设计补蚊帐的东西。<br></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320087309733800</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320087309733800</guid>
    <pubDate>Sat, 30 Aug 2008 09:07:33 +0800</pubDate>
    <dcterms:modified>2008-08-30T09:07:33+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[NFS FAQ]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320087296535349</link>
    <description><![CDATA[<div><pre><b> NFS PCS/FAQ</b><br><br><a href="http://www.pimpworks.org/sun/nfs.html#nfs1">1.0: About NFS</a></pre>
<pre><b><i>2.0: Debugging NFS</i></b><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs2">2.1: share and exportfs</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs3">2.2: showmount</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs4">2.3: nfsstat</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs5">2.4: rpcinfo</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs6">2.5: etherfind and snoop</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs7">2.6 Running a snoop of NFS requests:</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs8">2.7 Lockd debug hints</a></pre>
<pre><b><i>3.0: Common How Tos</i></b><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs9">3.1: Exporting Filesystems Under SunOS</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs10">3.2: Exporting Filesystems Under Solaris</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs11">3.3: Mounting Filesystems Under SunOS</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs12">3.4: Mounting Filesystems Under Solaris</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs13">3.5: Setting Up Secure NFS</a></pre>
<pre><b><i>4.0: Some Frequently Asked Questions</i></b><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs14">4.1: Miscellaneous NFS Questions</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs15">4.2: Problems Mounting Filesystems on a Client</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs16">4.3: Common NFS Client Errors Including NFS Server Not Responding</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs17">4.4: Problems Umounting Filesystems on a Client</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs18">4.5: Interoperability Problems With Non-Sun Systems</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs19">4.6: Common NFS Server Errors</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs20">4.7: Common nfsd Error Message on NFS Servers</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs21">4.8: Common rpc.mountd Error Messages on NFS Servers</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs22">4.9: Common rpc.lockd &amp; rpc.statd Error Messages</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs23">4.10: NFS Related Shutdown Errors</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs24">4.11: NFS Performance Tuning</a></pre>
<pre><b><i>5.0: Patches</i></b><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs25">5.1: Core NFS Patches for SunOS</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs26">5.2: Patches Related to NFS for SunOS</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs27">5.3: Core NFS Patches for Solaris</a><br>  <a href="http://www.pimpworks.org/sun/nfs.html#nfs28">5.4: Patches Related to NFS for Solaris</a></pre>
<pre> <a ><b><i>1.0: About NFS</i></b></a><br><br>This Tip Sheet documents a wide variety of information concerning NFS,<br>as implemented in the SunOS and Solaris operating systems. It is<br>intended as both an introduction to NFS and as a guide to the most<br>common problems. There are many more complete references to NFS, a few<br>of which are noted in section 7.4 and 7.5.<br><br>The following terms are important to an understanding of NFS:<br><br>The NFS SERVER is the machine that makes file systems available to<br>the network. It does so by either EXPORTING (SunOS term) or SHARING<br>(Solaris term) them.<br><br>The NFS CLIENT is the machine that accesses file systems that have<br>been made available. It does so by MOUNTING them.<br><br>A number of different daemons are involved with NFS:<br><br>RPC.MOUNTD only runs on NFS servers. It answers initial requests from<br>clients for file systems.<br><br>NFSD runs on NFS servers. They are the daemons that deal<br>with the majority of the client NFS requests.<br><br>On SunOS 4.1.X, BIODS (block I/O daemons) help clients with<br>their NFS requests.  These do not exist on Solaris 2.X.<br><br>LOCKD and STATD are a set of daemons that keep track of locks on NFS<br>files. There will typically be a set of daemons running on a client<br>and server.<br><br>NFS partitions can be mounted in one of two ways, hard or soft.<br><br>HARD MOUNTS are permanent mounts designed to look just like any<br>normal, local file system. If a partition that is hard mounted becomes<br>unavailable, client programs will keep trying to access it forever.<br>This will cause local processes to lock when a hard mounted disk goes<br>away. Hard mounts are the default type of mount.<br><br>SOFT MOUNTS will fail after a few retries if a remote partition<br>becomes unavailable. This is a problem if you are writing to the<br>partition, because you can never be sure that a write will actually<br>get processed  on the other hand, your local processes will not lock<br>up if that partition does go away. In general, soft mounts should only<br>be used if you are solely reading from a disk and even then it should<br>be understood that the mount is an unreliable one. If you soft mount a<br>partition that will be written to, you are nearly guaranteeing that<br>you will have problems.<br><br>There are a number of files related to NFS:<br><br>/etc/exports (SunOS) or /etc/dfs/dfstab (Solaris) lists which files to<br>export on a Server. These file are maintained by hand.<br><br>/etc/xtab (SunOS) or /etc/dfs/sharetab (Solaris) lists the filesystems<br>that actually are currently exported. They are maintained by exportfs<br>and share, respectively.<br><br>/etc/rmtab on a server lists filesystems that are remotely mounted by<br>clients. This file is maintained by rpc.mountd.<br><br>/etc/fstab (SunOS) or /etc/vfstab (Solaris) lists which files to mount<br>on a client. These files are maintained by hand.<br><br>/etc/mtab (SunOS) or /etc/mnttab (Solaris) on a client lists<br>filesystems which are currently mounted onto that client. The mount<br>and umount commands modify this file.</pre>
<pre><b><i>2.0 Debugging NFS</i></b><br><br> General NFS Debugging Note<br><br>When NFS is not working or working intermittently, it can be very<br>difficult to track down what exactly is causing the problem. The<br>following tools are the best ones available to figure out what exactly<br>NFS is doing.</pre>
<pre> <i><a ><b>2.1: share and exportfs</b></a><br></i><br>share (on Solaris) and exportfs (on SunOS) are good tools to use to<br>see exactly how a NFS server is exporting its filesystems. Simply log<br>on to the NFS server and run the command that is appropriate for the<br>OS.<br><br>  SunOS:<br>  # exportfs<br>  /usr -root=koeller<br>  /mnt<br>  /tmp<br><br>The above shows that /mnt and /tmp are exported normally. Since we see<br>neither rw or ro as options, this means that the default is being<br>used, which is rw to the world. In addition /usr gives root<br>permissions to the machine koeller.<br><br>  Solaris:<br>  # share<br>  -               /var   rw=engineering   ""<br>  -               /usr/sbin   rw=lab-manta.corp.sun.com   ""<br>  -               /usr/local   rw   ""<br><br>The above shows that /usr/local is exported normally, /var is exported<br>only to engineering (which happens to be a netgroup) and /usr/sbin is<br>exported only to lab-manta.corp.sun.com (which is a machine).<br><br>Note: netgroups are only supported if you are running NIS or NIS+.<br>Consult documentation on those products for how to set up netgroups on<br>your machines</pre>
<pre> <a ><b><i>2.2: showmount</i></b></a><br><br>showmount, used with the -e option, can also show how a NFS server is<br>exporting its file systems. Its benefit is that it works over the<br>network, so you can see exactly what your NFS client is being offered.<br>However, showmount does not show all of the mount options and thus<br>you must sometimes use share or exportfs, as described in<br>section 2.1. When you do a test with showmount, do it from<br>the NFS client that is having problems:<br><br>  # showmount -e psi<br>  export list for psi:<br>  /var       engineering<br>  /usr/sbin  lab-manta.corp.sun.com<br>  /usr/local (everyone)<br><br>  # showmount -e crimson<br>  export list for crimson:<br>  /usr (everyone)<br>  /mnt (everyone)<br>  /tmp (everyone)<br><br>Note that showmount only displays: the partition and who can mount<br>it. We will not see any other options displayed. In the example above,<br>there are no restrictions on who can mount crimson's partitions and<br>so showmount lists (everyone).</pre>
<pre> <a ><b><font color="blue"> </font><i>2.3: nfsstat</i></b></a><br><br>The nfsstat command gives diagnostics on what type of messages are<br>being sent via NFS. It can be run with either the -c option, to show<br>the stats of an NFS client, or the -s option, to show the stats of an<br>NFS server. When we run 'nfsstat -c' we see the following:<br><br>  # nfsstat -c<br><br>  Client rpc:<br>  calls      badcalls   retrans    badxids    timeouts   waits      newcreds<br>  45176      1          45         3          45         0          0<br>  badverfs   timers     toobig     nomem      cantsend   bufulocks<br>  0          80         0          0          0          0<br><br>  Client nfs:<br>  calls      badcalls   clgets     cltoomany<br>  44866      1          44866      0<br><br>  Version 2: (44866 calls)<br>  null       getattr    setattr    root       lookup     readlink   read<br>  0 0%%       7453 16%%   692 1%%     0 0%%       15225 33%%  55 0%%      13880<br>30%%<br>  wrcache    write      create     remove     rename     link       symlink<br>  0 0%%       5162 11%%   623 1%%     914 2%%     6 0%%       306 0%%     0 0%%<br>  mkdir      rmdir      readdir    statfs<br>  15 0%%      0 0%%       467 1%%     68 0%%<br><br>The rpc stats at the top are probably the most useful. High 'retrans'<br>and 'timeout' values can indicate performance or network issues. The<br>client nfs section can show you what types of NFS calls are taking up<br>the most time. This can be useful if you're trying to figure out what<br>is hogging your NFS. For the most part, the nfsstat command is most<br>useful when you are doing network and performance tuning. Section 7.4<br>and 7.5 list books that give some information on this  they are useful<br>to<br>make more sense of the nfsstat statistics.</pre>
<pre> <a ><b><i>2.4: rpcinfo</i></b></a><br><br>You can test that you have a good, solid NFS connection to your NFS<br>server via the rpcinfo command. As explained in the man page, this<br>program provides information on various rpc daemons, such as nfsd,<br>rpc.mountd, rpc.statd and rpc.lockd. Its biggest use is to determine<br>that one of these daemons is responding on the NFS server. The<br>following examples all show the indicated daemons correctly<br>responding. If instead you get complaints about a service 'not<br>responding,' there might be a problem.<br><br>To see that nfsd is responding:<br><br>  # rpcinfo -T udp crimson nfs<br>  program 100003 version 2 ready and waiting<br><br>[crimson is the name of the remote machine that I am testing]<br><br>To see that mountd is responding:<br><br>  # rpcinfo -T udp crimson mountd<br>  program 100005 version 1 ready and waiting<br>  program 100005 version 2 ready and waiting<br><br>To see that lockd is responding:<br><br>  # rpcinfo -T udp crimson nlockmgr<br>  program 100021 version 1 ready and waiting<br>  rpcinfo: RPC: Procedure unavailable<br>  program 100021 version 2 is not available<br>  program 100021 version 3 ready and waiting<br><br>  # rpcinfo -T udp crimson llockmgr<br>  program 100020 version 2 ready and waiting<br><br>(the procedure unavailable error for the nlockmgr seems to be normal<br>for most systems)<br><br>If you run rpcinfo and determine that certain rpc services are not<br>responding, check those daemons on the master.<br><br>If none of the above works, you can verify that RPC services are<br>working at all on the server by running:<br><br>  # rpcinfo remote-machine-name<br><br>If this gives errors too, there is probably an issue with portmap<br>(SunOS) or rpcbind (Solaris).<br><br>[Note: the above rpcinfo commands will vary slightly under Solaris 2.5<br>or higher, as those OSes will offer NFS version 3, running over TCP,<br>rather than UDP.]</pre>
<pre> <a ><b><i>2.5: etherfind and snoop</i></b></a><br><br>If all else fails and NFS still doesn't seem to be working right, the<br>last resort in debugging is to use a network sniffer program, such as<br>etherfind (SunOS) or snoop (Solaris). This can give you some<br>indication of whether remote machines are responding at all. Below is<br>an example of a totally normal NFS interaction, shown by snoop on<br>Solaris:<br><br>  # snoop psi and rainbow-16<br>  Using device /dev/le (promiscuous mode)<br>           psi -&gt; rainbow-16   NFS C GETATTR FH=4141<br>    rainbow-16 -&gt; psi          NFS R GETATTR OK<br>           psi -&gt; rainbow-16   NFS C READDIR FH=4141 Cookie=2600<br>    rainbow-16 -&gt; psi          NFS R READDIR OK 1 entries (No more)<br><br>These were the results when an 'ls' was run on 'psi' in a directory<br>that was mounted from 'rainbow-16'. The lines labelled 'C' are NFS<br>requests, while the lines labelled 'R' are NFS replies. Through snoop<br>you can easily see: NFS not being responding to (you would get lots of<br>'C' lines without 'R' replies to them) and also certain errors<br>(timeouts and retransmits particularly). The man page on snoop gives<br>some indication of how to make more in-depth use of the tool. In<br>general, it should only be used for very complex issues, where NFS is<br>behaving very oddly and even then you must be very good with NFS<br>to perceive unexpected behavior.  See the next section for<br>more tips on snoop.</pre>
<pre> <a ><b><i>2.6  Running a snoop of NFS requests:</i></b></a><br><br>This is best done from a third, uninvolved machine.  If the<br>machine that you are trying to debug is on "systemA", then trace<br>the packets going to and from "systemA" as follows:<br><br>snoop -o /var/snoop.out systemA<br><br>Alternatively, snoop between systemA and clientB:<br><br>snoop -o /var/snoop.out systemA clientB<br><br>snoop will run in the window (do not put into background), with a counter<br>of the packets in the corner of the screen.  It will dump all the<br>packets into a raw snoop file.  When the "network event" occurs,<br>wait a couple of seconds and then kill the snoop job.  If the network<br>event includes error messages in /var/adm/messages, please send<br>us the /var/adm/messages and the raw snoop file (/var/snoop.out).<br><br>You can read the snoop file with snoop -i /var/snoop.out more.  There<br>are a variety of options in the snoop man page to increase verbosity,<br>and/or to look at specific packets.<br><br>Please note that if disk space becomes an issue, you must<br>take steps similar to those listed above.  A very large snoop file<br>can be created in two or three minutes, so snooping is best reserved<br>for easily reproduced events.</pre>
<pre> <a ><b><i>2.7  Lockd debug hints</i></b></a><br><br>Please see section 4.9: Common rpc.lockd &amp; rpc.statd Error Messages<br>for information regarding specific lockd and statd problems.<br><br>Generally you can pick out problem clients by snooping and/or<br>putting lockd into debug mode.  Sections 2.5 and 2.6 cover snoop.<br><br>How to put the Solaris 2.3 and 2.4 lockd into debug mode:<br>Edit the line in the /etc/init.d/nfs.client script that starts<br>up lockd to start it with -d3 and redirect stdout to a<br>filesystem with ALOT of disk space.<br><br>   /usr/lib/nfs/lockd -d3 &gt; /var/lockd.debug.out<br><br>Note that lockd always creates an empty file in the pwd, called<br>logfile when it is running in debug mode.  Disregard this file.<br><br>If disk space becomes an issue from doing the lockd debug mode,<br>you will have to stop lockd and restart it.<br><br>If you turn the above command from a shell, make sure it is<br>a bourne or korn shell (sh or ksh).<br><br>How to put the Solaris 2.5 lockd into debug mode:<br><br>You will have to do this from a shell, preferably<br>a command tool window.  You must capture the debug output<br>that scrolls by into a script file:<br><br>  script /var/lockd.out<br>  /usr/lib/nfs/lockd -d3<br><br>After you are done debugging, CTRL/C the lockd job since it does<br>not fork and exec to the background.  Then exit or CTRL/D the<br>script job.  The debug output will be in /var/lockd.out.<br><br>Please note that Solaris 2.5 will also log more detailed debug output into<br>the /var/adm/messages file.  We will need that also.<br><br>How to run a truss of lockd (you rarely need to do this):<br><br>Just modify the start of lockd to be a truss of the lockd process.<br>You will need even more disk space to do this!<br><br>For Solaris 2.3 and 2.4:<br>truss  -o /var/truss.out -vall -f /usr/lib/nfs/lockd<br>-d3&gt;/var/lockd.debug.out<br><br>For Solaris 2.5:<br>  script /var/lockd.out<br>  truss -o /var/truss.out -vall -f /usr/lib/nfs/lockd -d3<br><br>CTRL/C the script job (and exit from the script shell if on 2.5) after you<br>have reproduced the problem.<br><br>If disk space becomes an issue from doing the truss, use a cron job<br>to:<br>1.  stop running truss<br>2.  move "current" truss file to "old" truss file<br>3.  get PID of lockd<br>4.  truss -o /var/truss.out.current -vall -f -p PID (PID from step 3).</pre>
<pre><b><i><font size="4">3.0 Common How-Tos</font></i></b><br><br> <i><a ><b>3.1: Exporting Filesystems Under SunOS</b></a><br></i><br>In order to export a fs under SunOS, you must first edit the file<br>/etc/exports on your NFS server, adding a line for the new filesystem.<br>For example, the following /etc/exports file is for a server that<br>makes available the filesystems /usr, /var/spool/mail and /home:<br><br>  # cat /etc/exports<br>  /usr<br>  /var/spool/mail<br>  /home<br><br>You can add normal mount options to these lines, such as ro, rw and<br>root. These options are fully described in the exports man page. The<br>following example shows our /etc/exports file, but this time with the<br>filesystems all being exported read only:<br><br>  # cat /etc/exports<br>  /usr  -ro<br>  /var/spool/mail       -ro<br>  /home -ro<br><br>If your machine is already exporting filesystems and you are adding a<br>new one, simply run the exportfs command to make this new<br>filesystem available:<br><br>  # exportfs -a<br><br>If you have never exported filesystems from this machine before, you<br>should reboot it after editing the /etc/exports file. This will cause<br>rpc.mountd and nfsd to get started and will also automatically export<br>out the filesystems.</pre>
<pre> <a ><b><i>3.2: Exporting Filesystems Under Solaris</i></b></a><br><br>You must edit the file /etc/dfs/dfstab in order to make files<br>automatically export on a Solaris system. The standard syntax of lines<br>in that file is:<br><br>  share -F nfs partition<br><br>For example, the following /etc/dfs/dfstab file is for a server that<br>makes available the filesystems /usr, /var/spool/mail and /home:<br><br>  share -F nfs /usr<br>  share -F nfs /var/spool/mail<br>  share -F nfs /home<br><br>You can add normal mount options to these lines, such as ro, rw and<br>root. this is done by proceeding the options with a -o flag. These<br>options are fully described in the share man page. The following<br>example shows our /etc/dfs/dfstab file, but this time with the<br>filesystems all being exported read only:<br><br>  share -F nfs -o ro /usr<br>  share -F nfs -o ro /var/spool/mail<br>  share -F nfs -o ro /home<br><br>If your machine is already exporting filesystems and you are adding a<br>new one, simply run the shareall command to make this new<br>filesystem available:<br><br>  # shareall<br><br>If you have never exported filesystems from this machine before, you<br>must run the nfs.server script:<br><br>  # /etc/init.d/nfs.server start<br><br>(The NFS Server will come up fine on the next boot, now that an<br>/etc/dfs/dfstab file exists)</pre>
<pre> <a ><b><i>3.3: Mounting Filesystems Under SunOS</i></b></a><br><br>You can always mount file systems with the mount command, with the<br>following syntax:<br><br>  mount remotemachine:/remotepartition /localpartition<br><br>For example:<br><br>  mount bigserver:/usr/local /usr/local<br><br>You might also give the mount command any of the general mount options.<br>For example, to mount /usr/local read only, you would use the command:<br><br>  mount -o ro bigserver:/usr/local /usr/local<br><br>If you wish a filesystem to get mounted every time the machine is<br>booted, you must edit the /etc/fstab file. The syntax is:<br><br>  remotemach:/remotepart        /localpart      nfs     [options]       0 0<br><br>The options field is optional and can be left out if none are needed.<br>To make /usr/local mount automatically, you would add the following to<br>your /etc/fstab:<br><br>  bigserver:/usr/local  /usr/local      nfs     0 0<br><br>To make it mount read only, you could use:<br><br>  bigserver:/usr/local  /usr/local      nfs     ro      0 0</pre>
<pre> <a ><b><i>3.4: Mounting Filesystems Under Solaris</i></b></a><br><br>Section 3.3, above, shows how to correctly use the mount command, to<br>interactively mount files. It works exactly the same under Solaris.<br><br>If you wish a filesystem to get mounted every time the machine is<br>booted, you must edit the /etc/vfstab file. The syntax is:<br><br>  remotemach:/remotepart - localpart nfs - yes [options]<br><br>For example, to mount the /usr/local partition, you would enter:<br><br>  bigserver:/usr/local - /usr/local nfs - yes -<br><br>To mount it read-only, you would enter:<br><br>  bigserver:/usr/local - /usr/local nfs - yes ro<br><br>Consult the vfstab man page if you're interested in knowing what the<br>fields that contain "-"s and "yes" are for. For the most part,<br>they're<br>only relevant for non-NFS mounts.</pre>
<pre> <a ><b><i>3.5: Setting Up Secure NFS</i></b></a><br><br>NFS has built-in private-key encryption routines that can<br>provide added security. To use this functionality, a<br>partition must be both exported with the "secure" option and mounted<br>with the "secure" option. In addition, either NIS or NIS+ must be<br>available. Secure NFS will not work without one of these naming<br>services.<br><br>To add the -secure option to the /secret/top partition on a SunOS<br>machine, the following exports entry would be needed on the server:<br><br>  /secret/top   -secure<br><br>In addition, the following fstab entry would be needed on the client:<br><br>  server:/secret/top    /secret/top     nfs     rw,secure       0 0<br><br>(Solaris machines would have to have the -secure option similarly<br>added.)<br><br>If you are running NIS+, you will not need to do anything further to<br>access the partition, since NIS+ users and NIS+ hosts will already have<br>credentials created for them.<br><br>If you are running NIS, you must create credentials for all users and<br>hosts that might want to access the secure partition.<br><br>Root can add credentials for users with the following command:<br><br>  # newkey -u username<br><br>Users can create their own credentials with the following command:<br><br>  $ chkey<br><br>The passwd supplied to these programs should be the same as the user's<br>passwd.<br><br>Root can add credentials for hosts with the following command:<br><br>  # newkey -h machinename<br><br>The passwd supplied to newkey in this case should be the same as the<br>machine's root passwd.<br><br>It is important to note that rpc.yppasswd must be running on your NIS<br>server for these commands to work. In addition, push out<br>publickey maps afterwards to make sure that the most up-to-date<br>credential information is available.<br><br>Once this is all done, secure NFS should work on your NIS network,<br>with two caveats: First, keyserv must be running on your client<br>machines. If this is not the case, adjust your rc files, so that it<br>automatically starts up. Second, if a user does not supply a passwd<br>when logging in (due to a .rhosts or /etc/hosts.equiv for example) or<br>if his secure key is different than his passwd, then he will need to<br>execute the command 'keylogin' before he can access the secure NFS<br>partition.</pre>
<pre><b><i><font size="4">4.0 Frequently Asked Questions</font></i></b></pre>
<pre> <a ><b><i>4.1: Miscellaneous NFS Questions</i></b></a><br><br><b>Q</b>: What version of NFS does Sun implement?<br><br><b>A</b>: All of the currently supported revisions of SunOS and Solaris<br>support NFS version 2, over UDP. In addition, Solaris 2.5 will support<br>NFS version 3, over TCP. Although NFS version 3 is the default<br>for Solaris 2.5 and up, the NFS will fall back to version 2 if other<br>machines do not have version 3 capability.<br><br><b>Q</b>: What do these NFS Error Codes mean (e.g. NFS write error 49)?<br><br><b>A</b>: On SunOS, you can find a list of error codes in the intro(2) man<br>page:<br><br>  # man 2 intro<br><br>On Solaris, you can consult the /usr/include/sys/errno.h file. SRDB<br>#10946, available through SunSolve also lists some of the NFS error<br>codes.<br><br><b>Q</b>: Why isn't my netgroup entry working?<br><br><b>A1</b>: There are lots of factors related to netgroup. First, you must be<br>using either NIS or NIS+, to propagate the netgroup. Second, netgroup<br>will only work as ro or rw arguments and even then only when the ro<br>or rw is not being used to override another ro or rw option. Netgroups<br>can not be used as an argument to the root option.<br><br><b>A2</b>: NFS requires that the "reverse lookup" capability work such that<br>the hostname returned by looking up the IP address (gethostbyaddr)<br>matches EXACTLY the text specified in the netgroup entry.<br>Otherwise the NFS mount will fail with "access denied"<br><br>For example, if the NFS server has the following NIS netgroup entry:<br><br>goodhosts   (clienta,,) (clientb,,) (blahblah,,)<br><br>clienta is at 192.1.1.1 and the Server uses DNS for hostname lookups.<br><br>The NFS request to do the mount arrives from IP address 192.1.1.1<br>The NFS server looks up the IP address of 192.1.1.1 to get the hostname<br>associated with that IP address.<br><br>The gethostbyaddr MUST return "clienta".  If it does not, the NFS<br>request will fail with "access denied".  telnet from the NFS client<br>to the NFS server and run "who am i".  The hostname in parentheses<br>is the name that should be in the netgroup:<br><br>hackley    pts/13       Jan 24 09:21    (mercedes)<br><br>The most common cause of this failure is failure of a DNS administrator<br>to properly manage the "reverse lookup maps" e.g. 192.1.1.IN-ADDR.ARPA.<br><br><b>Q</b>:  What can you tell me about CacheFS?<br><br><b>A</b>:  CacheFS is the "cache file system".  It allows a Solaris 2.X NFS<br>client<br>to cache a remote file system to improve performance.  For example,<br>CacheFS allows you to be on "clienta" and cache your home directory,<br>which<br>is mounted via NFS from an NFS server.<br><br>Because most often CacheFS is used in conjunction with the automounter,<br>we have some basic information on CacheFS in our automounter tips sheet<br>(Product Support Document).  You can read more about CacheFS in the<br>"NFS Administration Guide" and in the "mount_cachefs" man page.<br><br><b>Q</b>:  Is there a showfh for Solaris to show the NFS File Handle?<br><br><b>A</b>:  Yes here it is:<br><br>#!/bin/sh<br>#<br># fhfind: takes the expanded filehandle string from an<br># NFS write error or stale filehandle message and maps<br># it to a pathname on the server.<br>#<br># The device id in the filehandle is used to locate the<br># filesystem mountpoint.  This is then used as the starting<br># point for a find for the file with the inode number<br># extracted from the filehandle.<br>#<br># If the filesystem is big - the find can take a long time.<br># Since there's no way to terminate the find upon finding<br># the file, you might need to kill fhfind after it prints<br># the path.<br>#<br><br>if [ $# -ne 8 ]  then<br>        echo<br>        echo "Usage: fhfind &lt;filehandle&gt; e.g."<br>        echo<br>        echo "  fhfind 1540002 2 a0000 4df07 48df4455 a0000 2 25d1121d"<br>        exit 1<br>fi<br><br># Filesystem ID<br><br>FSID1=$1<br>FSID2=$2<br><br># FID for the file<br><br>FFID1=$3<br>FFID2=`echo $4   tr [a-z] [A-Z]` # uppercase for bc<br>FFID3=$5<br><br># FID for the export point (not used)<br><br>EFID1=$6<br>EFID2=$7<br>EFID3=$8<br><br># Use the device id to find the /etc/mnttab<br># entry and thus the mountpoint for the filesystem.<br><br>E=`grep $FSID1 /etc/mnttab`<br>if [ "$E" = "" ]   then<br>        echo<br>        echo "Cannot find filesystem for devid $FSID1"<br>        exit 0<br>fi<br><br>set - $E<br>MNTPNT=$2<br><br>INUM=`echo "ibase=16 $FFID2"   bc` # hex to decimal for find<br><br>echo<br>echo "Now searching $MNTPNT for inode number $INUM"<br>echo<br><br>find $MNTPNT -mount -inum $INUM -print 2&gt;/dev/null</pre>
<pre> <a ><b>4.2: Problems Mounting Filesystems on a Client</b></a><br><br><b>Q</b>: Why do I get "permission denied" or "access denied" when I<br>try to<br>mount a remote filesystem?<br><br><b>A1</b>: Your remote NFS server is not exporting or sharing its file systems.<br>You can verify this by running the showmount command as follows:<br><br>  # showmount -e servername<br><br>That will provide you with a list of all the file systems that are<br>being sent out. If a file system is not being exported, you should<br>consult section 3.1 or 3.2, as applicable.<br><br><b>A2</b>: Your remote NFS server is exporting file systems, but only to a<br>limited number of client machines, which does not include you. To<br>verify this, again use the command showmount:<br><br>  # showmount -e psi<br>  /var       engineering<br>  /usr/sbin  lab-manta.corp.sun.com<br>  /usr/local (everyone)<br><br>In this example, /usr/local is being exported to everyone, /var is<br>being exported to the engineering group, and /usr/sbin is only being<br>exported to the machine lab-manta.corp.sun.com. So, I might get the<br>denial message if I tried to mount /var from a machine not in the<br>engineering netgroup or if I tried to mount /usr/sbin from anything<br>but lab-manta.corp.sun.com.<br><br><b>A3</b>: Your machine is given explicit permission to mount the partition,<br>but the server does not list your correct machine name. In the example<br>above, psi is exporting to "lab-manta.corp.sun.com", but the machine<br>might actually identify itself as "lab-manta" without the suffix. Or,<br>alternatively, a machine might be exporting to "machine-le0" while the<br>mount request actually comes from "machine-le1". You can test this by<br>first running "showmount -e" and then physically logging in to the<br>server, from the client that cannot mount, and then typing "who". This<br>will show you if the two names do not match. For example, I am on<br>lab-manta, trying to mount /usr/sbin from psi:<br><br>  lab-manta# mount psi:/usr/sbin /test<br>  mount: access denied for psi:/usr/sbin<br><br>I use showmount -e to verify that I am being exported to:<br><br>  lab-manta# showmount -e psi<br>  export list for psi:<br>  /usr/sbin  lab-manta.corp.sun.com<br><br>I then login to psi, from lab-manta, and execute who:<br><br>  lab-manta%% rsh psi<br>  ...<br>  psi# who<br>  root       pts/6        Sep  8 14:02    (lab-manta)<br><br>As can be seen, the names "lab-manta" and<br>"lab-manta.corp.sun.com" do<br>not match. The entry shown by who, lab-manta, is what should appear in<br>my export file. When I change it and re-export, I can verify it with<br>showmount and then see that mounts do work:<br><br>  lab-manta[23] showmount -e psi<br>  export list for psi:<br>  /usr/sbin  lab-manta<br>  lab-manta[24] mount psi:/usr/sbin /test<br>  lab-manta[25]<br><br><b>A4</b>: Your client is a member of a netgroup, but it seems that the netgroup<br>does not work.  See Section 4.1 for notes on debugging netgroups.<br><br><b>Q</b>: Why do I get the following error when I try and mount a remote file<br>system:<br><br>  nfs mount: remote-machine:: RPC: Program not registered<br>  nfs mount: retrying: /local-partition<br><br><b>A</b>: rpc.mountd is not running on the server. You probably just exported<br>the first filesystem from a machine that has never done NFS serving<br>before. Reboot the NFS server, if it is SunOS 4.X,.  The<br>NFS server is running Solaris 2.X, run the following:<br><br>/etc/init.d/nfs.server start<br><br>Note: Consult section 3.1 or 3.2 for information on how to create<br>the exports file on a SunOS 4.X system or on how to create the dfstab<br>file on a Solaris 2.X system.<br><br><b>Q</b>: Why doesn't the mountd respond?  After I try the mount I get NFS SERVER<br>NOT RESPONDING.  When I try to talk to the mountd, rpcinfo gives an rpc<br>timed out error.  How can I debug or fix a hung mountd on the NFS server.<br><br><b>A</b>: First, try killing the mountd process on the server and restarting it.<br>This gets around many hung mountd issues.<br><br>Second, make sure the NFS server is "patched up".  There is a mountd<br>patch<br>for Solaris 2.3 and we've seen cases where the \patch 101973 patch helps<br>on 2.4.<br><br>Further troubleshooting tips to debug the hung mountd on Solaris 2.X:<br>1.  get the PID of the running mountd<br>2.  truss -f -vall -p PID<br>3.  start a snoop at the same time you start the truss<br>4.  if you have access to it, run "gcore" or "pstack"<br>(unsupported utilities<br>    made available by SunService) to get the stack trace of the mountd PID.<br>    Update:  pstack is supported at 2.5, /usr/proc/bin/pstack .  It is<br>             on of the new "proc" tools.<br><br><b>Q</b>:  Why do I get the message "Device Busy" in response to my mount<br>command?<br><br><b>A</b>:  You get this message because some process is using the underlying mount<br>    point.  For example, if you had a shell whose pwd was /mnt and you<br>    tried to mount something into /mnt, e.g. mount server:/export/test /mnt<br>    you would see this error.<br>    To work around this, find the process using the directory and either kill<br>    it or move its pwd someplace else.  The "fuser" command is<br>extremely handy<br>    to do this:<br>    mercedes[hackley]:cd /mnt<br>    mercedes[hackley]:fuser -u /mnt<br>    /mnt:     4368c(hackley)     368c(hackley)<br><br>    In this case you see process # 368 and 4368 are using the /mnt mount point.<br>    PID 368  is the shell and PID 4368 was the fuser command.<br><br>    You can forcibly kill any process (must be root) from a mount point<br>    using fuser -k /mnt.<br><br>    Please note that fuser is not infallible and cannot identify kernel<br>    threads using a mount point (as sometimes happens with the automounter).</pre>
<pre> <i><a ><b>4.3: Common NFS Client Errors Including NFS Server Not Responding</b></a><br></i><br>If a file system has been successfully mounted, you can encounter the<br>following errors when accessing it.<br><br><b>Q</b>: Why do I get the following error message:<br><br>  Stale NFS file handle<br><br><b>A1</b>: This means that a file or directory that your client has open has<br>been removed or replaced on the server. It happens most often when a<br>dramatic change is made to the file system on the server, for example<br>if it was moved to a new disk or totally erased and restored. The<br>client should be rebooted to clear Stale NFS file handles.<br><br><b>A2</b>: If you prefer not to reboot the machine, you can create a new<br>mount point on the client for the mount point with the Stale NFS file<br>handle.<br><br><b>Q</b>: Why do I get the following error message:<br><br>  NFS Server &lt;server&gt; not responding<br>  NFS Server ok<br><br>  Note, this error will occur when using HARD mounts.<br>  This troubleshooting section applies to HARD or SOFT mounts.<br><br><b>A1</b>: If this problem is happening intermittently, while some NFS<br>traffic is occurring, though slowly, you have run into the performance<br>limitations of either your current network setup or your current NFS<br>server. This issue is beyond the scope of what SunService can support.<br>Consult sections 7.4 &amp; 7.5 for some excellent references that can help you<br>tune NFS performance. Section 9.0 can point you to where you can get<br>additional support on this issue from Sun.<br><br><b>A2</b>: If the problem lasts for an extended period of time, during which<br>no NFS traffic at all is going through, it is possible that your NFS<br>server is no longer available.<br><br>You can verify that the server is still responding by running the commands:<br><br>  # ping server<br>and<br>  # ping -s server 8000 10<br>(this will send 10 8k ICMP Echo request packets to the server)<br><br>If your machine is not available by ping, you will want to check the<br>server machine's health, your network connections and your routing.<br><br>If the ping works, check to see that the NFS server's nfsd and<br>mountd are responding with the "rpcinfo" command:<br><br>   # rpcinfo -u server nfs<br><br>program 100003 version 2 ready and waiting<br><br>   # rpcinfo -u server mountd<br><br>program 100005 version 1 ready and waiting<br>program 100005 version 2 ready and waiting<br><br>If there is no response, go to the NFS server and find out why<br>the nfsd and/or /mountd are not working over the network.  From<br>the server, run the same commands.  If they work OK from the<br>server, the network is the culprit.  If they do NOT work,<br>check to see if they are running.  If not, restart them and<br>repeat this process.  If either nfsd or mountd IS running but<br>does not respond, then kill it and restart it and retest.<br><br><b>A3</b>: Some older bugs might have caused this symptom. Make sure that you<br>have the most up-to-date Core NFS patches on the NFS server.<br>These are listed in Section 5.0 below. In addition, if you are running<br>quad ethernet cards on Solaris, install the special quad<br>ethernet patches listed in Section 5.4.<br><br><b>A4</b>:  Try cutting down the NFS read and write size with the NFS mount<br>options:  rsize=1024,wsize=1024.  This will eliminate problems with<br>packet fragmentation across WANS, routers, hubs, and switches in a<br>multivendor environment, until the root cause can be pin-pointed.<br>THIS IS THE MOST COMMON RESOLUTION TO THIS PROBLEM.<br><br><b>A5</b>: If the NFS server is  Solaris 2.3 and 2.4, 'nfsreadmap' occasionally<br>caused the "NFS server not responding" message on Sun and non-Sun<br>NFS clients.  You can resolve this by adding the following entry to<br>your /etc/system file on the NFS server:<br><br>set nfs:nfsreadmap=0<br><br>And rebooting the machine.  The nfsreadmap function was removed in 2.5<br>because it really didn't work.<br><br><b>A6</b>: If you are using FDDI on Solaris, you must enable fragmentation<br>with the command:<br>ndd -set /dev/ip ip_path_mtu_discovery 0<br><br>Add this to /etc/init.d/inetinit, after the other ndd command on line 18.<br><br><b>A7</b>:  Another possible cause is IF the NFS SERVER is Ultrix, old AIX,<br>Stratus, and older SGI and you ONLY get this error on Solaris 2.4 and 2.5<br>clients, but the 2.3 and 4.X clients are OK.<br><br>The NFS Version 2 and 3 protocol allow for the NFS READDIR request to be<br>1048 bytes in length.  Some older implementations incorrect thought the<br>request had a max length of 1024.  To work around this, either mount<br>those problem servers with rsize=1024,wsize=1024 or add the following<br>to the NFS client's /etc/system file and reboot:<br><br>set nfs:nfs_shrinkreaddir=1<br><br><b>A8</b>:  Oftentimes NFS SERVER NOT RESPONDING is an indication of another problem<br>on the NFS server, particularly on the disk subsystem.  If you have a<br>SPARCStorage Array, you must verify that you have the most recent<br>firmware and patches due to the volatility of that product.<br><br>Another general method that can be tried to is look at the output<br>from iostat -xtc 5 and check the svt_t field.  If this value goes<br>over 50.0 (50 msec) for a disk that is being used to serve NFS requests,<br>you might have found your bottleneck.  Consult the references in<br>Section 7 of this PSD for other possible NFS Server tuning hints.<br><br>NOTE:  NFS Server performance tuning services are only available<br>on a Time and Materials basis.<br><br><b>Q</b>: Why can't I write to a NFS mounted file system as root?<br><br><b>A</b>: Due to security concerns, the root user is given "nobody"<br>permissions when it tries to read from or write to a NFS file system.<br>This means that root has less access than any user, will only be<br>able to read from things with world read permissions, and will only be<br>able to write to things with world write permissions.<br><br>If you would like your machine to have normal root permissions to a<br>filesystem, the filesystem must be exported with the option<br>"root=clientmachine".<br><br>An alternative is to export the filesystem with the "anon=0" option.<br>This will allow everyone to mount the partition with full root<br>permissions.<br><br>Sections 3.1 and 3.2 show how to include options when exporting<br>filesystems.<br><br><b>Q1</b>: Why do 'ls'es of NFS mounted directories sometimes get mangled on<br>    my SunOS machine?<br><b>Q2</b>: Why do I get errors when looking at a NFS file on my SunOS<br>    machine?<br><br><b>A</b>: By default, SunOS does not have UDP checksums enabled. This can<br>cause problems if NFS is being done over an extended distance,<br>especially if it is going across multiple routers. If you are seeing<br>very strange errors on NFS or are getting corruption of directories<br>when you view them, try turning UDP checksums on.<br><br>You can do so my editing the kernel file /usr/sys/netinet/in_proto.c,<br>changing the following:<br><br>  int  udp_cksum = 0            /* turn on to check &amp; generate udp<br>checksums */<br><br>to:<br><br>  int  udp_cksum = 1            /* turn on to check &amp; generate udp<br>checksums */<br><br>Afterwards, you will must build a new kernel, install it and<br>reboot. UDP checksums must be enabled on both the NFS client and NFS<br>server for it to have any effect.<br><br>This is only an issue on SunOS machines, as Solaris machines have UDP<br>checksums enabled by default.<br><br><b>Q1</b>: Why do I get intermittent errors writing to an NFS partition?<br><b>Q2</b>: Why do I get intermittent errors reading from an NFS partition?<br><b>Q3</b>: Why do I get the following error on my NFS partition?<br><br>  "nfs read error on &lt;machine&gt; rpc: timed out"<br><br><b>A</b>: These symptoms can all be caused by failures of soft mounts.<br>Soft mounts time out instead of logging an "NFS SERVER NOT RESPONDING"<br>message.  Because of this and other reasons, it is recommended that<br>you only mount non-critical read-only servers with soft mounts (e.g.<br>man pages).<br><br>To resolve the problem, you must solve the underlying problem<br>(See the section above on "NFS server not responding" for<br>troubleshooting<br>assistance.  Alternatively, you can mount the NFS server with hard,intr<br>instead of soft, but this will have the effect of causing applications<br>to hang instead of timeout when the NFS servers are unavailable or<br>unreachable.</pre>
<pre><i> <a ><b>4.4: Problems Umounting Filesystems on a Client</b></a></i><br><br><b>Q</b>: When I try and umount a partition, why do I get the following<br>error:<br><br>  /partition: Device busy<br><br><b>A</b>: This means that someone is actively using the partition you are<br>trying to unmount. They might be running a program from it or they<br>might simply be sitting in a subdirectory of the partition.<br><br>In Solaris, you can run the command fuser to determine what processes<br>are using a partition:<br><br>  # fuser /test<br>  /test:     1997c    1985c<br><br>The above example shows that pids 1985 and 1997 are accessing the<br>/test partition. Either kill the processes or run fuser -k /test to<br>have fuser do this for you.<br><br>NOTES:  This functionality is not available under SunOS.  It does<br>not always identify an automounted process on Solaris.<br><br>In many cases, it is necessary to reboot a machine in order to clear<br>out all of the processes that could be making a file system busy.</pre>
<pre><i> <a ><b>4.5: Interoperability Problems With Non-Sun Systems</b></a></i><br><br>The following problems are relevant to Suns that are doing mounts<br>from non-Sun systems.<br><br><b>Q</b>: Why do I get the following error when mounting from my HP or SunOS<br>3.5 machine or other machine running an older version of NFS:<br><br>  nfsmount server/filesystem server not responding RPC authentication error <br>why = invalid client credential.<br><br><b>A</b>: Older versions of NFS only allowed users to be in eight groups or<br>less. Reduce root's number of groups to eight or less and the problem<br>will go away. Users planning to access this partition should also<br>reduce their number of groups to eight.<br><br><b>Q</b>: When I NFS mount filesystems to my Sun, from my PC, why does the<br>Sun never see changes I make to those filesystems.<br><br><b>A</b>: Most PC NFS servers do not seem to correctly notify their NFS<br>clients of changes made to their filesystems. It appears that this is<br>due to the fact that file timestamps on PCs are very coarse. If you<br>are having this problem, speak with the vendor of your PC<br>NFS product.<br><br><b>Q</b>: Why do mounts from my SGI fail with "not a directory" ?<br><br><b>A</b>: For some reason, certain versions of the SGI NFS server sometimes<br>begin using port 860 rather than 2049 for NFS. When this occurs,<br>mounts will fail. In order to get around this bug, always use the<br>"port" option, with 2049 as a value, when doing mounts from an SGI,<br>e.g.:<br><br>  mount -o port=2049 sgi:/partition /localpartition<br><br>If you are mounting from an SGI via autofs, be sure you have the<br>newest version of the kernel patch (101318-74 or better for 5.3,<br><a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/101945">101945-32</a> or better for 5.4), as older versions of the kernel patch<br>did not support the port option for autofs.<br><br><b>Q</b>: Why can't I NFS mount from my old, old machine?<br><br><b>A</b>: If you have a very old machine, it is probably running NFS version<br>1. Such machines often have problems talking to newer versions of NFS.<br>If you have a very old machine, speak with the manufacturer<br>to see if they've ported NFS version 2 or 3.</pre>
<pre><i> <a ><b>4.6: Common NFS Server Errors</b></a></i><br><br><b>Q</b>: Why do I get the following error when I run exportfs/shareall?<br><br>  exportfs: /var/opt: parent-directory (/var) already exported<br>  share_nfs: /var/opt: parent-directory (/var) already shared<br><br><b>A</b>: NFS specs forbid you from exporting both a parent directory and a<br>sub-directory. If you try and export a sub-directory when the parent<br>directory is already exported, you will get the above error. The above<br>example showed an export of the subdirectory /var/opt being attempted,<br>after the directory /var was already available.<br><br>A very similar error will occur in the opposite case:<br><br>  exportfs: /var: sub-directory (/var/spool/mail) already exported<br><br>This shows the directory /var being exported after /var/spool/mail was<br>already available.<br><br>If you want to have both a parent directory and its sub-directory<br>exported, you must export just the parent directory. Among other<br>things, this means that you can not have different options on parent<br>and sub-directories, for example -ro on a parent directory and -rw on<br>a specific subdirectory.<br><br><b>Q</b>: Why is my NFS server getting totally overrun by quota errors?<br><br><b>A</b>: Solaris 2.4 experienced an error relating to way that quotas and<br>NFS interacted.  Obtain <a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/101945">101945-34</a> or later, if quota message from NFS<br>partitions are having a serious impact on your machine.<br><br>If you are running into this problem where your client is Solaris and<br>your server is SunOS, you will not have this option and it is<br>recommended that you simply upgrade your SunOS system.<br><br><b>Q</b>: Why does the /etc/rmtab file get huge?<br><br><b>A</b>: The rmtab contains the list of all the file systems currently being<br>mounted by remote machines. When a filesystem is unmounted by a remote<br>machine, the line in the rmtab is just commented out, not deleted.<br>This can make the rmtab file get very large, maybe even filling the<br>root partition.<br><br>If this is a problem at your site, add the following lines<br>to your rc, prior to the starting of the rpc.mountd:<br><br>  if [ -f /etc/rmtab ]   then<br>    sed -e "/^#/d" /etc/rmtab &gt; /tmp/rmtab 2&gt;/dev/null<br>    mv /tmp/rmtab /etc/rmtab &gt;/dev/null 2&gt;&amp;1<br>  fi<br><br>This will cause the rmtab file to be trimmed every time the system boots.</pre>
<pre> <a ><b><i>4.7: Common nfsd Error Message on NFS Servers</i></b></a><br><br><b>Q</b>: Why do I get the following error message when nfsd starts?<br><br>  /usr/lib/nfs/nfsd[247]: netdir_getbyname (transport udp,<br>       host/serv \1/nfs), Bad file number<br><br><b>A</b>: This problem is usually the result of an nfsd line not being in<br>your services map. Consult your naming service (files, nis, nis+) and<br>insert the following entry, if it is missing:<br><br>  nfsd            2049/udp        nfs             # NFS server daemon<br><br>...and at 2.5, you must also have:<br>  nfsd          2049/tcp        nfs<br><br><b>Q</b>: Why do I get the following error message when nfsd starts?<br><br>/usr/lib/nfs/nfsd[2943]: t_bind to wrong address<br>/usr/lib/nfs/nfsd[2943]: Cannot establish NFS service over /dev/udp:  <br>transport setup problem.<br>/usr/lib/nfs/nfsd[2943]: t_bind to wrong address<br>/usr/lib/nfs/nfsd[2943]: Cannot establish NFS service over /dev/tcp:  <br>transport setup problem.<br>/usr/lib/nfs/nfsd[2943]: Could not start NFS service for any protocol. Exiting.<br><br><b>A</b>: This problem is caused by trying to start a second nfsd when one is<br>already running.<br></pre>
<pre> <a ><b>4.8: Common rpc.mountd Error Messages on NFS Servers</b></a><br><br><b>Q</b>: Why do I constantly get the following error message on my NFS<br>server:<br><br>  Aug 15 13:13:56 servername mountd[930]: couldn't register TCP MOUNTPROG<br>  Aug 15 13:13:58 servername inetd[141]: mountd/rpc/udp server failing<br><br><b>A</b>: This problem occurs most often on SunOS machines. It typically<br>means that you are starting rpc.mountd from the rc.local, but also<br>have a line in your inetd.conf:<br><br>  mountd/1       dgram   rpc/udp wait root /usr/etc/rpc.mountd   rpc.mountd<br><br>You can resolve this problem by commenting out the mountd line in the<br>/etc/inetd.conf file and then killing and restarting your inetd.</pre>
<pre> <a ><b><i>4.9: Common rpc.lockd &amp; rpc.statd Error Messages</i></b></a><br><br><b>Q</b>: What does it mean when I get the following error:<br><br>  lock manager: rpc error (#): RPC: Program/version mismatch<br><br><b>A</b>: Some of your systems are running up-to-date versions of lockd,<br>while others are outdated. Install the most up-to-date<br>lockd patch on all of your systems. See section 5.0 below for a list<br>of lockd patches.<br><br><b>Q</b>: What does it mean when I get the following error:<br><br>  rpc.statd: cannot talk to statd on [machine]<br><br><b>A</b>: Either, [machine] is down or it is no longer doing NFS services.<br>It's possible that the machine might still be around, but has changed its<br>name or something similar. If these changes are going to be<br>permanent, clear out the statmon directories on your<br>machine. Do this by rebooting the machine into single user mode and<br>running the following command:<br><br>  SunOS:<br>  rm /etc/sm/* /etc/sm.bak/*<br><br>  Solaris:<br>  rm /var/statmon/sm/* /var/statmon/sm.bak/*<br><br>Afterwards, execute reboot to bring your machine back up.<br><br>Alternatively, if you cannot put the system into single user mode,<br>- Kill the statd and lockd process<br>- clear out the "sm" and "sm.bak" directories"<br>- Restart statd and lockd in that order<br><br><b>Q</b>: How can I fix these errors?  The SunOS 4.1.X lockd reports:<br><br>  lockd[136]: fcntl: error Stale NFS file handle<br>  lockd[136]: lockd: unable to do cnvt.<br><br>the lockd error message is different on Solaris 2.3 and 2.4:<br><br>  lockd: unable to do cnvt.<br>  _nfssys: error Stale NFS file handle<br><br> Generally, this is caused by an error from a client.  The client<br> has submitted a request for a lock on a stale file handle.  Sometimes,<br> older or unpatched lockd clients will continually resubmit these<br> requests.  See the "lockd debug hint" Section for help in<br> identifying the client making the request.  See section 5.0 for info<br> on the NFS and lockd patches.  If the client is a non-Sun,<br> contact the client system vendor for their latest lockd patch.<br><br><b>Q</b>: How can I fix the following errors:<br>     nlm1_reply: RPC unknown host<br>     create_client: no name for inet address 0x90EE4A14.<br>We also see<br>     nlm1_call: RPC: Program not registered<br>     create_client: no name for inet address 0x90EE4A14.<br><br><b>A</b>: There are THREE items to check in order.<br><br><b>1</b>.  This first answer applies if the hexadecimal address 0x90EE4A14<br>    corresponds to an IP address in use on your network and it not<br>    in your hosts database (/etc/hosts, NIS, NIS+ or DNS as appropriate).<br><br>    In this case, to 144.238.74.20.<br>    The customer does not have that host ID in his NIS+ hosts table.<br>    The customer can find out the host name for that IP address by using<br>    telnet to connect to the IP address, then getting the hostname.<br>    The customer then adds the entry to the NIS+ hosts table.<br><br>    Then verify that gethostbyaddr() was working with the new<br>    IP/hostname in NIS+ with:<br>      ping -s 144.238.74.20<br>    The responses interpret the IP address into the hostname.<br><br><b>2</b>.  If you do the above and the messages continue, kill and<br>    restart the lockd as it appears lockd caches name service<br>    information.<br><br><b>3.  Patch levels:</b><br><br><b><i>Solaris 2.4</i></b>:<br><a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/101945">101945-34</a> or better kernel jumbo patch<br><a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/101977">101977-04</a> or better lockd jumbo patch<br><a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/102216">102216-05</a> or better klm kernel locking patch (See note below)<br><br><b>Note:</b><br>Patch <a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/102216">102216-05</a> contains a fix for a bug that can cause this error message:<br><a href="http://www.pimpworks.org/private-cgi/us/doc2html?bug/network/locking/1164679">1164679</a> KLM doesn't initialize rsys &amp; rpid correctly<br><br><b><i>Solaris 2.3</i></b>:<br><a href="http://www.pimpworks.org/private-cgi/us/doc2html?patches/101318">101318-75</a> or better kernel jumbo patch<br><br><b>Q</b>:  Why do I get the following error message on Solaris?<br><br>lockd[2269]:netdir_getbyname (transport udp, host/serv<br>\1/lockd), Resource temporarily unavailable<br>lockd[2269]: Cannot establish LM service over /dev/udp:<br>bind problem. Exiting.<br><br><b>A</b>:  This is caused by missing entries for lockd in /etc/services,<br>the NIS services map, or the NIS+ services table.<br>Verify this with:<br>getent services lockd<br><br>If you don't get the lockd entries, add the following<br>entry to the appropriate services database if it does not exist:<br>lockd           4045/udp<br>lockd           4045/tcp<br><br>Check your /etc/nsswitch.conf file's services entry to determine<br>which services database you are using.<br><br><b>Q</b>:  Why do I get the following error message on Solaris?<br><br>lockd[2947]: t_bind to wrong address<br>lockd[2947]: Cannot establish LM service over /dev/udp: bind problem. Exiting.<br><br><b>A</b>:  This is caused by trying to start lockd when it is already running.<br>If you see this message at bootup, you must inspect your startup<br>scripts in /etc/rc2.d and /etc/rc3.d to determine the cause.</pre>
<pre><i> <a ><b>4.10: NFS Related Shutdown Errors</b></a></i><br><br><b>Q</b>: Why do I get the following error, when running 'shutdown' on my<br>Solaris machine:<br><br>  "showmount: machine: RPC:program not registered"<br><br><b>A</b>: This is due to a bug in the /usr/sbin/shutdown command. shutdown<br>executes the showmount command as part of its scheme to warn other<br>machines that it will not be available. If the machine you executed<br>shutdown on is not a nfs server, shutdown will complain with the above<br>message. This will cause no impact to your machine, but if it annoys<br>you, you can run the older /usr/ucb/ shutdown program:<br><br>  # /usr/ucb/shutdown<br><br><b>Q</b>: Why do I get the following error, when running 'shutdown' on my<br>Solaris machine:<br><br>  "nfs mount:machine(vold(PID###):server not responding:RPC not<br>registered"<br><br><b>A</b>: This is due to a bug in vold, which causes it to be shutdown too<br>late. This will cause no impact to your machine, but if it annoys you,<br>you can stop vold before executing shutdown:<br><br>  # /etc/init.d/volmgt stop<br>  # shutdown</pre>
<pre> <a ><b><i>4.11  NFS Performance Tuning</i></b></a><br><br><b>Q</b>: How do I determine how many nfsds to run on a SunOS 4.1.X or on a<br>   Solaris 2.X system?<br><br><b>A</b>:  It is difficult to provide NFS tuning in short a technical note,<br>but here are some general guidelines.  For more specific guidelines,<br>consult the O'Reilly and Associates book "Managing NFS and NIS",<br>the SunSoft Press book, "Sun Performance and Tuning", or the<br>"SMCC NFS Performance and Tuning Guide".  Ordering info is in<br>Section 7 of this PSD.<br><br>If you need NFS performance consulting assistance from SunService,<br>please refer to Sections 8 and 9 of this document on supportability<br>and support providers.<br><br>In SunOS 4.1.X, the number of nfsd's specifies<br>the number of nfsd processes that run.  In Solaris 2.X, the<br>number of nfsd's specifies the number of nfsd threads<br>that run inside the single nfsd Unix process.<br><br>Here are some general guidelines for SunOS 4.1.X:<br><br>To determine how many nfsds to run, use any of the<br>formulas below to pick a starting value.  Then use the<br>procedures below to adjust the number of nfsds until it<br>is right for the particular environment.<br><br>--------------------------------------------------------<br>  VARIATION                    FORMULA<br>--------------------------------------------------------<br> Variation 1   #(disk spindles) + #(network interfaces)<br>--------------------------------------------------------<br> Variation 2   4 for a desktop system that is both<br>               client and server,<br>               8 for a small dedicated server,<br>               16 for a large NFS and compute server,<br>               24 for a large NFS-only server<br>+-----------+------------------------------------------+<br> Variation 3   2 * max#(simultaneous disk operations)<br>--------------------------------------------------------<br><br>On Solaris 2.X, this number will be different.  The SunSoft<br>press book recommends taking the highest number obtained by<br>applying the following three rules:<br><br>* Two NFS threads per active client process<br>* 32 NFS threads on a SPARCclassic server, 64 NFS threads per<br>  SuperSPARC processor.<br>* 16 NFS threads per ethernet, 160 per FDDI<br><br>The default for 2.X is 16 threads.<br><br><b>Q</b>: What other guidelines and help is there on Tuning NFS?<br><br><b>A</b>:  Consult the O'Reilly and Associates book "Managing NFS and NIS",<br>the SunSoft Press book, "Sun Performance and Tuning", or the<br>"SMCC NFS Performance and Tuning Guide".  Ordering info is in<br>Section 7 of this PSD.</pre>
<pre><b><i>5.0 Patches</i></b><br><br> <b><i>General Information on Patches</i></b><br><br>The following is the list of all of the NFS related patches for 4.1.3,<br>4.1.3_u1, 4.1.4, 2.3, 2.4, and 2.5.  If you are having NFS problems,<br>installing the patches is a good place to start, especially if you<br>recognize the general symptoms noted below.<br><br>In order for a machine to be stable, all of the recommended patches<br>should be installed as well. The list of recommended patches for your<br>operating system is available from sunsolve1.sun.com</pre>
<pre><i> <a ><b>5.1: Core NFS Patches for SunOS 4.1.X</b></a></i><br><br>100173-13 SunOS 4.1.3: NFS Jumbo Patch<br>102177-04 SunOS 4.1.3_U1: NFS Jumbo Patch<br>102394-02 SunOS 4.1.4: NFS Jumbo Patch<br><br>  Resolve a large number of NFS problems. Should be installed on any<br>  machine doing NFS.<br><br>100988-05 SunOS 4.1.3: UFS File system and NFS locking Jumbo Patch.<br>101784-04 SunOS 4.1.3_U1: rpc.lockd/rpc.statd jumbo patch<br>102516-05 SunOS 4.1.4: UFS File system Jumbo Patch<br><br>  Fixes a wide variety of rpc.lockd and rpc.statd problems.<br><br>102264-02 SunOS 4.1.4: rpc.lockd patch for assertion failed panic<br><br>  Fixes an "Assertion failed" panic related to the lockd.<br><br>103275-01 SunOS 4.1.4: System with heavy NFS load may crash due to<br>                 IP driver bu</pre>
<pre> <a ><b><i>5.2: Patches Related to NFS for SunOS</i></b></a><br><br>100361-04 SunOS 4.1.1 4.1.2 4.1.3: server not responding due to limits of<br><br>  Resolves an error that could cause "NFS server not responding"<br>  errors on a machine that had more than 500 machines in its arp cache.<br>  Only a problem at sites with very large local nets.<br><br>101849-01 SunOS 4.1.3: rpc.quotad is very slow on busy NFS servers<br><br>  Speeds up slow rpc.quotads on NFS servers.</pre>
<pre> <a ><b><i>5.3: Core NFS Patches for Solaris</i></b></a><br><br><b><i>SOLARIS 2.3:</i></b><br><br>101318-81 SunOS 5.3: Jumbo patch for kernel (includes libc, lockd)<br><br>  Resolves a large number of problems involving both nfs and the<br>  lockd, as well as the related autofs program. Should be installed<br>  on any 5.3 machine, but is an absolute necessity on a machine doing<br>  NFS.<br><br>102654-01 SunOS 5.3: rmtab grows without bounds<br><br>  This patch solves problems where the mountd hangs up, but the nfsd<br>  continues to process NFS requests from existing NFS mounts.<br><br>103059-01 SunOS 5.3: automountd /dev rdev not in mnttab<br><br>  This patch fixes a variety of issues where the automounter loses<br>  entries from mnttab, often seen with lofs (loopback) mounts.<br><br>101930-01 SunOS 5.3: some files may not show up under cachefs<br><br>  This patch is required with the "autoclient" product, which is needed<br>  to cache the / and /usr file systems with cachefs.<br><br>102932-02 SunOS 5.3: statd dies intermittently<br></pre>
<pre><b><i>SOLARIS 2.4 and 2.4x86:</i></b><br><br>101945-42 SunOS 5.4: jumbo patch for kernel<br>101946-35 SunOS 5.4_x86: jumbo patch for kernel<br><br>  Resolves a large number of problems involving nfs, as well as the<br>  related autofs program. Should be installed on any 5.4 machine, but<br>  is an absolute necessity on a machine doing NFS.<br><br>102685-01 SunOS 5.4: lofs - causes problems with 400+ PC-NFS users<br><br>  This patch resolves some mountd hangs seen after sharing a lofs mount point.<br><br>101977-04 SunOS 5.4: lockd fixes<br>101978-03 SunOS 5.4_x86: lockd fixes<br><br>  Resolves various lockd error messages, as well as a lockd memory<br>  leak.<br><br>102216-07 SunOS 5.4: klmmod and rpcmod fixes<br><br>  Resolves problems with NFS file locking.  It is needed whenever<br>  patching lockd.<br><br>102769-03 SunOS 5.4: statd requires enhancements in support of HADF<br><br>  This patch is generally needed in high availability server application.<br><br>102209-01 SunOS 5.4: No way to cache the root and /usr file systems with<br>CacheFS<br>102210-01 SunOS 5.4_x86: No way to cache root &amp; /usr file systems with<br>CacheFS<br><br>  This patch is required with the "autoclient" product, which is needed<br>  to cache the / and /usr file systems with cachefs.<br><br>102217-07 SunOS 5.4_x86: NFS client starts using unreserved UDP port numb<br><br>  Resolves a problem specific to the x86 port of 5.4, which caused NFS<br>  clients to begin using unreserved ports. [look up bug 1179403]<br><br>SOLARIS 2.5 and 2.5x86<br><br>103226-07 SunOS 5.5: /kernel/sys/nfs and /kernel/fs/nfs fixes<br>103227-06 SunOS 5.5_x86: /kernel: sys/nfs, fs/nfs &amp; misc/nfssrv fixes<br>  This patch is needed for any Solaris 2.5 system w/ NFS<br><br>103325-02 SunOS 5.5: mount causes the system to panic Data fault<br><br>  This patch also fixes some file locking problems in klmmod<br><br>103477-02 SunOS 5.5: RPC: Unable to send/receive<br>103478-01 SunOS 5.5_x86: RPC: Unable to send/receive<br><br>SOLARIS 2.5.1, 2.5.1_x86, and 2.5.1_ppc<br>103609-02 SunOS 5.5.1: RPC: Unable to send/receive<br>103611-01 SunOS 5.5.1_ppc: RPC: Unable to send/receive<br>103610-01 SunOS 5.5.1_x86: RPC: Unable to send/receive</pre>
<pre> <a ><b><i>5.4: Patches Related to NFS for Solaris</i></b></a><br><br>We STRONGLY recommend you install these patches, especially if you have<br>had any problems with "NFS SERVER NOT RESPONDING":<br><br><b><i>SOLARIS 2.3:</i></b><br><br>101546-01 SunOS 5.3: nfs: multiple quota -v may not return info or too slow<br><br>101581-02 SunOS 5.3: quotaon/quotaoff/quotacheck fixes<br>  Resolves a problem that caused rquotad to hang on some NFS systems and<br>  to resolve other quota issues.<br><br>101306-11 SunOS 5.3: Jumbo Patch for le &amp; qe drivers<br>  This is a "must install" patch for systems with Ethernet.<br><br>102272-02 SunOS 5.3: Ethernet and ledmainit fixes<br>  Resolve dma problems with le interface, possible causes of NFS server hangs<br><br>101734-03 SunOS 5.3: iommu fixes for sun4m<br> Resolve iommu problems mainly on Sparc 5, possible causes of NFS server hangs.</pre>
<pre><b><i>SOLARIS 2.4:</i></b><br><br>101973-23 SunOS 5.4: jumbo patch for libnsl and ypbind<br>  This patch resolves a variety of name service issues that can cause<br>  a 2.4 NFS server to not respond to certain requests.  This is a "must<br>have" <br>  patch.<br><br>102001-11 SunOS 5.4: le, qe, be Ethernet driver Jumbo Patch<br>  This is a "must install" patch for systems with Ethernet.<br><br>102332-01 SunOS 5.4: ledma fix<br>  Resolve dma problems with le interface, possible causes of NFS server hangs<br><br>102038-02 SunOS 5.4: iommunex_dma_mctl Sparc 5 only<br>  Resolves iommu problems on Sparc 5, possible causes of NFS server hangs.</pre>
<pre><b><i>SOLARIS 2.5</i></b><br><br>102979-02 SunOS 5.5: /kernel/drv/be, /kernel/drv/hme and /kernel/drv/qe fixes<br>103244-03 SunOS 5.5: Fix for le driver<br><br></pre></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320087296535349</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320087296535349</guid>
    <pubDate>Fri, 29 Aug 2008 18:53:53 +0800</pubDate>
    <dcterms:modified>2008-08-30T11:05:47+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[我关于Linux的学习]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200872711383680</link>
    <description><![CDATA[<div><P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1、</FONT></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">PC</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">预留一个盘</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">FAT</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的格式，然后将</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">fedroa</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">image</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拷贝至其中</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2、</FONT></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">grub</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">启动，将</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">grubDOS</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的文件拷贝至才</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">c:</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">盘的根目录下，然后修改</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">boot.ini</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">追加启动</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">grub</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的选项。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">3、</FONT></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">grub</FONT></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">引导系统，然后在根目录下输入</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">root (hd0,0) </FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">4、</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">kernel /vmlinuz</SPAN></FONT></P>
<P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">5、initrd</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"> /intrid.img</SPAN></FONT></P>
<P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">6、b</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">oot</SPAN></FONT></P>
<P style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; LINE-HEIGHT: 150%; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">7、</SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">&nbsp;</SPAN></FONT></P>
<P style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目录可以这样的安排</SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">/</FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">/boot</FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">/swap</FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><FONT face="Times New Roman">（另我很喜欢163.输入blog的版面，比QQ的好很多，希望163能开到）</FONT></SPAN></P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200872711383680</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200872711383680</guid>
    <pubDate>Wed, 27 Aug 2008 11:38:36 +0800</pubDate>
    <dcterms:modified>2008-08-27T11:38:36+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[实战xp下硬盘安装fedora 9+redflag 6 并grub引导（IDE硬盘）(转载)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/920232008727104630493</link>
    <description><![CDATA[<div>fedora 9安装<BR>准备：<BR>(1)下载<BR>&nbsp; &nbsp; 下载fedora 9镜像Fedora-9-i386-DVD到fat32格式分区（无论主还是分区），不需要解压提取Fedora-9-i386-DVD里面isolinux文件夹内vmlinuz 和initrd.img到c：根目录。<BR>&nbsp; &nbsp; 下载grub4dos，解压里面grub.exe grldr menu.1st三个文件到c：根目录。<BR>(2)配置<BR>&nbsp; &nbsp; 打开c：在根目录找到boot.ini（可以在地址栏输入），在最后行添加<BR>c:\grldr=GRUB,保存关闭。<BR>打开menu.1st在最后添加：<BR>title instal fedora 9<BR>kernel (hd0,0)/vmlinuz<BR>initrd (hd0,0)/initrd.img<BR>保存关闭。<BR>安装：<BR>&nbsp; &nbsp; 开机时选择GRUB，找到instal fedora 9，一路默认，有一项要你选择镜像所在盘，这里d：是（hd0，4）依次e：是（hd0，5）...，不懂的就一个一个试下来。接下来就是安装开始了。注意（root密码要牢记）。<BR>16:23 2008-6-28<BR>开机引导问题：<BR>&nbsp; &nbsp; 如果你没装fedora 9的引导，可以找到fedora 9的boot所在盘，然后在c根目录下menu.1st里面最后加上。<BR>title fedora 9<BR>root (hd0,？)&nbsp;&nbsp;\\登入boot所在盘符<BR>kernel /vmlinuz-2.6.25-14.fc9.i686 ro root=LABEL=/？ vga=188 splash=silent resume=/dev/sda？\\第一问填你boot编号，装第一个linux就0或默认，第二个用1，第二问是填你\所在盘符。这一行是登入内核吧，这一行，我不用ro root=LABEL=/？ vga=188 splash=silent resume=/dev/sda？也可以进fc9<BR>initrd /initrd-2.6.25-14.fc9.i686.img\\这里我想是注入RAM<BR>boot<BR>接着开机就找到GRUB到fedora 9.<BR>至于我为什么不装fedora 9的开机引导，是因为我前一次装了，删掉后就引导不起来，送去装机那，也不是个老鸟，惨遭重装，装的又不好，优化时不小心删了个系统文件，又进不去，不认识什么老鸟，自己重装。郁闷~~~~~<BR><BR>fedflag 6 安装<BR>&nbsp; &nbsp; 这一段看不懂也不要紧，其实我文采有限，不能很好的表达，我自己也常搞糊涂了。目的是讨论学习。<BR>&nbsp; &nbsp; 在xp系统下，我是先装fc 9在最后，xp下是第9-11盘，盘符是9 10 11.现在要装红旗6也就是redflag 6，我只有用第8个分区，我是在fedflag 6安装界面分的区。第8区删除了，结果后面的区集体向前进了一位，所以我猜fc9的盘变成了8 9 10不管。我创，结果盘符是11 12 13.那时我猜，物理上的8 9 10 是grub认为的11 12 13，物理上的11 12 13grub认为是8 9 10，xp是只认物理的。结果和我想的一样。<BR>&nbsp; &nbsp; 接着就是引导，我又没装红旗的引导，坚持xp的引导，也就是不修改MBR，我是不敢改，高手的话改了还能改回来。<BR>安装和fc如出一辙，接下来我说引导办法：<BR>（1）最有效的办法：<BR>&nbsp; &nbsp; 如果你有装别的linux，就进去把红旗的boot copy过来到xp下，打开里面grub里面的grub.conf，前提是你把红旗的引导装在里面了。一般红旗引导都是要么修改MBR要么引导装boot上。<BR>你找grub.conf里面有<BR>title RedFlag (2.6.22.6-1)<BR>root (hd0,？)<BR>kernel /vmlinuz-2.6.22.6-1 ro root=LABEL=/？ vga=788 splash=silent resume=/dev/sda？ <BR>initrd /initrd-2.6.22.6-1.img<BR>类似的一段，原封不动得拷到c：根下menu.1st最后，注意换行。<BR>（2）一般方法嘛：<BR>&nbsp; &nbsp;&nbsp; &nbsp; 我不知道有没有效，我曾在grub字符界面搞了很久，fc就那么搞出来的，自己去搞搞试试，方法嘛，我也很生疏。你没别的linux的话，或许，你可以理解一下（1）的步骤，和实现的目的，做一些修改，应该就可以引导了。就当学习了，反正你装linux也是为了学习嘛。<BR>&nbsp; &nbsp; <BR>&nbsp; &nbsp; 这个红旗引导我在网上问了好多人，也看了很多资料，终于在大家的帮助下完成了引导。事实证明我当初坚持xp的引导不变是对的。这里要感谢cupid、flay、aoacgo、和很多网上的朋友。希望这个文章可以帮到一些有需要的朋友。老鸟别笑。</div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/920232008727104630493</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/920232008727104630493</guid>
    <pubDate>Wed, 27 Aug 2008 10:46:30 +0800</pubDate>
    <dcterms:modified>2008-08-27T10:46:30+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[EMACS vs. vi: The endless geek &apos;holy war&apos;(转载)]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/9202320087268491885</link>
    <description><![CDATA[<div>There they went, at it again. The president of our local <a href="http://linux.umbc.edu/">Linux user's group</a>
sent out the word that the week's tutorial would be canceled. That the
tutorial was on using the vi text editor was enough to set off a fresh
round of sniping. <p>                   </p>
            
Greg Menke fired the first salvo. Use vi? How hard could that be? He
emailed his own steps for using vi. They were, as follows: <ol><p>
 
</p><li>Procure fish, any kind, length &gt; 12 inches
 </li><li>Freeze it overnight
</li><li> Sit in front of PC, run vi
</li><li> Holding fish by the tail, smash it repeatedly against your 
 forehead until you decide to give EMACS a try because the fish scales are 
 flying around your head and it's starting to ache.</li></ol><p>

 Menke, of course, was implying that not only vi was insanely obstinate but 
 that vi users were obstinate as well for refusing to admit how they were 
 inflicting upon themselves frozen-fish-against-the-noggin levels of 
 brutalization. </p><p>

 It didn't take long for vi lovers return fire. One suggested Menke add this 
 line to his  instructions: "Type 'emacs' before step 1, so that by the time 
 step 4 is done, it will have finally finished loading."</p><p>

 Now, was he trying to say the EMACS text editor was slow?</p><p>  
   
 Like fight-fatigued battalions who come to a temporary 
 truce but refuse to give up the war, vi and EMACS users keep an uneasy 
 standoff in many Linux, <a href="http://www.usenix.org/sage/">SAGE</a>
and other computer-related virtual communities. It's the kind of
standoff that may remain dormant for months, but it takes only the
vaguest slight from one side for the flames to roil across the
newsgroups and mailing lists once again. For just beneath their civil
demeanors, each camp feels the editor they use is the best of all
possible editors and those who use any other editor, <i>particularly that  other editor</i>, are fools who would realize the error in their  thinking if only pounded with enough mockery. </p><p> 
    
 Now, a  rift over which Unix text editor is God's Own Build may not seem 
 significant given all the troubles of the world, a  Coke vs. Pepsi standoff 
 of no consequence, no motivator beyond simple group bonding ("Go Team!").</p><p>     
 
But why has this difference of views remained a divisor of programmer culture 
 for more than two decades now? Why has it remained intact as the PC, 
 graphical user interfaces, the mouse, the Internet and Open Source each 
 altered the computation landscape?  </p><p>    
 
 "As far back I can remember both, the hacker population has been split 50/50 
 [between] EMACS [and] vi," emails Eric Raymond, who counts as many of his 
 roles in the Open Source software and hacker communities as a long-time 
 observer/participant anthropologist. "Pico, joe, MicroEmacs, and other 
 editors have basically been down in the statistical noise during the whole 
 period." Raymond can personally date the vi/EMACS split back to 1985 and 
 stipulates that, in all likelihood, it went on long before that.</p><p>

As early as 1991, Raymond recorded  the vi vs. EMACS "holy war" in the 
 <a href="http://www.tuxedo.org/jargon/">Jargon File</a>, perhaps the 
 ultimate collection of hacker terminology.</p><p>
When pressed, most people familiar with both editors will say the
difference between the two is one of speed vs. flexibility, with vi
users pointing to how darn quickly they can move around and EMACS
lovers touting their immense number of options. Vi users deride EMACS
for being unnecessarily ostentatious; EMACS users derided vi for being
difficult to learn and limited in scope. </p><p>
So the great text editor debate of our time comes down to the technical
equivalent of "tastes great/less filling?" Well, yes, kind of. But like
with all matters of religion -- or war -- the deeper you dig, the
murkier the issues get.</p><p> 

 But there is significance here. These editors are the <i>tabula rasa</i> 
 upon which much of cyberspace has been built. That these tools, each 
 designed to be transparent to the end user, are subject to such fierce and 
 competing loyalties, reveals something about some primordial assumptions 
 people have about the best ways of getting things done.  </p><p>

<b>Vi: The editor that time forgot?</b></p><p>     
 
At first glance, outsiders might see vi as the editor that time forgot. It's 
 not just that you have to open up a terminal window just to use the 
 thing. That's the best way to get to EMACS, too. But even with the VIM, the 
 updated version most vi users employ these days, one can't help but to marvel 
 at (or become frustrated over) the sheer lack of intuitiveness of how it works. 
 </p><p>     
 Even the webmaster of the <a href="http://www.thomer.com/thomer/vi/vi.html"> 
 VI Lovers Home Page</a> admits that the learning curve is steep.  "Vi 
 doesn't get fast before you know 25 commands or so," wrote Amsterdam native 
 Thomer Gil, now working on a computer science Ph.d. at the Massachusetts Institute of Technology.  </p><p>
 
Gil's been likened by his office-mates to a "caveman wielding ax and club" 
 for his use of VIM.</p><p>
 
Of all vi's perceived shortcomings, perhaps the most noticeable is how you 
 need to toggle the insert key just to type anything onto the screen. Vi has 
 two modes: One is the "insert" mode where you can enter text. You get to that 
 mode by hitting the "insert" key on the keyboard. But there is also the 
 command mode where you can't enter text, but instead enter relevant commands. 
 From insert mode, you can get there by hitting the escape key.  
 </p><p>     
 So imagine the unsuspecting first-time user typing away who accidentally hits 
 the escape key, only to find that not only can he longer enter text, but his 
 keystrokes are sending the program in strange directions.
 </p><p> 
The Jargon File <a href="http://www.techfak.uni-bielefeld.de/%7Ejoern/jargon/vi.HTML">dryly notes</a> 
 that this feature of vi  "tends to frustrate new users no end, as it will 
 neither take commands while expecting input text nor vice versa, and the 
 default setup provides no indication of which mode the editor is in."</p><p>
 
"Multiple modes freak people out," Gil admits.
 </p><p>
 Vi was written by Bill Joy in 1976, who forged it from two even more 
 primitive editing tools, ed and ex.  Vi stood for "visual interface," which in 1976 
 was in quite the bleeding edge in computing, according to a Joy <a href="http://www.linux-mag.com/1999-11/joy_04.html">interview</a> in <i>Linux 
 Magazine</i>. 
 </p><p>
 "I was trying to make it usable over a 300-baud modem. That's also the 
 reason you have all these funny commands. It just barely worked to use a 
 screen editor over a modem, " Joy said  "So the editor was optimized so that 
 you could edit and feel productive when it was painting slower than you could 
 think." </p><p>

In that interview, Joy contrasted the development environment of vi to that 
 of EMACS, which, he said was written for systems with blazing fiber-channel 
 links and monster PDP-10's.     
 </p><p>
"So they could have funny commands with the screen shimmering and all
that, and meanwhile, I'm sitting at home in sort of World War II
surplus housing at Berkeley with a modem and a terminal that can just
barely get the cursor off the bottom line," Joy said, perhaps sounding
a bit envious. "People don't know that vi was written for a world that
doesn't exist anymore." </p><p>
Yet, while vi should have died out in the early '80s as network and 
 processor speed increased, instead, it has flourished. The <a href="http://www.math.fu-berlin.de/%7Eguckes/vi/">VI Pages </a>lists close to 30 vi 
 clones from elvis and VIM to such obscurities as WinVi and vigor. 
 </p><p>  
  Tim O'Reilly, mastermind behind the O'Reilly &amp; Associates publishing company 
  noted on the company's <a href="http://www.oreilly.com/ask_tim/unix_editor.html"><i>Ask Tim</i></a> column 
 that his company sells twice as many vi books than EMACS ones. Plus, whenever 
 O'Reilly sponsors a vi. vs. EMACS paintball game at some convention, 
 invariably twice as many volunteers sign up to defend the honor of vi than EMACS.  </p><p>

 So what is the appeal? That's best described by the 
 <a href="http://www.splange.freeserve.co.uk/misc/vi.html">Cult of VI</a>
 in which John Arundel writes, "Watching a vi guru doing some heavy editing on 
 a file, as her fingers fly over the keys and textual transformations sweep 
 across the screen, one could believe that one is in the presence of 
 supernatural powers."</p><p>

Gil publishes a few examples of this wizardry on his Web site. "A key 
 concept in vi is combining a certain action (delete, copy to buffer, 
 capitalize, etc.) with a movement (go to line 25, go to end of document, go 
 to next occurrence of 'foo,' go to 2nd occurrence of character 'x' in 
 this line, etc.)."  
 </p><p>
 "Huh?" I email him.
 </p><p> 
Gil sends back an example: "If, for example, a document contains the lines: 
 'a b c d e f g h' and the cursor is location on 'b,' then I can type 
 'd/f&lt;enter&gt;.' "
 </p><p>
 The first "d" means delete, the "/" is a search function, so what this 
 command will do is delete from b to f.</p><p>

"No special circumstances 
 required to use this . . . Delete words, sentences. Go back to where I was 
 before. 'Oh no, jump back again. Undo what I did, redo it,' " Gil writes.
 </p><p>     
 Gil stipulates you can do tricks like this one on EMACS, too. However, he says 
 it requires memorization of unwieldy "funky Ctrl-X Ctrl-c Alt-F4 key 
 combinations" to execute.
 </p><p>
Another trick Gil reveals is how VI allows users move around in files. "The 
 stupid way is using arrow keys; there are many other, more advanced, ways to 
 move around," Gil writes. Among the advanced forms of carriage vi offers is 
 the option to jet to the last or last few cursor jumps, or to the next 
 occurrence of a particular word, or to the next sentence or paragraph.
 </p><p> 
 Even the dual mode "feature" becomes transparent to users. About a year ago, 
 A while back I interviewed Jon Lasser to write about his then-recently published book <a href="http://www.tux.org/%7Elasser/think-unix/"><i>Think Unix</i></a>, (the 
 manuscript of which, he told me, was composed entirely in vi). The 
 conversation eventually came around to vi, and I complained about the two 
 modes. </p><p>
  
Lasser explained that he saw no difference between working in vi and in word 
 processors like StarOffice or Microsoft Word. In Word, when you move your 
 pointer out of the screen area, you can't type in text. You have, in effect, 
 moved from insert mode to command mode. "It's the same thing," he 
 explained. </p><p>     
 
As O'Reilly wrote about vi: "Like a lot of things about UNIX, it only *seems* 
 difficult."
 </p><p>
 <b>More is more with EMACS?</b>
 </p><p>
When vi loyalist O'Reilly wrote in <i>Ask Tim</i> that he first shifted from 
 EMACS to vi only after his customized EMACS profile was trashed, it was one 
 of those subtle jabs vi users like to use against EMACS.      
 </p><p>     
 EMACS stands in sharp contrast to vi's pristine limitation of commands, with 
 its almost infinite customizability. Given human nature being what it is, 
 however, such power in the hands of users may not always be a best thing. 
 </p><p>
 As the <a href="http://family.zawodny.com/jzawodn/emacs/">Emacs-Beginner-HOWTO</a> 
 puts it, EMACS can be a text editor, mail client, news reader, word 
 processor, script editor, and integrated development environment for 
 programming languages. </p><p>
  
The key to this is the multiple modes, each with a unique command set, that 
 EMACS offers. Want to check email? Just flip over to the email mode. Want 
 to writing a program in C++? Use the C++ mode. Need to author some Web pages? 
 Flip into the html-helper mode.</p><p>

And on top of all this, you can also customize EMACS and even add new 
 functions, usually through modifying the Lisp code. </p><p>     

All of which many vi users see as terribly presumptuous for what is 
 supposed to be a simple text editor, not to mention distracting for the user. 
 The ongoing joke about EMACS is that it is an operating system with a text 
 editor attached. </p><p>     

"EMACS as such actually started out as a standards project," emails Guy 
 Steele, one of the originators of EMACS, along with Richard Stallman, who 
 later founded the Free Software Foundation. </p><p>
The way Steele recalls, Stallman maintained an early editor for PDP-10
called TECO, which stood for "Text Editor and COrrector."Although
certain keystrokes would perform editing commands, Stallman created a
user-programmable table "such that each keystroke performed a lookup in
the table describing what to do for that keystroke," according to
Steele. "One option was to execute a user-specified TECO macro." </p><p>     

Using this macro functionality, users were programming custom sets of 
 macros to be attached to various keystrokes, but this became 
 problematic when programmers started collaborating on programs and found 
 out they had few common keystrokes between them. </p><p>     

"The user community had become fragmented with respect to the skills of 
 text (and program) editing," Steele writes. So Steele, along with David Moon 
 and Stallman, took on the project of integrating all the ideas into a 
 unified command set. </p><p>    

 "I made up a matrix on paper and did a lot of running back and forth 
 among the implementers and users of the various macro packages," Steele 
 emails. </p><p>     

"I remember this very well," recalls Dan Weinreb, who was one of the 
 first alpha testers of EMACS. "Guy had a clipboard with a piece of paper 
 showing all the key bindings, and he carefully and diplomatically collected 
 input and comments from everyone to put together the
 unified, standard key bindings."   </p><p>     

After a few months, Steele, busy trying to finish his master's 
 dissertation, handed the work over to Stallman. And the rest is history. </p><p>     

That the flexibility was baked in from the start gives EMACS its edge, 
 say hardcore users. </p><p>     

"I think of EMACS as the Swiss Army Knife of editors," emails Debra 
 Cameron, co-author of  <a href="http://www.oreilly.com/catalog/gnu2/index.html"><i>Learning GNU Emacs 
 </i></a> and president of <a href="http://www.camconsulting.com/">Cameron 
 Consulting</a>. "It is a complete work environment, a microcosm. If you think 
 of something you wish it did, you will probably find out (after looking 
 around) that it already does it. If it doesn't, you can extend it and make it 
 do what you wish it did."</p><p>
 
<b>Can't we all just get along?</b> </p><p>

So how does EMACS contrast to vi?</p><p>     

"I have seen very adept vi users do some pretty neat tricks, but I still 
 think vi is (just) an editor, even if for some it is a great editor," 
 emails Cameron.  "[It] always, always works the same way. In this sense, vi 
 is like McDonald's; no matter where you go, it is exactly the same."</p><p>     

"Do you want an editor that can be modified to your needs and quirks and 
 which does many, many things or do you just want to be able to quickly edit files 
 on any machine?" she asks. "For people who have to move around from one 
 computer to another constantly,  this consistency can be a real advantage." </p><p>    
 
In other words, EMACS = flexibility, whereas vi = uniformity? </p><p>     

Here's where things get murky. </p><p>     

"EMACS is certainly more complex than vi, but I don't believe it's more 
 powerful in any sort of useful way, because vi was designed to be part of a 
 UNIX system and to interact with those tools," counters Jon Lasser. </p><p>
Mind you, for Lasser, "useful" means the way that vi allows you to read
documents directly from a UNIX pipe from another process, "like you
would in any other UNIX application," he explains. So, the arcane
string of keystrokes "&lt;esc&gt; :r !ls&lt;enter&gt;" entered into vi
(in command mode, remember) reads into the buffer the output from the
"ls" program, or a listing of files from the current directory. And a
pipe from any other UNIX program would work as well. </p><p>     

As for editing a large number of files automatically in vi, Lasser says 
 that's why we have "sed, awk, and all of the other UNIX text-processing 
 tools. </p><p>

"Text processing is what UNIX was designed for, and vi was designed to be 
 part of such a system," Lasser writes. </p><p>     

Maybe the underlying issue between EMACS and vi isn't one of uniformity 
 versus flexibility at all. After all, both editors offer flexibility, its just 
 that with vi, it's through UNIX itself, whereas EMACS achieves it by building on 
 top of the system. </p><p>     

And, for that matter, the only point of flexibility anyway is to make the 
 job go faster. If you wanted straightforward no-frills text processing, you 
 could go with Pico, which offers just a blank screen and none of the 
 newbie-confusing features of either vi or EMACS. What both of these editors 
 offer are advanced ways of narrowing the gap between the speed of the fingers 
 on the keyboard and the speed of the programmer's brain.  </p><p>
In other words, could it be that these editors offer the same thing,
but demand different ways of thinking from their users? Vi requires the
patience to learn its quirky ways, though once you master them, you're
free to take your act to any UNIX system. EMACS endows you with mad
freedoms in customizing your setup as you see fit, though if you're not
careful, you'll become prisoner to your own configuration.</p><p>     

Sometime during the great hike of improving self-efficiency that all good 
 programmers take, vi and EMACS users cross paths, each coming from a different 
 direction. And when they meet, they usually throw stones at one another. </p><p>     

But it's all good. </p><p> 

"I don't think there is a strong difference in functionality. Both 
 editors do a fine job and it just comes down to what people learn first," Gil 
 writes. "Since most people know EMACS, they will teach others EMACS. Hence, 
 most people use EMACS, etc." </p><p> 

And so the feud will continue ... </p></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/9202320087268491885</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/9202320087268491885</guid>
    <pubDate>Tue, 26 Aug 2008 20:49:01 +0800</pubDate>
    <dcterms:modified>2008-08-26T20:49:01+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Linux环境下重新编译GCC-4.3.0]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200872544332420</link>
    <description><![CDATA[<div><DIV>
<P>GCC是Unix下的程序编译器的集合,包括C,C++,Fortran77,Java等,升级GCC有助于缩短编译过程的时间,生成更加高效的程序,但是也可能会出现编译后的程序比较大.目前最新的版本是4.3.接下来就开始安装4.3版本.</P>
<P>首先要确认,你的Linux环境有那些编译语言.本人所用的系统为RedHat AS 4.0 U6版本</P>
<P>#gcc -v<BR>Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.3/specs<BR>Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux<BR>Thread model: posix<BR>gcc version 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)<BR>显示GCC的版本信息.</P>
<P>GCC环境可以不包含任何编译器,默认安装中会安装上C,C++,g77和Java.一般在升级GCC和编译器时需要用户指定升级那些编译器,本次将着重介绍升级C和C++的编译器,其中包括g95.g95即Fortran语言的最新版,很多时候,源码依然调用g77进行编译.</P>
<P>#gcc<BR>gcc: no input files<BR># c++<BR>c++: no input files<BR># g77<BR>g77: no input files<BR>说明c,c++,g77集成在GCC中</P>
<P># java<BR>-bash: java: command not found<BR>这个表示没有安装上</P>
<P>安装GCC需要先安装mpfr和gmp (Fortran编译器需要这两个包)<BR>先卸载.<BR># rpm -qa |grep gmp<BR>gmp-devel-4.1.4-3<BR>gmp-4.1.4-3</P>
<P># rpm -e --nodeps gmp-devel-4.1.4-3<BR># rpm -e --nodeps gmp-4.1.4-3</P>
<P># wget ftp://ftp.gnu.org/gnu/gmp/gmp-4.2.2.tar.bz2<BR># tar jxf gmp-4.2.2.tar.bz2<BR># cd gmp-4.2.2<BR># ./configure --prefix=/usr --enable-cxx \<BR>--enable-mpbsd<BR>#make<BR>#make install</P>
<P># wget http://svn.cross-lfs.org/svn/repos/patches/mpfr/mpfr-2.3.1-cumulative-1.patch<BR># wget http://www.mpfr.org/mpfr-current/mpfr-2.3.1.tar.bz2<BR># tar jxf mpfr-2.3.1.tar.bz2<BR># cd mpfr-2.3.1<BR># patch -Np1 -Z -i ../mpfr-2.3.1-cumulative-1.patch<BR># ./configure --prefix=/usr --enable-shared<BR># make<BR># make install</P>
<P>安装g95<BR># wget http://ftp.g95.org/g95-x86-linux.tgz<BR># tar zxf g95-x86-linux.tgz<BR># cp g95-install/bin/i686-<A title=SuSE href="http://www.linuxidc.com/topicnews.aspx?tid=3">SuSE</A>-linux-gnu-g95 /usr/bin/g95</P>
<DIV>
<P>接下来开始安装gcc了,这里不建议彻底删除老版本的gcc,只需要把gcc指向到新的版本就行了.这样仍然可以使用老版本的gcc.</P>
<P># wget http://ftp.gnu.org/gnu/gcc/gcc-4.3.0/gcc-4.3.0.tar.bz2<BR># tar jxf gcc-4.3.0.tar.bz2<BR># cd gcc-4.3.0<BR># sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in<BR># mkdir -v ../gcc-build<BR># cd ../gcc-build<BR># ../gcc-4.3.0/configure --prefix=/usr \<BR>--libdir=/usr/lib \<BR>--libexecdir=/usr/lib \<BR>--enable-shared \<BR>--enable-threads=posix \<BR>--enable-__cxa_atexit \<BR>--enable-c99 \<BR>--enable-long-long \<BR>--enable-clocale=gnu \<BR>--disable-libstdcxx-pch \<BR>--disable-multilib \<BR>--enable-languages=c,c++,f95</P>
<P>如果在--enable-languages=中添加了本来没有的语言make的过程中会报错.</P>
<P># make bootstrap<BR># make -k check<BR># ../gcc-4.3.0/contrib/test_summary<BR># make install <BR># ln -sfv ../usr/bin/cpp /lib <BR># ln -sfv gcc /usr/bin/cc <BR># chown -Rv root:root /usr/lib/gcc/$(gcc -dumpmachine)/4.3.0/include <BR># ln -sfv `find /usr/lib/gcc -name ffitarget.h` /usr/include</P>
<P>完成后查看gcc<BR># gcc -v<BR>[root@mailserver ~]# gcc -v<BR>Using built-in specs.<BR>Target: i686-pc-linux-gnu<BR>Configured with: ../gcc-4.3.0/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-c99 --enable-long-long --enable-clocale=gnu --disable-libstdcxx-pch --disable-multilib --enable-languages=c,c++,f95<BR>Thread model: posix<BR>gcc version 4.3.0 (GCC) </P></DIV></DIV></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200872544332420</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200872544332420</guid>
    <pubDate>Mon, 25 Aug 2008 16:43:32 +0800</pubDate>
    <dcterms:modified>2008-08-25T16:43:58+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Linux上安装GCC编译器过程（转载）]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/920232008725103210839</link>
    <description><![CDATA[<div><P>2004年4月20日最新版本的GCC编译器3.4.0发布了。目前，GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序，可根据需要选择安装支持的语言。GCC 3.4.0比以前版本更好地支持了C++标准。本文以在Redhat Linux上安装GCC3.4.0为例，介绍了GCC的安装过程。</P>
<P>　　安装之前，系统中必须要有cc或者gcc等编译器，并且是可用的，或者用环境变量CC指定系统上的编译器。如果系统上没有编译器，不能安装源代码形式的GCC 3.4.0。如果是这种情况，可以在网上找一个与你系统相适应的如RPM等二进制形式的GCC软件包来安装使用。本文介绍的是以源代码形式提供的GCC软件包的安装过程，软件包本身和其安装过程同样适用于其它Linux和Unix系统。 </P>
<P>　　系统上原来的GCC编译器可能是把gcc等命令文件、库文件、头文件等分别存放到系统中的不同目录下的。与此不同，现在GCC建议我们将一个版本的GCC安装在一个单独的目录下。这样做的好处是将来不需要它的时候可以方便地删除整个目录即可（因为GCC没有uninstall功能）；缺点是在安装完成后要做一些设置工作才能使编译器工作正常。在本文中我采用这个方案安装GCC 3.4.0，并且在安装完成后，仍然能够使用原来低版本的GCC编译器，即一个系统上可以同时存在并使用多个版本的GCC编译器。 </P>
<P>　　按照本文提供的步骤和设置选项，即使以前没有安装过GCC，也可以在系统上安装上一个可工作的新版本的GCC编译器。 </P>
<P>　　1. 下载 </P>
<P>　　在GCC网站上（<A href="http://gcc.gnu.org/">http://gcc.gnu.org/</A>）或者通过网上搜索可以查找到下载资源。目前GCC的最新版本为 3.4.0。可供下载的文件一般有两种形式：gcc-3.4.0.tar.gz和gcc-3.4.0.tar.bz2，只是压缩格式不一样，内容完全一致，下载其中一种即可。 </P>
<P>　　2. 解压缩 </P>
<P>　　根据压缩格式，选择下面相应的一种方式解包（以下的“%”表示命令行提示符）： </P>
<P>　　% tar xzvf gcc-3.4.0.tar.gz <BR>　　或者 <BR>　　% bzcat gcc-3.4.0.tar.bz2 | tar xvf - </P>
<P>　　新生成的gcc-3.4.0这个目录被称为源目录，用${srcdir}表示它。以后在出现${srcdir}的地方，应该用真实的路径来替换它。用pwd命令可以查看当前路径。 </P>
<P>　　在${srcdir}/INSTALL目录下有详细的GCC安装说明，可用浏览器打开index.html阅读。 </P>
<P>　　3. 建立目标目录<BR>&nbsp;<BR>　　目标目录（用${objdir}表示）是用来存放编译结果的地方。GCC建议编译后的文件不要放在源目录${srcdir]中（虽然这样做也可以），最好单独存放在另外一个目录中，而且不能是${srcdir}的子目录。 </P>
<P>　　例如，可以这样建立一个叫 gcc-build 的目标目录（与源目录${srcdir}是同级目录）： </P>
<P>　　% mkdir gcc-build <BR>　　% cd gcc-build </P>
<P>　　以下的操作主要是在目标目录 ${objdir} 下进行。 </P>
<P>　　4. 配置<BR>&nbsp;<BR>　　配置的目的是决定将GCC编译器安装到什么地方（${destdir}），支持什么语言以及指定其它一些选项等。其中，${destdir}不能与${objdir}或${srcdir}目录相同。 </P>
<P>　　配置是通过执行${srcdir}下的configure来完成的。其命令格式为（记得用你的真实路径替换${destdir}）： </P>
<P>　　% ${srcdir}/configure --prefix=${destdir} [其它选项] </P>
<P>　　例如，如果想将GCC 3.4.0安装到/usr/local/gcc-3.4.0目录下，则${destdir}就表示这个路径。 </P>
<P>　　在我的机器上，我是这样配置的： </P>
<P>　　% ../gcc-3.4.0/configure --prefix=/usr/local/gcc-3.4.0 --enable-threads=posix --disable-checking --enable--long-long --host=i386-redhat-linux --with-system-zlib --enable-languages=c,c++,java </P>
<P>　　将GCC安装在/usr/local/gcc-3.4.0目录下，支持C/C++和JAVA语言，其它选项参见GCC提供的帮助说明。 </P>
<P>　　5. 编译 </P>
<P>　　% make </P>
<P>　　这是一个漫长的过程。在我的机器上（P4-1.6），这个过程用了50多分钟。 </P>
<P>　　6. 安装 </P>
<P>　　执行下面的命令将编译好的库文件等拷贝到${destdir}目录中（根据你设定的路径，可能需要管理员的权限）： </P>
<P>　　% make install </P>
<P>　　至此，GCC 3.4.0安装过程就完成了。 </P>
<P>　　6. 其它设置 </P>
<P>　　GCC 3.4.0的所有文件，包括命令文件（如gcc、g++）、库文件等都在${destdir}目录下分别存放，如命令文件放在bin目录下、库文件在lib下、头文件在include下等。由于命令文件和库文件所在的目录还没有包含在相应的搜索路径内，所以必须要作适当的设置之后编译器才能顺利地找到并使用它们。</P>
<P>　　6.1 gcc、g++、gcj的设置 </P>
<P>　　要想使用GCC 3.4.0的gcc等命令，简单的方法就是把它的路径${destdir}/bin放在环境变量PATH中。我不用这种方式，而是用符号连接的方式实现，这样做的好处是我仍然可以使用系统上原来的旧版本的GCC编译器。 </P>
<P>　　首先，查看原来的gcc所在的路径： </P>
<P>　　% which gcc </P>
<P>　　在我的系统上，上述命令显示：/usr/bin/gcc。因此，原来的gcc命令在/usr/bin目录下。我们可以把GCC 3.4.0中的gcc、g++、gcj等命令在/usr/bin目录下分别做一个符号连接： </P>
<P>　　% cd /usr/bin <BR>　　% ln -s ${destdir}/bin/gcc gcc34 <BR>　　% ln -s ${destdir}/bin/g++ g++34 <BR>　　% ln -s ${destdir}/bin/gcj gcj34 </P>
<P>　　这样，就可以分别使用gcc34、g++34、gcj34来调用GCC 3.4.0的gcc、g++、gcj完成对C、C++、JAVA程序的编译了。同时，仍然能够使用旧版本的GCC编译器中的gcc、g++等命令。 </P>
<P>　　6.2 库路径的设置 </P>
<P>　　将${destdir}/lib路径添加到环境变量LD_LIBRARY_PATH中，最好添加到系统的配置文件中，这样就不必要每次都设置这个环境变量了。 </P>
<P>　　例如，如果GCC 3.4.0安装在/usr/local/gcc-3.4.0目录下，在RH Linux下可以直接在命令行上执行或者在文件/etc/profile中添加下面一句： </P>
<P>　　setenv LD_LIBRARY_PATH /usr/local/gcc-3.4.0/lib:$LD_LIBRARY_PATH </P>
<P>　　7. 测试<BR>&nbsp;<BR>　　用新的编译命令（gcc34、g++34等）编译你以前的C、C++程序，检验新安装的GCC编译器是否能正常工作。 </P>
<P>　　8. 根据需要，可以删除或者保留${srcdir}和${objdir}目录。 </P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/920232008725103210839</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/920232008725103210839</guid>
    <pubDate>Mon, 25 Aug 2008 10:32:10 +0800</pubDate>
    <dcterms:modified>2008-08-25T10:32:10+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Building an application]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200872011392902</link>
    <description><![CDATA[<div><p>(Extract from Qt Documentation)<br></p><p>The tutorial examples are located in the Qt <i>examples/tutorials/tutorial</i>
directory. If you installed a binary Qt package, pre-built examples
were installed as well. If you built Qt yourself, the examples were
built at the same time. In either case, there is a lot to be learned
about using Qt by modifying and building the examples yourself.</p>
<p>Assuming you have copied an example's <tt>.cpp</tt> and <tt>.h</tt>
files to an otherwise empty directory, and you have made your changes
there, the next step is to create a Qt makefile in that directory. To
create a Qt makefile, use <a href="http://doc.trolltech.com/4.4/qmake-manual.html#qmake">qmake</a>,
the build tool supplied with Qt. Run the following two commands in the
directory containing your modified sources to create the makefile.</p>
<pre> qmake -project<br> qmake</pre>
<p>The first command tells qmake to create a project (<tt>.pro</tt>) file. The second command tells qmake to use the <tt>.pro</tt> file to create a platform-specific makefile.</p>
<p>Now you can just run <tt>make</tt> (<tt>nmake</tt> if you are using Visual Studio) to compile the program, and then you can run your first Qt application!</p></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200872011392902</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200872011392902</guid>
    <pubDate>Wed, 20 Aug 2008 11:39:02 +0800</pubDate>
    <dcterms:modified>2008-08-20T11:39:02+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[GDB中文手册  ]]></title>	
    <link>http://pannsp.blog.163.com/blog/static/92023200871972343376</link>
    <description><![CDATA[<div><P>GDB中文手册&nbsp; <BR>/****************************************************/<BR>用GDB调试程序<BR>GDB概述 2<BR>使用GDB 5<BR>GDB中运行UNIX的shell程序 8<BR>在GDB中运行程序 8<BR>调试已运行的程序 两种方法： 9<BR>暂停 / 恢复程序运行 9<BR>一、设置断点（BreakPoint） 9<BR>二、设置观察点（WatchPoint） 10<BR>三、设置捕捉点（CatchPoint） 10<BR>四、维护停止点 11<BR>五、停止条件维护 12<BR>六、为停止点设定运行命令 12<BR>七、断点菜单 13<BR>八、恢复程序运行和单步调试 13<BR>九、信号（Signals） 14<BR>十、线程（Thread Stops） 15<BR>查看栈信息 16<BR>查看源程序 18<BR>一、显示源代码 18<BR>二、搜索源代码 19<BR>三、指定源文件的路径 19<BR>四、源代码的内存 20<BR>查看运行时数据 21<BR>一、表达式 21<BR>二、程序变量 21<BR>三、数组 22<BR>四、输出格式 23<BR>五、查看内存 23<BR>六、自动显示 24<BR>七、设置显示选项 25<BR>GDB中关于显示的选项比较多，这里我只例举大多数常用的选项。 25<BR>八、历史记录 27<BR>九、GDB环境变量 28<BR>十、查看寄存器 28<BR>改变程序的执行 29<BR>一、修改变量值 29<BR>二、跳转执行 29<BR>三、产生信号量 30<BR>四、强制函数返回 30<BR>五、强制调用函数 30<BR>在不同语言中使用GDB 31<BR>后记 32</P>
<P>GDB概述<BR>GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许，各位比较喜欢那种图形界面</P>
<P>方式的，像VC、BCB等IDE的调试，但如果你是在 UNIX平台下做软件，你会发现GDB这个调试工具</P>
<P>有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长，尺有所短”就是这个道理。</P>
<P>一般来说，GDB主要帮忙你完成下面四个方面的功能：</P>
<P>1、启动你的程序，可以按照你的自定义的要求随心所欲的运行程序。<BR>2、可让被调试的程序在你所指定的调置的断点处停住。（断点可以是条件表达式）<BR>3、当程序被停住时，可以检查此时你的程序中所发生的事。<BR>4、动态的改变你程序的执行环境。</P>
<P>从上面看来，GDB和一般的调试工具没有什么两样，基本上也是完成这些功能，不过在细节上，你</P>
<P>会发现GDB这个调试工具的强大，大家可能比较习惯了图形化的调试工具，但有时候，命令行的调</P>
<P>试工具却有着图形化工具所不能完成的功能。让我们一一看来。</P>
<P>一个调试示例<BR>——————</P>
<P>源程序：tst.c<BR>1 #include &lt;stdio.h&gt;<BR>2<BR>3 int func(int n)<BR>4 {<BR>5 int sum=0,i;<BR>6 for(i=0; i&lt;n; i++)<BR>7 {<BR>8 sum+=i;<BR>9 }<BR>10 return sum;<BR>11 }<BR>12<BR>13<BR>14 main()<BR>15 {<BR>16 int i;<BR>17 long result = 0;<BR>18 for(i=1; i&lt;=100; i++)<BR>19 {<BR>20 result += i;<BR>21 }<BR>22<BR>23 printf("result[1-100] = %d \n", result );<BR>24 printf("result[1-250] = %d \n", func(250) );<BR>25 }</P>
<P>编译生成执行文件：（Linux下）<BR>hchen/test&gt; cc -g tst.c -o tst</P>
<P>使用GDB调试：</P>
<P>hchen/test&gt; gdb tst &lt;---------- 启动GDB<BR>GNU gdb 5.1.1<BR>Copyright 2002 Free Software Foundation, Inc.<BR>GDB is free software, covered by the GNU General Public License, and you are<BR>welcome to change it and/or distribute copies of it under certain conditions.<BR>Type "show copying" to see the conditions.<BR>There is absolutely no warranty for GDB. Type "show warranty" for details.<BR>This GDB was configured as "i386-suse-linux"...<BR>(gdb) l &lt;-------------------- l命令相当于list，从第一行开始例出原码。<BR>1 #include &lt;stdio.h&gt;<BR>2<BR>3 int func(int n)<BR>4 {<BR>5 int sum=0,i;<BR>6 for(i=0; i&lt;n; i++)<BR>7 {<BR>8 sum+=i;<BR>9 }<BR>10 return sum;<BR>(gdb) &lt;-------------------- 直接回车表示，重复上一次命令<BR>11 }<BR>12<BR>13<BR>14 main()<BR>15 {<BR>16 int i;<BR>17 long result = 0;<BR>18 for(i=1; i&lt;=100; i++)<BR>19 {<BR>20 result += i; <BR>(gdb) break 16 &lt;-------------------- 设置断点，在源程序第16行处。<BR>Breakpoint 1 at 0x8048496: file tst.c, line 16.<BR>(gdb) break func &lt;-------------------- 设置断点，在函数func()入口处。<BR>Breakpoint 2 at 0x8048456: file tst.c, line 5.<BR>(gdb) info break &lt;-------------------- 查看断点信息。<BR>Num Type Disp Enb Address What<BR>1 breakpoint keep y 0x08048496 in main at tst.c:16<BR>2 breakpoint keep y 0x08048456 in func at tst.c:5<BR>(gdb) r &lt;--------------------- 运行程序，run命令简写<BR>Starting program: /home/hchen/test/tst</P>
<P>Breakpoint 1, main () at tst.c:17 &lt;---------- 在断点处停住。<BR>17 long result = 0;<BR>(gdb) n &lt;--------------------- 单条语句执行，next命令简写。<BR>18 for(i=1; i&lt;=100; i++)<BR>(gdb) n<BR>20 result += i;<BR>(gdb) n<BR>18 for(i=1; i&lt;=100; i++)<BR>(gdb) n<BR>20 result += i;<BR>(gdb) c &lt;--------------------- 继续运行程序，continue命令简写。<BR>Continuing.<BR>result[1-100] = 5050 &lt;----------程序输出。</P>
<P>Breakpoint 2, func (n=250) at tst.c:5<BR>5 int sum=0,i;<BR>(gdb) n<BR>6 for(i=1; i&lt;=n; i++)<BR>(gdb) p i &lt;--------------------- 打印变量i的值，print命令简写。<BR>$1 = 134513808<BR>(gdb) n<BR>8 sum+=i;<BR>(gdb) n<BR>6 for(i=1; i&lt;=n; i++)<BR>(gdb) p sum<BR>$2 = 1<BR>(gdb) n<BR>8 sum+=i;<BR>(gdb) p i<BR>$3 = 2<BR>(gdb) n<BR>6 for(i=1; i&lt;=n; i++)<BR>(gdb) p sum<BR>$4 = 3<BR>(gdb) bt &lt;--------------------- 查看函数堆栈。<BR>#0 func (n=250) at tst.c:5<BR>#1 0x080484e4 in main () at tst.c:24<BR>#2 0x400409ed in __libc_start_main () from /lib/libc.so.6<BR>(gdb) finish &lt;--------------------- 退出函数。<BR>Run till exit from #0 func (n=250) at tst.c:5<BR>0x080484e4 in main () at tst.c:24<BR>24 printf("result[1-250] = %d \n", func(250) );<BR>value returned is $6 = 31375<BR>(gdb) c &lt;--------------------- 继续运行。<BR>Continuing.<BR>result[1-250] = 31375 &lt;----------程序输出。</P>
<P>Program exited with code 027. &lt;--------程序退出，调试结束。<BR>(gdb) q &lt;--------------------- 退出gdb。<BR>hchen/test&gt;</P>
<P>好了，有了以上的感性认识，还是让我们来系统地认识一下gdb吧。<BR>使用GDB<BR>一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序，首先在编译时，我们必须要把调试</P>
<P>信息加到可执行文件中。使用编译器（cc/gcc/g++）的 -g 参数可以做到这一点。如：</P>
<P>&gt; cc -g hello.c -o hello<BR>&gt; g++ -g hello.cpp -o hello</P>
<P>如果没有-g，你将看不见程序的函数名、变量名，所代替的全是运行时的内存地址。当你用-g把</P>
<P>调试信息加入之后，并成功编译目标代码以后，让我们来看看如何用gdb来调试他。</P>
<P>启动GDB的方法有以下几种：</P>
<P>1、gdb &lt;program&gt; <BR>program也就是你的执行文件，一般在当然目录下。</P>
<P>2、gdb &lt;program&gt; core<BR>用gdb同时调试一个运行程序和core文件，core是程序非法执行后core dump后产生的文件。</P>
<P>3、gdb &lt;program&gt; &lt;PID&gt;<BR>如果你的程序是一个服务程序，那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach</P>
<P>上去，并调试他。program应该在PATH环境变量中搜索得到。</P>
<P>&nbsp;</P>
<P>GDB启动时，可以加上一些GDB的启动开关，详细的开关可以用gdb -help查看。我在下面只例举一</P>
<P>些比较常用的参数：</P>
<P>-symbols &lt;file&gt; <BR>-s &lt;file&gt; <BR>从指定文件中读取符号表。</P>
<P>-se file <BR>从指定文件中读取符号表信息，并把他用在可执行文件中。</P>
<P>-core &lt;file&gt;<BR>-c &lt;file&gt; <BR>调试时core dump的core文件。</P>
<P>-directory &lt;directory&gt;<BR>-d &lt;directory&gt;<BR>加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。<BR>启动gdb后，就你被带入gdb的调试环境中，就可以使用gdb的命令开始调试程序了，gdb的命令可</P>
<P>以使用help命令来查看，如下所示：</P>
<P>/home/hchen&gt; gdb<BR>GNU gdb 5.1.1<BR>Copyright 2002 Free Software Foundation, Inc.<BR>GDB is free software, covered by the GNU General Public License, and you are<BR>welcome to change it and/or distribute copies of it under certain conditions.<BR>Type "show copying" to see the conditions.<BR>There is absolutely no warranty for GDB. Type "show warranty" for details.<BR>This GDB was configured as "i386-suse-linux".<BR>(gdb) help<BR>List of classes of commands:</P>
<P>aliases -- Aliases of other commands<BR>breakpoints -- Making program stop at certain points<BR>data -- Examining data<BR>files -- Specifying and examining files<BR>internals -- Maintenance commands<BR>obscure -- Obscure features<BR>running -- Running the program<BR>stack -- Examining the stack<BR>status -- Status inquiries<BR>support -- Support facilities<BR>tracepoints -- Tracing of program execution without stopping the program<BR>user-defined -- User-defined commands</P>
<P>Type "help" followed by a class name for a list of commands in that class.<BR>Type "help" followed by command name for full documentation.<BR>Command name abbreviations are allowed if unambiguous.<BR>(gdb)</P>
<P>gdb 的命令很多，gdb把之分成许多个种类。help命令只是例出gdb的命令种类，如果要看种类中</P>
<P>的命令，可以使用help &lt; class&gt;&nbsp; 命令，如：help breakpoints，查看设置断点的所有命令。也</P>
<P>可以直接help &lt;command&gt;来查看命令的帮助。</P>
<P>gdb中，输入命令时，可以不用打全命令，只用打命令的前几个字符就可以了，当然，命令的前几</P>
<P>个字符应该要标志着一个唯一的命令，在Linux下，你可以敲击两次TAB键来补齐命令的全称，如</P>
<P>果有重复的，那么gdb会把其例出来。</P>
<P>示例一：在进入函数func时，设置一个断点。可以敲入break func，或是直接就是b func<BR>(gdb) b func<BR>Breakpoint 1 at 0x8048458: file hello.c, line 10.</P>
<P>示例二：敲入b按两次TAB键，你会看到所有b打头的命令：<BR>(gdb) b<BR>backtrace break bt<BR>(gdb)</P>
<P>示例三：只记得函数的前缀，可以这样：<BR>(gdb) b make_ &lt;按TAB键&gt;<BR>（再按下一次TAB键，你会看到:）<BR>make_a_section_from_file make_environ<BR>make_abs_section make_function_type<BR>make_blockvector make_pointer_type<BR>make_cleanup make_reference_type<BR>make_command make_symbol_completion_list<BR>(gdb) b make_<BR>GDB把所有make开头的函数全部例出来给你查看。</P>
<P>示例四：调试C++的程序时，有可以函数名一样。如：<BR>(gdb) b 'bubble( M-? <BR>bubble(double,double) bubble(int,int)<BR>(gdb) b 'bubble(<BR>你可以查看到C++中的所有的重载函数及参数。（注：M-?和“按两次TAB键”是一个意思）</P>
<P>要退出gdb时，只用发quit或命令简称q就行了。 <BR>GDB中运行UNIX的shell程序<BR>在gdb环境中，你可以执行UNIX的shell的命令，使用gdb的shell命令来完成：</P>
<P>shell &lt;command string&gt;<BR>调用UNIX的shell来执行&lt;command string&gt;，环境变量SHELL中定义的UNIX的shell将会被用来执行</P>
<P>&lt; command string&gt;，如果SHELL没有定义，那就使用UNIX的标准shell：/bin/sh。（在 Windows</P>
<P>中使用 Command.com或cmd.exe）</P>
<P>还有一个gdb命令是make：<BR>make &lt;make-args&gt; <BR>可以在gdb中执行make命令来重新build自己的程序。这个命令等价于“shell make &lt;make-args&gt;</P>
<P>”。 <BR>在GDB中运行程序<BR>当以gdb &lt;program&gt;方式启动gdb后，gdb会在PATH路径和当前目录中搜索&lt;program&gt;的源文件。如</P>
<P>要确认gdb是否读到源文件，可使用l或list命令，看看gdb是否能列出源代码。</P>
<P>在gdb中，运行程序使用r或是run命令。程序的运行，你有可能需要设置下面四方面的事。</P>
<P>1、程序运行参数。<BR>set args 可指定运行时参数。（如：set args 10 20 30 40 50）<BR>show args 命令可以查看设置好的运行参数。</P>
<P>2、运行环境。<BR>path &lt;dir&gt; 可设定程序的运行路径。<BR>show paths 查看程序的运行路径。<BR>set environment varname [=value] 设置环境变量。如：set env USER=hchen<BR>show environment [varname] 查看环境变量。</P>
<P>3、工作目录。<BR>cd &lt;dir&gt; 相当于shell的cd命令。<BR>pwd 显示当前的所在目录。</P>
<P>4、程序的输入输出。<BR>info terminal 显示你程序用到的终端的模式。<BR>使用重定向控制程序输出。如：run &gt; outfile<BR>tty命令可以指写输入输出的终端设备。如：tty /dev/ttyb</P>
<P><BR>调试已运行的程序 两种方法：<BR>1、在UNIX下用ps查看正在运行的程序的PID（进程ID），然后用gdb &lt;program&gt; PID格式挂接正在</P>
<P>运行的程序。<BR>2、先用gdb &lt;program&gt;关联上源代码，并进行gdb，在gdb中用attach命令来挂接进程的PID。并用</P>
<P>detach来取消挂接的进程。<BR>暂停 / 恢复程序运行<BR>调试程序中，暂停程序运行是必须的，GDB可以方便地暂停程序的运行。你可以设置程序的在哪行</P>
<P>停住，在什么条件下停住，在收到什么信号时停往等等。以便于你查看运行时的变量，以及运行</P>
<P>时的流程。</P>
<P>当进程被gdb停住时，你可以使用info program 来查看程序的是否在运行，进程号，被暂停的原</P>
<P>因。</P>
<P>在gdb 中，我们可以有以下几种暂停方式：断点（BreakPoint）、观察点（WatchPoint）、捕捉</P>
<P>点（CatchPoint）、信号（Signals）、线程停止（Thread Stops）。如果要恢复程序运行，可以</P>
<P>使用c或是continue命令。<BR>一、设置断点（BreakPoint）</P>
<P>我们用break命令来设置断点。正面有几点设置断点的方法：</P>
<P>break &lt;function&gt; <BR>在进入指定函数时停住。C++中可以使用class::function或function(type,type)格式来指定函数</P>
<P>名。</P>
<P>break &lt;linenum&gt;<BR>在指定行号停住。</P>
<P>break +offset <BR>break -offset <BR>在当前行号的前面或后面的offset行停住。offiset为自然数。</P>
<P>break filename:linenum <BR>在源文件filename的linenum行处停住。</P>
<P>break filename:function <BR>在源文件filename的function函数的入口处停住。</P>
<P>break *address<BR>在程序运行的内存地址处停住。</P>
<P>break <BR>break命令没有参数时，表示在下一条指令处停住。</P>
<P>break ... if &lt;condition&gt;<BR>...可以是上述的参数，condition表示条件，在条件成立时停住。比如在循环境体中，可以设置</P>
<P>break if i=100，表示当i为100时停住程序。</P>
<P>查看断点时，可使用info命令，如下所示：（注：n表示断点号）<BR>info breakpoints [n] <BR>info break [n] <BR>二、设置观察点（WatchPoint）<BR>观察点一般来观察某个表达式（变量也是一种表达式）的值是否有变化了，如果有变化，马上停</P>
<P>住程序。我们有下面的几种方法来设置观察点：</P>
<P>watch &lt;expr&gt;<BR>为表达式（变量）expr设置一个观察点。一量表达式值有变化时，马上停住程序。</P>
<P>rwatch &lt;expr&gt;<BR>当表达式（变量）expr被读时，停住程序。</P>
<P>awatch &lt;expr&gt;<BR>当表达式（变量）的值被读或被写时，停住程序。</P>
<P>info watchpoints<BR>列出当前所设置了的所有观察点。<BR>三、设置捕捉点（CatchPoint）<BR>你可设置捕捉点来补捉程序运行时的一些事件。如：载入共享库（动态链接库）或是C++的异常。</P>
<P>设置捕捉点的格式为：</P>
<P>catch &lt;event&gt;<BR>当event发生时，停住程序。event可以是下面的内容：<BR>1、throw 一个C++抛出的异常。（throw为关键字）<BR>2、catch 一个C++捕捉到的异常。（catch为关键字）<BR>3、exec 调用系统调用exec时。（exec为关键字，目前此功能只在HP-UX下有用）<BR>4、fork 调用系统调用fork时。（fork为关键字，目前此功能只在HP-UX下有用）<BR>5、vfork 调用系统调用vfork时。（vfork为关键字，目前此功能只在HP-UX下有用）<BR>6、load 或 load &lt;libname&gt; 载入共享库（动态链接库）时。（load为关键字，目前此功能只在</P>
<P>HP-UX下有用）<BR>7、unload 或 unload &lt;libname&gt; 卸载共享库（动态链接库）时。（unload为关键字，目前此功</P>
<P>能只在HP-UX下有用）</P>
<P>tcatch &lt;event&gt; <BR>只设置一次捕捉点，当程序停住以后，应点被自动删除。<BR>四、维护停止点<BR>上面说了如何设置程序的停止点，GDB中的停止点也就是上述的三类。在GDB中，如果你觉得已定</P>
<P>义好的停止点没有用了，你可以使用delete、clear、disable、enable这几个命令来进行维护。</P>
<P>clear<BR>清除所有的已定义的停止点。</P>
<P>clear &lt;function&gt;<BR>clear &lt;filename:function&gt;<BR>清除所有设置在函数上的停止点。</P>
<P>clear &lt;linenum&gt;<BR>clear &lt;filename:linenum&gt;<BR>清除所有设置在指定行上的停止点。</P>
<P>delete [breakpoints] [range...]<BR>删除指定的断点，breakpoints为断点号。如果不指定断点号，则表示删除所有的断点。range 表</P>
<P>示断点号的范围（如：3-7）。其简写命令为d。</P>
<P>比删除更好的一种方法是disable停止点，disable了的停止点，GDB不会删除，当你还需要时，</P>
<P>enable即可，就好像回收站一样。</P>
<P>disable [breakpoints] [range...]<BR>disable所指定的停止点，breakpoints为停止点号。如果什么都不指定，表示disable所有的停止</P>
<P>点。简写命令是dis.</P>
<P>enable [breakpoints] [range...]<BR>enable所指定的停止点，breakpoints为停止点号。</P>
<P>enable [breakpoints] once range...<BR>enable所指定的停止点一次，当程序停止后，该停止点马上被GDB自动disable。<BR>enable [breakpoints] delete range...<BR>enable所指定的停止点一次，当程序停止后，该停止点马上被GDB自动删除。<BR>五、停止条件维护<BR>前面在说到设置断点时，我们提到过可以设置一个条件，当条件成立时，程序自动停止，这是一</P>
<P>个非常强大的功能，这里，我想专门说说这个条件的相关维护命令。一般来说，为断点设置一个</P>
<P>条件，我们使用if关键词，后面跟其断点条件。并且，条件设置好后，我们可以用condition命令</P>
<P>来修改断点的条件。（只有 break和watch命令支持if，catch目前暂不支持if）</P>
<P>condition &lt;bnum&gt; &lt;expression&gt;<BR>修改断点号为bnum的停止条件为expression。</P>
<P>condition &lt;bnum&gt;<BR>清除断点号为bnum的停止条件。</P>
<P><BR>还有一个比较特殊的维护命令ignore，你可以指定程序运行时，忽略停止条件几次。</P>
<P>ignore &lt;bnum&gt; &lt;count&gt;<BR>表示忽略断点号为bnum的停止条件count次。<BR>六、为停止点设定运行命令<BR>我们可以使用GDB提供的command命令来设置停止点的运行命令。也就是说，当运行的程序在被停</P>
<P>止住时，我们可以让其自动运行一些别的命令，这很有利行自动化调试。对基于GDB的自动化调试</P>
<P>是一个强大的支持。</P>
<P>commands [bnum]<BR>... command-list ...<BR>end</P>
<P>为断点号bnum指写一个命令列表。当程序被该断点停住时，gdb会依次运行命令列表中的命令。</P>
<P>例如：</P>
<P>break foo if x&gt;0<BR>commands<BR>printf "x is %d\n",x<BR>continue<BR>end <BR>断点设置在函数foo中，断点条件是x&gt;0，如果程序被断住后，也就是，一旦x的值在foo函数中大</P>
<P>于0，GDB会自动打印出x的值，并继续运行程序。</P>
<P>如果你要清除断点上的命令序列，那么只要简单的执行一下commands命令，并直接在打个end就行</P>
<P>了。<BR>七、断点菜单<BR>在C ++中，可能会重复出现同一个名字的函数若干次（函数重载），在这种情况下，break </P>
<P>&lt;function&gt;不能告诉GDB要停在哪个函数的入口。当然，你可以使用break &lt;function(type)&gt;也就</P>
<P>是把函数的参数类型告诉GDB，以指定一个函数。否则的话， GDB会给你列出一个断点菜单供你选</P>
<P>择你所需要的断点。你只要输入你菜单列表中的编号就可以了。如：</P>
<P>(gdb) b String::after<BR>[0] cancel<BR>[1] all<BR>[2] file:String.cc; line number:867<BR>[3] file:String.cc; line number:860<BR>[4] file:String.cc; line number:875<BR>[5] file:String.cc; line number:853<BR>[6] file:String.cc; line number:846<BR>[7] file:String.cc; line number:735<BR>&gt; 2 4 6<BR>Breakpoint 1 at 0xb26c: file String.cc, line 867.<BR>Breakpoint 2 at 0xb344: file String.cc, line 875.<BR>Breakpoint 3 at 0xafcc: file String.cc, line 846.<BR>Multiple breakpoints were set.<BR>Use the "delete" command to delete unwanted<BR>breakpoints.<BR>(gdb)</P>
<P>可见，GDB列出了所有after的重载函数，你可以选一下列表编号就行了。0表示放弃设置断点，1</P>
<P>表示所有函数都设置断点。<BR>八、恢复程序运行和单步调试<BR>当程序被停住了，你可以用continue命令恢复程序的运行直到程序结束，或下一个断点到来。也</P>
<P>可以使用step或next命令单步跟踪程序。</P>
<P>continue [ignore-count]<BR>c [ignore-count]<BR>fg [ignore-count]<BR>恢复程序运行，直到程序结束，或是下一个断点到来。ignore-count表示忽略其后的断点次数。</P>
<P>continue，c，fg三个命令都是一样的意思。</P>
<P><BR>step &lt;count&gt;<BR>单步跟踪，如果有函数调用，他会进入该函数。进入函数的前提是，此函数被编译有debug信息。</P>
<P>很像VC等工具中的step in。后面可以加count也可以不加，不加表示一条条地执行，加表示执行</P>
<P>后面的count条指令，然后再停住。</P>
<P>next &lt;count&gt;<BR>同样单步跟踪，如果有函数调用，他不会进入该函数。很像VC等工具中的step over。后面可以加</P>
<P>count也可以不加，不加表示一条条地执行，加表示执行后面的count条指令，然后再停住。</P>
<P>set step-mode<BR>set step-mode on<BR>打开step-mode模式，于是，在进行单步跟踪时，程序不会因为没有debug信息而不停住。这个参</P>
<P>数有很利于查看机器码。</P>
<P>set step-mod off<BR>关闭step-mode模式。</P>
<P>finish<BR>运行程序，直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。</P>
<P>until 或 u<BR>当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。</P>
<P>stepi 或 si<BR>nexti 或 ni<BR>单步跟踪一条机器指令！一条程序代码有可能由数条机器指令完成，stepi和nexti可以单步执行</P>
<P>机器指令。与之一样有相同功能的命令是 “display/i $pc” ，当运行完这个命令后，单步跟踪</P>
<P>会在打出程序代码的同时打出机器指令（也就是汇编代码）<BR>九、信号（Signals）<BR>信号是一种软中断，是一种处理异步事件的方法。一般来说，操作系统都支持许多信号。尤其是</P>
<P>UNIX，比较重要应用程序一般都会处理信号。UNIX 定义了许多信号，比如SIGINT表示中断字符信</P>
<P>号，也就是Ctrl+C的信号，SIGBUS表示硬件故障的信号；SIGCHLD表示子进程状态改变信号； </P>
<P>SIGKILL表示终止程序运行的信号，等等。信号量编程是UNIX下非常重要的一种技术。</P>
<P>GDB有能力在你调试程序的时候处理任何一种信号，你可以告诉GDB需要处理哪一种信号。你可以</P>
<P>要求GDB收到你所指定的信号时，马上停住正在运行的程序，以供你进行调试。你可以用GDB的</P>
<P>handle命令来完成这一功能。</P>
<P>handle &lt;signal&gt; &lt;keywords...&gt;<BR>在GDB 中定义一个信号处理。信号&lt;signal&gt;可以以SIG开头或不以SIG开头，可以用定义一个要处</P>
<P>理信号的范围（如：SIGIO- SIGKILL，表示处理从SIGIO信号到SIGKILL的信号，其中包括SIGIO，</P>
<P>SIGIOT，SIGKILL三个信号），也可以使用关键字 all来标明要处理所有的信号。一旦被调试的程</P>
<P>序接收到信号，运行程序马上会被GDB停住，以供调试。其&lt; keywords&gt;可以是以下几种关键字的</P>
<P>一个或多个。</P>
<P>nostop<BR>当被调试的程序收到信号时，GDB不会停住程序的运行，但会打出消息告诉你收到这种信号。<BR>stop<BR>当被调试的程序收到信号时，GDB会停住你的程序。<BR>print<BR>当被调试的程序收到信号时，GDB会显示出一条信息。<BR>noprint<BR>当被调试的程序收到信号时，GDB不会告诉你收到信号的信息。<BR>pass<BR>noignore<BR>当被调试的程序收到信号时，GDB不处理信号。这表示，GDB会把这个信号交给被调试程序会处理</P>
<P>。<BR>nopass<BR>ignore<BR>当被调试的程序收到信号时，GDB不会让被调试程序来处理这个信号。</P>
<P>info signals<BR>info handle<BR>查看有哪些信号在被GDB检测中。<BR>十、线程（Thread Stops）<BR>如果你程序是多线程的话，你可以定义你的断点是否在所有的线程上，或是在某个特定的线程。</P>
<P>GDB很容易帮你完成这一工作。</P>
<P>break &lt;linespec&gt; thread &lt;threadno&gt;<BR>break &lt;linespec&gt; thread &lt;threadno&gt; if ...<BR>linespec 指定了断点设置在的源程序的行号。threadno指定了线程的ID，注意，这个ID是GDB分</P>
<P>配的，你可以通过“info threads”命令来查看正在运行程序中的线程信息。如果你不指定</P>
<P>thread &lt;threadno&gt;则表示你的断点设在所有线程上面。你还可以为某线程指定断点条件。如：</P>
<P>(gdb) break frik.c:13 thread 28 if bartab &gt; lim</P>
<P>当你的程序被GDB停住时，所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。而</P>
<P>在你恢复程序运行时，所有的线程也会被恢复运行。那怕是主进程在被单步调试时。<BR>查看栈信息<BR>当程序被停住了，你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函</P>
<P>数，函数的地址，函数参数，函数内的局部变量都会被压入“栈”（Stack）中。你可以用GDB命</P>
<P>令来查看当前的栈中的信息。</P>
<P>下面是一些查看函数调用栈信息的GDB命令：</P>
<P>backtrace <BR>bt <BR>打印当前的函数调用栈的所有信息。如：</P>
<P>(gdb) bt<BR>#0 func (n=250) at tst.c:6<BR>#1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30<BR>#2 0x400409ed in __libc_start_main () from /lib/libc.so.6</P>
<P>从上可以看出函数的调用栈信息：__libc_start_main --&gt; main() --&gt; func()</P>
<P><BR>backtrace &lt;n&gt;<BR>bt &lt;n&gt; <BR>n是一个正整数，表示只打印栈顶上n层的栈信息。</P>
<P>backtrace &lt;-n&gt; <BR>bt &lt;-n&gt; <BR>-n表一个负整数，表示只打印栈底下n层的栈信息。</P>
<P>如果你要查看某一层的信息，你需要在切换当前的栈，一般来说，程序停止时，最顶层的栈就是</P>
<P>当前栈，如果你要查看栈下面层的详细信息，首先要做的是切换当前栈。</P>
<P>frame &lt;n&gt; <BR>f &lt;n&gt; <BR>n是一个从0开始的整数，是栈中的层编号。比如：frame 0，表示栈顶，frame 1，表示栈的第二</P>
<P>层。</P>
<P>up &lt;n&gt;<BR>表示向栈的上面移动n层，可以不打n，表示向上移动一层。 </P>
<P>down &lt;n&gt; <BR>表示向栈的下面移动n层，可以不打n，表示向下移动一层。 </P>
<P>上面的命令，都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命</P>
<P>令：</P>
<P>select-frame &lt;n&gt; 对应于 frame 命令。<BR>up-silently &lt;n&gt; 对应于 up 命令。<BR>down-silently &lt;n&gt; 对应于 down 命令。</P>
<P><BR>查看当前栈层的信息，你可以用以下GDB命令：</P>
<P>frame 或 f <BR>会打印出这些信息：栈的层编号，当前的函数名，函数参数值，函数所在文件及行号，函数执行</P>
<P>到的语句。</P>
<P>info frame <BR>info f <BR>这个命令会打印出更为详细的当前栈层的信息，只不过，大多数都是运行时的内内地址。比如：</P>
<P>函数地址，调用函数的地址，被调用函数的地址，目前的函数是由什么样的程序语言写成的、函</P>
<P>数参数地址及值、局部变量的地址等等。如：<BR>(gdb) info f<BR>Stack level 0, frame at 0xbffff5d4:<BR>eip = 0x804845d in func (tst.c:6); saved eip 0x8048524<BR>called by frame at 0xbffff60c<BR>source language c.<BR>Arglist at 0xbffff5d4, args: n=250<BR>Locals at 0xbffff5d4, Previous frame's sp is 0x0<BR>Saved registers:<BR>ebp at 0xbffff5d4, eip at 0xbffff5d8</P>
<P>info args<BR>打印出当前函数的参数名及其值。</P>
<P>info locals<BR>打印出当前函数中所有局部变量及其值。</P>
<P>info catch<BR>打印出当前的函数中的异常处理信息。<BR>查看源程序<BR>一、显示源代码<BR>GDB&nbsp; 可以打印出所调试程序的源代码，当然，在程序编译时一定要加上-g的参数，把源程序信息</P>
<P>编译到执行文件中。不然就看不到源程序了。当程序停下来以后， GDB会报告程序停在了那个文</P>
<P>件的第几行上。你可以用list命令来打印程序的源代码。还是来看一看查看源代码的GDB命令吧。</P>
<P>list &lt;linenum&gt;<BR>显示程序第linenum行的周围的源程序。</P>
<P>list &lt;function&gt; <BR>显示函数名为function的函数的源程序。</P>
<P>list <BR>显示当前行后面的源程序。</P>
<P>list - <BR>显示当前行前面的源程序。</P>
<P>一般是打印当前行的上5行和下5行，如果显示函数是是上2行下8行，默认是10行，当然，你也可</P>
<P>以定制显示的范围，使用下面命令可以设置一次显示源程序的行数。</P>
<P>set listsize &lt;count&gt;<BR>设置一次显示源代码的行数。</P>
<P>show listsize<BR>查看当前listsize的设置。</P>
<P><BR>list命令还有下面的用法：</P>
<P>list &lt;first&gt;, &lt;last&gt;<BR>显示从first行到last行之间的源代码。</P>
<P>list , &lt;last&gt;<BR>显示从当前行到last行之间的源代码。</P>
<P>list +<BR>往后显示源代码。</P>
<P><BR>一般来说在list后面可以跟以下这们的参数：</P>
<P>&lt;linenum&gt; 行号。<BR>&lt;+offset&gt; 当前行号的正偏移量。<BR>&lt;-offset&gt; 当前行号的负偏移量。<BR>&lt;filename:linenum&gt; 哪个文件的哪一行。<BR>&lt;function&gt; 函数名。<BR>&lt;filename:function&gt; 哪个文件中的哪个函数。<BR>&lt;*address&gt; 程序运行时的语句在内存中的地址。<BR>二、搜索源代码<BR>不仅如此，GDB还提供了源代码搜索的命令：</P>
<P>forward-search &lt;regexp&gt; <BR>search &lt;regexp&gt;<BR>向前面搜索。</P>
<P>reverse-search &lt;regexp&gt; <BR>全部搜索。</P>
<P>其中，&lt;regexp&gt;就是正则表达式，也主一个字符串的匹配模式，关于正则表达式，我就不在这里</P>
<P>讲了，还请各位查看相关资料。<BR>三、指定源文件的路径<BR>某些时候，用-g编译过后的执行程序中只是包括了源文件的名字，没有路径名。GDB提供了可以让</P>
<P>你指定源文件的路径的命令，以便GDB进行搜索。</P>
<P>directory &lt;dirname ... &gt;<BR>dir &lt;dirname ... &gt;<BR>加一个源文件路径到当前路径的前面。如果你要指定多个路径，UNIX下你可以使用“:”，</P>
<P>Windows下你可以使用“;”。<BR>directory <BR>清除所有的自定义的源文件搜索路径信息。</P>
<P>show directories <BR>显示定义了的源文件搜索路径。</P>
<P>四、源代码的内存<BR>你可以使用info line命令来查看源代码在内存中的地址。info line后面可以跟“行号”，“函</P>
<P>数名”，“文件名:行号”，“文件名:函数名”，这个命令会打印出所指定的源码在运行时的内</P>
<P>存地址，如：</P>
<P>(gdb) info line tst.c:func<BR>Line 5 of "tst.c" starts at address 0x8048456 &lt;func+6&gt; and ends at 0x804845d </P>
<P>&lt;func+13&gt;.</P>
<P>还有一个命令（disassemble）你可以查看源程序的当前执行时的机器码，这个命令会把目前内存</P>
<P>中的指令dump出来。如下面的示例表示查看函数func的汇编代码。</P>
<P>(gdb) disassemble func<BR>Dump of assembler code for function func:<BR>0x8048450 &lt;func&gt;: push %ebp<BR>0x8048451 &lt;func+1&gt;: mov %esp,%ebp<BR>0x8048453 &lt;func+3&gt;: sub $0x18,%esp<BR>0x8048456 &lt;func+6&gt;: movl $0x0,0xfffffffc(%ebp)<BR>0x804845d &lt;func+13&gt;: movl $0x1,0xfffffff8(%ebp)<BR>0x8048464 &lt;func+20&gt;: mov 0xfffffff8(%ebp),%eax<BR>0x8048467 &lt;func+23&gt;: cmp 0x8(%ebp),%eax<BR>0x804846a &lt;func+26&gt;: jle 0x8048470 &lt;func+32&gt;<BR>0x804846c &lt;func+28&gt;: jmp 0x8048480 &lt;func+48&gt;<BR>0x804846e &lt;func+30&gt;: mov %esi,%esi<BR>0x8048470 &lt;func+32&gt;: mov 0xfffffff8(%ebp),%eax<BR>0x8048473 &lt;func+35&gt;: add %eax,0xfffffffc(%ebp)<BR>0x8048476 &lt;func+38&gt;: incl 0xfffffff8(%ebp)<BR>0x8048479 &lt;func+41&gt;: jmp 0x8048464 &lt;func+20&gt;<BR>0x804847b &lt;func+43&gt;: nop<BR>0x804847c &lt;func+44&gt;: lea 0x0(%esi,1),%esi<BR>0x8048480 &lt;func+48&gt;: mov 0xfffffffc(%ebp),%edx<BR>0x8048483 &lt;func+51&gt;: mov %edx,%eax<BR>0x8048485 &lt;func+53&gt;: jmp 0x8048487 &lt;func+55&gt;<BR>0x8048487 &lt;func+55&gt;: mov %ebp,%esp<BR>0x8048489 &lt;func+57&gt;: pop %ebp<BR>0x804848a &lt;func+58&gt;: ret<BR>End of assembler dump.</P>
<P><BR>查看运行时数据<BR>在你调试程序时，当程序被停住时，你可以使用print命令（简写命令为p），或是同义命令</P>
<P>inspect来查看当前程序的运行数据。print命令的格式是：</P>
<P>print &lt;expr&gt;<BR>print /&lt;f&gt; &lt;expr&gt;<BR>&lt;expr&gt;是表达式，是你所调试的程序的语言的表达式（GDB可以调试多种编程语言），&lt;f&gt;是输出</P>
<P>的格式，比如，如果要把表达式按16进制的格式输出，那么就是/x。</P>
<P>一、表达式<BR>print和许多GDB的命令一样，可以接受一个表达式，GDB会根据当前的程序运行的数据来计算这个</P>
<P>表达式，既然是表达式，那么就可以是当前程序运行中的const常量、变量、函数等内容。可惜的</P>
<P>是GDB不能使用你在程序中所定义的宏。</P>
<P>表达式的语法应该是当前所调试的语言的语法，由于C/C++是一种大众型的语言，所以，本文中的</P>
<P>例子都是关于C/C++的。（而关于用GDB调试其它语言的章节，我将在后面介绍）</P>
<P>在表达式中，有几种GDB所支持的操作符，它们可以用在任何一种语言中。</P>
<P>@<BR>是一个和数组有关的操作符，在后面会有更详细的说明。</P>
<P>::<BR>指定一个在文件或是一个函数中的变量。</P>
<P>{&lt;type&gt;} &lt;addr&gt;<BR>表示一个指向内存地址&lt;addr&gt;的类型为type的一个对象。</P>
<P>二、程序变量<BR>在GDB中，你可以随时查看以下三种变量的值：<BR>1、全局变量（所有文件可见的）<BR>2、静态全局变量（当前文件可见的）<BR>3、局部变量（当前Scope可见的）</P>
<P>如果你的局部变量和全局变量发生冲突（也就是重名），一般情况下是局部变量会隐藏全局变量</P>
<P>，也就是说，如果一个全局变量和一个函数中的局部变量同名时，如果当前停止点在函数中，用</P>
<P>print显示出的变量的值会是函数中的局部变量的值。如果此时你想查看全局变量的值时，你可以</P>
<P>使用“::”操作符：</P>
<P>file::variable<BR>function::variable<BR>可以通过这种形式指定你所想查看的变量，是哪个文件中的或是哪个函数中的。例如，查看文件</P>
<P>f2.c中的全局变量x的值：</P>
<P>gdb) p 'f2.c'::x</P>
<P>当然，“::”操作符会和C++中的发生冲突，GDB能自动识别“::” 是否C++的操作符，所以你不</P>
<P>必担心在调试C++程序时会出现异常。</P>
<P>另外，需要注意的是，如果你的程序编译时开启了优化选项，那么在用GDB调试被优化过的程序时</P>
<P>，可能会发生某些变量不能访问，或是取值错误码的情况。这个是很正常的，因为优化程序会删</P>
<P>改你的程序，整理你程序的语句顺序，剔除一些无意义的变量等，所以在GDB调试这种程序时，运</P>
<P>行时的指令和你所编写指令就有不一样，也就会出现你所想象不到的结果。对付这种情况时，需</P>
<P>要在编译程序时关闭编译优化。一般来说，几乎所有的编译器都支持编译优化的开关，例如，GNU</P>
<P>的 C/C++编译器GCC，你可以使用“-gstabs”选项来解决这个问题。关于编译器的参数，还请查</P>
<P>看编译器的使用说明文档。<BR>三、数组<BR>有时候，你需要查看一段连续的内存空间的值。比如数组的一段，或是动态分配的数据的大小。</P>
<P>你可以使用GDB的“@”操作符，“@”的左边是第一个内存的地址的值，“@”的右边则你你想查</P>
<P>看内存的长度。例如，你的程序中有这样的语句：</P>
<P>int *array = (int *) malloc (len * sizeof (int));</P>
<P>于是，在GDB调试过程中，你可以以如下命令显示出这个动态数组的取值：</P>
<P>p <A href="mailto:*array@len">*array@len</A></P>
<P>@的左边是数组的首地址的值，也就是变量array所指向的内容，右边则是数据的长度，其保存在</P>
<P>变量len中，其输出结果，大约是下面这个样子的：</P>
<P>(gdb) p <A href="mailto:*array@len">*array@len</A><BR>$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}</P>
<P>如果是静态数组的话，可以直接用print数组名，就可以显示数组中所有数据的内容了。</P>
<P><BR>四、输出格式<BR>一般来说，GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如，你</P>
<P>想输出一个整数的十六进制，或是二进制来查看这个整型变量的中的位的情况。要做到这样，你</P>
<P>可以使用GDB的数据显示格式：</P>
<P>x 按十六进制格式显示变量。<BR>d 按十进制格式显示变量。<BR>u 按十六进制格式显示无符号整型。<BR>o 按八进制格式显示变量。<BR>t 按二进制格式显示变量。 <BR>a 按十六进制格式显示变量。<BR>c 按字符格式显示变量。<BR>f 按浮点数格式显示变量。</P>
<P>(gdb) p i<BR>$21 = 101 </P>
<P>(gdb) p/a i<BR>$22 = 0x65</P>
<P>(gdb) p/c i<BR>$23 = 101 'e'</P>
<P>(gdb) p/f i<BR>$24 = 1.41531145e-43</P>
<P>(gdb) p/x i<BR>$25 = 0x65</P>
<P>(gdb) p/t i<BR>$26 = 1100101<BR>五、查看内存<BR>你可以使用examine命令（简写是x）来查看内存地址中的值。x命令的语法如下所示：</P>
<P>x/&lt;n/f/u&gt; &lt;addr&gt; </P>
<P>n、f、u是可选的参数。</P>
<P>n 是一个正整数，表示显示内存的长度，也就是说从当前地址向后显示几个地址的内容。<BR>f 表示显示的格式，参见上面。如果地址所指的是字符串，那么格式可以是s，如果地十是指令地</P>
<P>址，那么格式可以是i。<BR>u&nbsp; 表示从当前地址往后请求的字节数，如果不指定的话，GDB默认是4个bytes。u参数可以用下面</P>
<P>的字符来代替，b表示单字节，h表示双字节，w表示四字节，g表示八字节。当我们指定了字节长</P>
<P>度后，GDB会从指内存定的内存地址开始，读写指定字节，并把其当作一个值取出来。</P>
<P>&lt;addr&gt;表示一个内存地址。</P>
<P>n/f/u三个参数可以一起使用。例如：</P>
<P>命令：x/3uh 0x54320 表示，从内存地址0x54320读取内容，h表示以双字节为一个单位，3表示三</P>
<P>个单位，u表示按十六进制显示。<BR>六、自动显示<BR>你可以设置一些自动显示的变量，当程序停住时，或是在你单步跟踪时，这些变量会自动显示。</P>
<P>相关的GDB命令是display。</P>
<P>display &lt;expr&gt; <BR>display/&lt;fmt&gt; &lt;expr&gt; <BR>display/&lt;fmt&gt; &lt;addr&gt;</P>
<P>expr是一个表达式，fmt表示显示的格式，addr表示内存地址，当你用display设定好了一个或多</P>
<P>个表达式后，只要你的程序被停下来，GDB会自动显示你所设置的这些表达式的值。</P>
<P>格式i和s同样被display支持，一个非常有用的命令是：</P>
<P>display/i $pc</P>
<P>$pc是GDB的环境变量，表示着指令的地址，/i则表示输出格式为机器指令码，也就是汇编。于是</P>
<P>当程序停下后，就会出现源代码和机器指令码相对应的情形，这是一个很有意思的功能。</P>
<P>下面是一些和display相关的GDB命令：</P>
<P>undisplay &lt;dnums...&gt;<BR>delete display &lt;dnums...&gt;<BR>删除自动显示，dnums意为所设置好了的自动显式的编号。如果要同时删除几个，编号可以用空格</P>
<P>分隔，如果要删除一个范围内的编号，可以用减号表示（如：2-5）</P>
<P>disable display &lt;dnums...&gt;<BR>enable display &lt;dnums...&gt;<BR>disable和enalbe不删除自动显示的设置，而只是让其失效和恢复。<BR>info display<BR>查看display设置的自动显示的信息。GDB会打出一张表格，向你报告当然调试中设置了多少个自</P>
<P>动显示设置，其中包括，设置的编号，表达式，是否enable。<BR>七、设置显示选项<BR>GDB中关于显示的选项比较多，这里我只例举大多数常用的选项。</P>
<P>set print address <BR>set print address on <BR>打开地址输出，当程序显示函数信息时，GDB会显出函数的参数地址。系统默认为打开的，如：</P>
<P>(gdb) f<BR>#0 set_quotes (lq=0x34c78 "&lt;&lt;", rq=0x34c88 "&gt;&gt;")<BR>at input.c:530<BR>530 if (lquote != def_lquote)</P>
<P>set print address off <BR>关闭函数的参数地址显示，如：</P>
<P>(gdb) set print addr off<BR>(gdb) f<BR>#0 set_quotes (lq="&lt;&lt;", rq="&gt;&gt;") at input.c:530<BR>530 if (lquote != def_lquote)</P>
<P>show print address <BR>查看当前地址显示选项是否打开。</P>
<P>set print array <BR>set print array on <BR>打开数组显示，打开后当数组显示时，每个元素占一行，如果不打开的话，每个元素则以逗号分</P>
<P>隔。这个选项默认是关闭的。与之相关的两个命令如下，我就不再多说了。</P>
<P>set print array off <BR>show print array </P>
<P>set print elements &lt;number-of-elements&gt;<BR>这个选项主要是设置数组的，如果你的数组太大了，那么就可以指定一个&lt;number-of-elements&gt;</P>
<P>来指定数据显示的最大长度，当到达这个长度时，GDB就不再往下显示了。如果设置为0，则表示</P>
<P>不限制。</P>
<P>show print elements <BR>查看print elements的选项信息。<BR>set print null-stop &lt;on/off&gt;<BR>如果打开了这个选项，那么当显示字符串时，遇到结束符则停止显示。这个选项默认为off。</P>
<P>set print pretty on <BR>如果打开printf pretty这个选项，那么当GDB显示结构体时会比较漂亮。如：</P>
<P>$1 = {<BR>next = 0x0,<BR>flags = {<BR>sweet = 1,<BR>sour = 1<BR>},<BR>meat = 0x54 "Pork"<BR>}</P>
<P>set print pretty off<BR>关闭printf pretty这个选项，GDB显示结构体时会如下显示：</P>
<P>$1 = {next = 0x0, flags = {sweet = 1, sour = 1}, meat = 0x54 "Pork"}</P>
<P>show print pretty <BR>查看GDB是如何显示结构体的。</P>
<P><BR>set print sevenbit-strings &lt;on/off&gt;<BR>设置字符显示，是否按“\nnn”的格式显示，如果打开，则字符串或字符数据按\nnn显示，如</P>
<P>“\065”。</P>
<P>show print sevenbit-strings<BR>查看字符显示开关是否打开。 </P>
<P>set print union &lt;on/off&gt;<BR>设置显示结构体时，是否显式其内的联合体数据。例如有以下数据结构：</P>
<P>typedef enum {Tree, Bug} Species;<BR>typedef enum {Big_tree, Acorn, Seedling} Tree_forms;<BR>typedef enum {Caterpillar, Cocoon, Butterfly}<BR>Bug_forms;</P>
<P>struct thing {<BR>Species it;<BR>union {<BR>Tree_forms tree;<BR>Bug_forms bug;<BR>} form;<BR>};</P>
<P>struct thing foo = {Tree, {Acorn}};</P>
<P>当打开这个开关时，执行 p foo 命令后，会如下显示：<BR>$1 = {it = Tree, form = {tree = Acorn, bug = Cocoon}}</P>
<P>当关闭这个开关时，执行 p foo 命令后，会如下显示：<BR>$1 = {it = Tree, form = {...}}</P>
<P>show print union<BR>查看联合体数据的显示方式</P>
<P>set print object &lt;on/off&gt;<BR>在C++中，如果一个对象指针指向其派生类，如果打开这个选项，GDB会自动按照虚方法调用的规</P>
<P>则显示输出，如果关闭这个选项的话，GDB就不管虚函数表了。这个选项默认是off。</P>
<P>show print object<BR>查看对象选项的设置。</P>
<P>set print static-members &lt;on/off&gt;<BR>这个选项表示，当显示一个C++对象中的内容是，是否显示其中的静态数据成员。默认是on。</P>
<P>show print static-members<BR>查看静态数据成员选项设置。</P>
<P>set print vtbl &lt;on/off&gt;<BR>当此选项打开时，GDB将用比较规整的格式来显示虚函数表时。其默认是关闭的。</P>
<P>show print vtbl<BR>查看虚函数显示格式的选项。<BR>八、历史记录<BR>当你用GDB的print查看程序运行时的数据时，你每一个print都会被GDB记录下来。GDB会以$1, </P>
<P>$2, $3 .....这样的方式为你每一个print命令编上号。于是，你可以使用这个编号访问以前的表</P>
<P>达式，如$1。这个功能所带来的好处是，如果你先前输入了一个比较长的表达式，如果你还想查</P>
<P>看这个表达式的值，你可以使用历史记录来访问，省去了重复输入。</P>
<P><BR>九、GDB环境变量<BR>你可以在GDB的调试环境中定义自己的变量，用来保存一些调试程序中的运行数据。要定义一个</P>
<P>GDB的变量很简单只需。使用GDB的set命令。GDB的环境变量和UNIX一样，也是以$起头。如：</P>
<P>set $foo = *object_ptr</P>
<P>使用环境变量时，GDB会在你第一次使用时创建这个变量，而在以后的使用中，则直接对其賦值。</P>
<P>环境变量没有类型，你可以给环境变量定义任一的类型。包括结构体和数组。</P>
<P>show convenience <BR>该命令查看当前所设置的所有的环境变量。</P>
<P>这是一个比较强大的功能，环境变量和程序变量的交互使用，将使得程序调试更为灵活便捷。例</P>
<P>如：</P>
<P>set $i = 0<BR>print bar[$i++]-&gt;contents</P>
<P>于是，当你就不必，print bar[0]-&gt;contents, print bar[1]-&gt; contents地输入命令了。输入这</P>
<P>样的命令后，只用敲回车，重复执行上一条语句，环境变量会自动累加，从而完成逐个输出的功</P>
<P>能。<BR>十、查看寄存器<BR>要查看寄存器的值，很简单，可以使用如下命令：</P>
<P>info registers <BR>查看寄存器的情况。（除了浮点寄存器）</P>
<P>info all-registers<BR>查看所有寄存器的情况。（包括浮点寄存器）</P>
<P>info registers &lt;regname ...&gt;<BR>查看所指定的寄存器的情况。</P>
<P>寄存器中放置了程序运行时的数据，比如程序当前运行的指令地址（ip），程序的当前堆栈地址</P>
<P>（sp）等等。你同样可以使用print命令来访问寄存器的情况，只需要在寄存器名字前加一个$符</P>
<P>号就可以了。如：p $eip。</P>
<P>&nbsp;</P>
<P>改变程序的执行<BR>一旦使用GDB挂上被调试程序，当程序运行起来后，你可以根据自己的调试思路来动态地在GDB中</P>
<P>更改当前被调试程序的运行线路或是其变量的值，这个强大的功能能够让你更好的调试你的程序</P>
<P>，比如，你可以在程序的一次运行中走遍程序的所有分支。<BR>一、修改变量值<BR>修改被调试程序运行时的变量值，在GDB中很容易实现，使用GDB的print命令即可完成。如：</P>
<P>(gdb) print x=4</P>
<P>x=4这个表达式是C/C++的语法，意为把变量x的值修改为4，如果你当前调试的语言是Pascal，那</P>
<P>么你可以使用Pascal的语法：x:=4。</P>
<P>在某些时候，很有可能你的变量和GDB中的参数冲突，如：</P>
<P>(gdb) whatis width<BR>type = double<BR>(gdb) p width<BR>$4 = 13<BR>(gdb) set width=47<BR>Invalid syntax in expression.</P>
<P>因为，set width是GDB的命令，所以，出现了“Invalid syntax in&nbsp; expression”的设置错误，</P>
<P>此时，你可以使用set var命令来告诉GDB，width不是你GDB的参数，而是程序的变量名，如：</P>
<P>(gdb) set var width=47</P>
<P>另外，还可能有些情况，GDB并不报告这种错误，所以保险起见，在你改变程序变量取值时，最好</P>
<P>都使用set var格式的GDB命令。<BR>二、跳转执行<BR>一般来说，被调试程序会按照程序代码的运行顺序依次执行。GDB提供了乱序执行的功能，也就是</P>
<P>说，GDB可以修改程序的执行顺序，可以让程序执行随意跳跃。这个功能可以由GDB的jump命令来</P>
<P>完：</P>
<P>jump &lt;linespec&gt;<BR>指定下一条语句的运行点。&lt;linespce&gt;可以是文件的行号，可以是file:line格式，可以是+num这</P>
<P>种偏移量格式。表式着下一条运行语句从哪里开始。</P>
<P>jump &lt;address&gt;<BR>这里的&lt;address&gt;是代码行的内存地址。</P>
<P>注意，jump命令不会改变当前的程序栈中的内容，所以，当你从一个函数跳到另一个函数时，当</P>
<P>函数运行完返回时进行弹栈操作时必然会发生错误，可能结果还是非常奇怪的，甚至于产生程序</P>
<P>Core Dump。所以最好是同一个函数中进行跳转。</P>
<P>熟悉汇编的人都知道，程序运行时，有一个寄存器用于保存当前代码所在的内存地址。所以，</P>
<P>jump命令也就是改变了这个寄存器中的值。于是，你可以使用“set $pc”来更改跳转执行的地址</P>
<P>。如：</P>
<P>set $pc = 0x485<BR>三、产生信号量<BR>使用singal命令，可以产生一个信号量给被调试的程序。如：中断信号Ctrl+C。这非常方便于程</P>
<P>序的调试，可以在程序运行的任意位置设置断点，并在该断点用GDB产生一个信号量，这种精确地</P>
<P>在某处产生信号非常有利程序的调试。</P>
<P>语法是：signal &lt;singal&gt;，UNIX的系统信号量通常从1到15。所以&lt;singal&gt;取值也在这个范围。</P>
<P>single命令和shell的kill命令不同，系统的kill命令发信号给被调试程序时，是由GDB截获的，</P>
<P>而single命令所发出一信号则是直接发给被调试程序的。<BR>四、强制函数返回<BR>如果你的调试断点在某个函数中，并还有语句没有执行完。你可以使用return命令强制函数忽略</P>
<P>还没有执行的语句并返回。</P>
<P>return<BR>return &lt;expression&gt;<BR>使用return命令取消当前函数的执行，并立即返回，如果指定了&lt;expression&gt;，那么该表达式的</P>
<P>值会被认作函数的返回值。<BR>五、强制调用函数<BR>call &lt;expr&gt;<BR>表达式中可以一是函数，以此达到强制调用函数的目的。并显示函数的返回值，如果函数返回值</P>
<P>是void，那么就不显示。<BR>另一个相似的命令也可以完成这一功能——print，print后面可以跟表达式，所以也可以用他来</P>
<P>调用函数，print和call的不同是，如果函数返回void，call则不显示，print则显示函数返回值</P>
<P>，并把该值存入历史数据中。<BR>在不同语言中使用GDB<BR>GDB 支持下列语言：C, C++, Fortran, PASCAL, Java, Chill, assembly, 和 Modula- 2。一般</P>
<P>说来， GDB会根据你所调试的程序来确定当然的调试语言，比如：发现文件名后缀为“.c”的，</P>
<P>GDB会认为是C程序。文件名后缀为“.C, .cc, .cp,&nbsp; .cpp, .cxx, .c++”的，GDB会认为是C++程</P>
<P>序。而后缀是“.f, .F”的，GDB会认为是Fortran程序，还有，后缀为如果是“.s, .S”的会认</P>
<P>为是汇编语言。</P>
<P>也就是说，GDB会根据你所调试的程序的语言，来设置自己的语言环境，并让GDB的命令跟着语言</P>
<P>环境的改变而改变。比如一些GDB命令需要用到表达式或变量时，这些表达式或变量的语法，完全</P>
<P>是根据当前的语言环境而改变的。例如C/C++中对指针的语法是*p，而在Modula-2中则是p^。并且</P>
<P>，如果你当前的程序是由几种不同语言一同编译成的，那到在调试过程中，GDB也能根据不同的语</P>
<P>言自动地切换语言环境。这种跟着语言环境而改变的功能，真是体贴开发人员的一种设计。</P>
<P><BR>下面是几个相关于GDB语言环境的命令：</P>
<P>show language <BR>查看当前的语言环境。如果GDB不能识为你所调试的编程语言，那么，C语言被认为是默认的环境</P>
<P>。</P>
<P>info frame <BR>查看当前函数的程序语言。</P>
<P>info source<BR>查看当前文件的程序语言。</P>
<P>如果GDB没有检测出当前的程序语言，那么你也可以手动设置当前的程序语言。使用set language</P>
<P>命令即可做到。</P>
<P>当set language命令后什么也不跟的话，你可以查看GDB所支持的语言种类：</P>
<P>(gdb) set language<BR>The currently understood settings are:</P>
<P>local or auto Automatic setting based on source file<BR>c Use the C language<BR>c++ Use the C++ language<BR>asm Use the Asm language<BR>chill Use the Chill language<BR>fortran Use the Fortran language<BR>java Use the Java language<BR>modula-2 Use the Modula-2 language<BR>pascal Use the Pascal language<BR>scheme Use the Scheme language</P>
<P>于是你可以在set language后跟上被列出来的程序语言名，来设置当前的语言环境。<BR>&nbsp;</P></div>]]></description>
	    <author><![CDATA[pannsp]]></author>
	    <comments>http://pannsp.blog.163.com/blog/static/92023200871972343376</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://pannsp.blog.163.com/blog/static/92023200871972343376</guid>
    <pubDate>Tue, 19 Aug 2008 19:23:43 +0800</pubDate>
    <dcterms:modified>2008-08-19T19:23:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[pannsp关注的博友]]></title>	
    <link>http://pannsp.blog.163.com/friends</link>
    <description><![CDATA[<div>
			<a href="http://nardolook.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/Oag3KwEkRqCMQk5pF5GTPw==/219831956811123249.jpg" border="0" />Meng</a>
</div>]]></description>
    <guid isPermaLink="true">http://pannsp.blog.163.com/friends</guid>
    <pubDate>Tue, 1 Jan 2008 00:00:00 +0800</pubDate>
    <dcterms:modified>2008-01-01T00:00:00+08:00</dcterms:modified>
  </item>    
 </channel>
</rss>