﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-sk8boy-文章分类-其他技术文章</title><link>http://www.blogjava.net/sk8boy/category/871.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 04:10:15 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 04:10:15 GMT</pubDate><ttl>60</ttl><item><title>win2003系统自动登录两法（转贴）</title><link>http://www.blogjava.net/sk8boy/articles/59485.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Fri, 21 Jul 2006 14:39:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/59485.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/59485.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/59485.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/59485.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/59485.html</trackback:ping><description><![CDATA[<a name="part">第一种方法比较复杂，但可以帮助您完全掌握Windows 2003自动登录的设置方法。首先单击“开始　运行”，在输入框中键入“regedit”打开注册表编辑器，然后在注册表编辑器左方控制台中依次单击展开“HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/Current Version/Winlogon”，再选择“编辑　添加　字符串值”，在数值名称中键入“AutoAdminLogon”，然后在窗口中的空白位置上点一下，再双击刚新建的字符串“AutoAdminLogon”，在弹出的“编辑字符串”对话框中输入“1”设置系统允许自动登录。再重复以上的操作，创建一个名为“DefaultUserName”的字符串值，编辑字符串为您准备用于自动登录的账户名称。再新创建一个名为“Defaultpassword”的字符串值，并编辑字符串为您准备用于自动登录的用户账户密码，编辑完并检查无误后，关闭注册表编辑器并重新启动电脑即可自动登录。注意，如果已有“DefaultUserName”，可以不必重新创建，直接更改原有字符串值。如果您的系统工作在局域网环境下，并且在登录到系统上时需要登录域服务器，那么您还需要再添加一个“DefaultDomainName”并编辑字符串为您登录的域名称。 <br /><br /><br />另一种方法比较简单，您只需单击“开始　运行”，并在输入框中键入“control userpasswords2”，这样就可以在“用户账户”管理窗口中清除“要使用本机，用户必须输入密码”复选项的选中状态，然后按下键盘的“Ctrl+Shift+A”，将会得到一个“自动登录”的设置对话框,您可以按自己的需要设置系统在电脑启动时自动登录使用的用户账户和密码。</a><img src ="http://www.blogjava.net/sk8boy/aggbug/59485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2006-07-21 22:39 <a href="http://www.blogjava.net/sk8boy/articles/59485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>待机、休眠究竟是咋回事？它们之间究竟有何区别？（转载）</title><link>http://www.blogjava.net/sk8boy/articles/45161.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Tue, 09 May 2006 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/45161.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/45161.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/45161.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/45161.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/45161.html</trackback:ping><description><![CDATA[<p>
				<strong>如何进入待机和休眠</strong>
				<br />
				<br />　　按下“开始→关机”，在弹出窗口中，你会看到最后一项就是“待机”。怎么没有“休眠”呢？原来，系统默认是不启用休眠的，需要我们自己设置，在控制面板中双击“电源选项”，切换到“休眠”标签，勾选“启用休眠”（见图1 ），就可以在关机菜单中看到“休眠”了。</p>
		<p align="center"> <img src="http://www.dvbbs.net/ShowImg.asp?p=/2006-4-20/68334112113_1.jpg" /></p>
		<p>
				<br />
				<strong>电脑的高级电源管理</strong>
				<br />
				<br />　　要掌握待机和休眠，必须先了解下面两个知识：ACPI和APM。<br /></p>
		<strong>1.什么是ACPI<br /><br /></strong>　　ACPI是Advanced Configuration and Power Interface的缩写，中文意为“高级配置与电源接口”，这是微软、英特尔和东芝共同开发的一种工业标准。<br /><br /><strong>ACPI主要可实现以下功能:</strong><br /><br />①用户可以使电脑在指定时间开、关； 　　<br />②即插即用设备在插入时能够由ACPI来控制，并为其供电；<br />③在无人使用电脑时可以使电脑进入休眠状态，但保证一些通信设备打开；<br />④操作系统可以根据外设和主板具体需求为它分配能源；<br />⑤操作系统可以在应用程序对时间要求不高的情况下降低时钟频率； <br />⑥使用笔记本电脑的用户可以指定电脑在低电压情况下进入低功耗状态，以保证重要应用程序运行。 　　<br /><br />　　同时，可将ACPI分为六种不同的工作状态，分别是S0到S5，它们代表的含义分别是：<br /><br />S0：电脑正常工作，所有硬件设备全部处于打开或正常工作的状态；<br />S1：也称为POS（Power on Suspend，CPU停止工作），其他的硬件设备仍然正常工作；<br />S2：将CPU关闭，但其余的硬件设备仍然运转；<br />S3：通常称为STR（Suspend to RAM，挂起到内存），将运行中的数据写入内存后关闭硬盘；<br />S4：也称为STD（Suspend to Disk，挂起到硬盘），内存信息写入硬盘，然后所有部件停止工作；<br />S5：所有硬件设备（包括电源）全部都关闭，也就是关机。<br /><br /><strong>2.什么是APM<br /></strong><br />　　APM其实是Advanced Power Manager（高级电源管理）的缩写，这是通过操作系统来控制、管理电脑硬件电源的一种管理模式，其实也是一套电脑电源管理程序（软件），版本不同，功能也有所不同，比如APM V1.0&amp;V1.1,这两个版本都是直接由BIOS执行电源管理，而APM V1.2则是可以先通过操作系统定义电源管理，然后再由BIOS负责执行。<br />在如今流行的操作系统中，都内置了APM，而在以前的DOS时代，APM并未真正被引入操作系统，所以无法执行待机、休眠等操作，重启也只能用Ctrl＋Alt＋Delete组合键或电源的Reset键。<br /><br /><strong>3.BIOS中的电源管理设置<br /></strong><br />　　一般而言，主板产商定义BIOS的默认设置都是启动了“高级电源管理”这个功能的，大多数情况下不需要我们自己设置，只需采用其默认设置即可。如果碰到以前能使用“高级电源管理”，但后来又不行了，排除系统或其他硬件可能外，才会考虑BIOS中的设置是否有问题。遇到这种情况，可以将BIOS设置还原到默认状态即可，方法为：启动电脑，用DEL键进入BIOS，用键盘上方向键定位到“Load Optimized Defaults”，然后按F10保存并退出BIOS设置即可。这里以Intel845PE主板为例，其他类型主板大致相同，这里仅作为参考。<br /><br /><strong>“Power Management Setup”常见设置举例<br /><br />ACPI Function:是否允许ACPI功能</strong><br /><br />　　ACPI Suspend Type:ACPI的挂起类型，通常这里只有一个选择，即S1（POS）状态，其实这个就包含了其他的挂起状态（S2、S3、S4）<br /><br />　　Power Management:电能管理方式，默认为User Define（用户自定义），还有就是Min Saving（最小）和Max Saving（最大）<br /><br /><strong>Video Off Method:显示器开关<br /></strong><br />　　可以设置的值:Blank Screen表示显示器不发射电子光束，即可减少耗电；V/H SYNC＋Blank表示除Blank Screen外，还可由BIOS来控制显示器水平与垂直同步信号，达到省电目的，此项为默认设置；DPMS Support，DPMS是显示器与显卡之间的电源管理协定。在两者都支持DPMS的状态下，只要BIOS支持，显卡即可通过信号通知显示器进入省电模式。<br /><br />　　HDD Power Down:设置IDE硬盘在多长时间内完全没有读写操作时，便可进入省电状态，切断硬盘电源以省电，缺省值为Disabled。<br /><br />　　Modem Use IRQ:该选项说明Modem使用的端口所占用的IRQ编号，让系统在省电状态下仍可以监视。Modem是否有活动，可以设置的值：N/A、3、4、5、7、9、11。其中N/A表示不对Modem进行监测；<br /><br />　　USB KB Wake-Up Drom S3:是否采用USB键盘唤醒，缺省值为“Disabled”。<br /><br />　　Soft-Off by PWR-Button:这是机箱电源开关的功能设置，在开机状态下，按住开机电源按键超过四秒钟，系统就一定会关机，如果不超过4秒，系统就会按此设置操作。可以设置的值：Delay 4 Sec表示超过4秒关机，如果不超过4秒则进入Suspend模式，此项为默认设置；Instant-Off表示不需要等待4秒，只要按下关机按钮立刻关机。<br /><strong>待机、休眠是怎样工作的<br /><br />1.为什么需要待机、休眠<br /><br /></strong>　　尽管电脑硬件运行速度越来越快，但操作系统的体积也在不断膨胀，使得电脑开、关机时，启动、关闭的程序越来越多，花费时间也越来越漫长。因此如何让电脑能够快速启动、一开机就进入Windows，就成为用户关心的问题。<br />于是，随着硬件和软件的升级，操作系统开始引入了高级电源管理，其作用就是在电脑闲置时关闭部分设备，将电脑进入等待休息状态，这样当需要重新使用电脑时，能够直接从等待休息状态尽快恢复到原先的工作状态，起到类似于快速启动的效果；同时，不用电脑时还能节省不少电能。<br /><br /><strong>2.把数据存到内存中——待机</strong><br /><br />　　我们都知道，从硬盘读取数据的速度远低于从内存读取的速度。因此，电脑运行时首先是将硬盘中的数据提出并存到内存中，然后再由内存将数据发送到CPU中进行处理，接着处理后的数据将先返回内存，再写进硬盘。正在运行的数据几乎都保存在内存中。然而，进入待机状态也就是将当前数据保存在内存中，然后将硬盘关闭，也就是挂起到内存（Suspend to RAM,简称STR）。<br /><br />　　这时除硬盘外，其他设备还是处于加电等待状态（也就是说唤醒时无须重新加电，通俗地说就是原地待命），所以电源、CPU、显卡等设备的风扇还是处于工作中，键盘指示灯也是亮着的。我们可以通过按键盘任意键或动一下鼠标来唤醒电脑，这时硬盘就会重新加电并启动，然后和内存、CPU等设备交换数据，从而完成返回到原来工作状态的任务。<br /><br /><strong>3.将内存装进硬盘——休眠</strong><br /><br />　　休眠，在广义上包括挂起到内存（STR，也就是待机）和挂起到硬盘（Suspend to Disk，简称STD）两种，而我们通常所指的休眠其实是STD。当电脑进入休眠状态时，电脑首先将内存中的状态复制到硬盘，然后关闭电源。此时电脑几乎和通常关机一样“安静”，你完全可以切断电源，因为保存到硬盘里面的数据不会由于断电而丢失！它和Ghost给系统做镜像的道理一样，不过与Ghost不同的是：Ghost保存并恢复的是整个系统信息，而休眠保存并恢复的是系统运行的信息。与待机相比，休眠是不能通过外部设备来唤醒的，它和正常开机一样启动电脑；不过和开机相比，休眠后启动电脑无需一个一个进程地来启动，只须要将硬盘中的内存镜像读取到内存中即可。<br /><br />　　由于内存中的资料就是电脑当前的“状态”，为保持这个状态不变（可理解为不能压缩），系统必须在硬盘中开辟一个和内存容量大小相等的空间以保证能装下整个内存的“当前状态”，而这个空间的名字就叫hiberfil.sys，它的体积一般为物理内存的大小（比如电脑的内存是256MB，这个文件的体积也将是256MB，如图1），和我们管虚拟内存叫做pagefile.sys道理是一样的。<br /><br /><strong>  你知道吗？<br /><br />为什么Windows 98中不要启用休眠？</strong><br /><br />　　原因有两个：①在刚推出Windows 98时，很多硬件对ACPI支持不是很好，所以Windows 98不能自动识别ACPI规范，不过可以在安装时用“Setup /PJ”命令来安装Windows 98，或升级Windows 98“高级电源管理”的驱动，让其支持ACPI。②由于Windows 98的内核对内存管理上的缺陷，很多时候Windows 98需要将电脑重启，清空内存后才能保证系统正常高效地运行。休眠正好是不清空内存信息而将其存储到硬盘里面，所以休眠对Windows 98系统而言，也就失去了原来的意义。相比之下，NT内核的系统在内存管理方面要优秀得多，可以连续使用很多天而无须重启，系统照样能高效运行。 
<p><strong>巧用待机、休眠，助你事半功倍<br /><br />实例1：一键待机，一键关机</strong><br /><br />　　在控制面板中打开“电源选项”，切换到“高级”标签，将“在按下计算机电源按钮时”设置为“关机”，将“在按下计算机睡眠按钮时”设置为“待机”（见图2），这样按键盘上的“Power”键就是“关机”，按“Sleep”键就是“待机”，是不是方便了不少?</p><p align="center"><img alt="Windows：俺是这样休息的" src="http://www.dvbbs.net/ShowImg.asp?p=/2006-4-20/65674112113_2.jpg" border="0" /></p><p>　　如果你的键盘没有“Sleep”键，可以在桌面右击并选择“新建→快捷方式”，在弹出对话框的“请键入项目的位置”中输入“rundll32.exe powrprof.dll,SetSuspendState”，完成后再给它设置一个快捷键组合，比如：Ctrl＋F12。这个快捷方式的功能与“在按下计算机睡眠按钮时”的设置有很大关系，如果你将这里改为“休眠”，那么它就成了休眠的快捷方式了。<br /></p><strong>实例2：让鼠标别来打搅爱机休息<br /><br /></strong>　　有不少朋友都碰上过由于鼠标太灵敏了，待机时，稍微震动一下电脑桌就唤醒了电脑，你可以依次打开“开始→运行”，输入devmgmt.msc，打开设备管理器,然后定位到“鼠标和其他指针设备”，打开当前鼠标设备的属性，切换到“电源管理”，取消“允许这台设备使用计算机脱离待机状态”（见图3），这样鼠标就不会来打扰爱机的休息了。 
<p align="center"><img alt="Windows：俺是这样休息的" src="http://www.dvbbs.net/ShowImg.asp?p=/2006-4-20/37565112113_3.jpg" border="0" /></p><p><strong>实例3：超快速关机法——待机＋断电<br /></strong><br />　　由于待机是将数据存储到内存后正常地将硬盘关闭，也就是不会损坏硬盘。如果这时断电，所有在内存中的数据将丢失。从另外一个角度看，断电造成内存数据丢失，也可看作将内存清空，而此前待机已经将硬盘关闭了。我们平时的正常关机不就是在不会损坏硬盘的情况下将其关闭，然后切断内存电源关机目的吗？从这个角度看，待机后断电就等同于安全关机。所以，当正常关机速度太慢，就可以考虑先待机，然后拔电源来到达安全关机目的。不过，在执行这项操作前，记得先保存未完成的工作，比如打开的文档，正在运行的程序等。</p><p><em>小提示</em><br /><br />　　这种关机方法虽然快捷，但毕竟不是微软推荐的方法，属于一种有风险的强迫式关机方法，但由于它对硬盘没有影响，所以不会造成硬件损坏，特别适用于那些急于关机的用户。比如同事在电梯口催促Cornel电梯来了，让我赶快出门，就只好使用这种方法了。 </p><img src ="http://www.blogjava.net/sk8boy/aggbug/45161.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2006-05-09 10:48 <a href="http://www.blogjava.net/sk8boy/articles/45161.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DUSE--让DOS支持USB驱动器(转载http://publishblog.blogchina.com/blog/tb.b?diaryID=3749687)</title><link>http://www.blogjava.net/sk8boy/articles/43102.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Tue, 25 Apr 2006 11:20:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/43102.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/43102.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/43102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/43102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/43102.html</trackback:ping><description><![CDATA[不知有多少人以为DOS不支持USB设备。因为USB设备标准是在Windows 95之后才制定的，而当时DOS的老东家微软早已决定放弃继续发展其MS-DOS了。这样一来，当您想在DOS下操作USB设备的时候，往往只能望洋兴叹 了。即使您使用的系统是Windows，当Windows崩溃要备份或恢复数据时，平时使用的USB硬盘等USB设备也都成了摆设。<br /> <br />幸好微软并不能决定一切，Pocketec公司开发的DUSE就为我们提供了在DOS下对USB存储设备（USB硬盘、软驱、光驱）的支持，不过它目前还 不支持较常见的USB ThumbDrive（即U盘）。若要在DOS下驱动USB的U盘，请使用Motto Hairu驱动程序。另外，如果想在纯DOS下使用其它USB设备，如USB鼠标、USB打印机等，则可以使用其它的USB驱动程序，如USB_Link 中的OHCI/UHCI，以及USB4DOS等，均可在本站的“驱动程序”中找到相应的链接，并可在“DOS使用中的常见问题解答(FAQ)”中看到一些 DOS下使用USB设备的信息。 <br /><br />DUSE是DOS下的USB存储设备的驱动程序，目前的最新版本为4.2，是今年刚推出的。它的用法很简单，可在CONFIG.SYS中加载，也可以用它 自带的DUSELDR.COM程序来实现在DOS命令行下（包括批处理文件中）的加载。例如在CONFIG.SYS中加上一行：DEVICE=C:\ DOS\DUSE.EXE或在DOS命令行下执行DUSELDR C:\DOS\DUSE.EXE均可。 <br /><br />如果要加载的是USB光驱，除加载DUSE驱动程序外，还需运行光驱扩展驱动程序，通常可以使用DOS自带的MSCDEX.EXE。DUSE的默认光驱设备名是USBCDROM，在DOS命令行下可以像下面这样运行MSCDEX.EXE： 
<p>MSCDEX /D:USBCDROM /K </p><p>如果要更好地使用和控制DUSE，可以使用它提供的参数，DUSE的运行参数如下表： <br />（说明：以下为它的4.2版的参数，其最新4.4版又增加了EMUIRQ、UBNU、DDWAIT等参数。[]中表示可以省略的，以VER[BOSE]为例，VERBOSE是参数的完整写法，而VER则是简写，即[]中的BOSE可以省略。） <br /><br />1: VER[BOSE][=x], 允许显示状态信息。x的合法值是0、1和2。0表示不显示信息，1表示显示文本消息，2表示采用弹出式窗口显示信息。默认值为0，如果输入了VERBOSE参数但未设定x的值的话，默认值为2。 <br />2: WAI[T]=x, 设置显示弹出式窗口到关闭此窗口的时间（以秒来计算）。x的合法值为0到255之间，默认值为3。只有当VERBOSE的值为2的时候此参数才有效。 <br />3: DRI[VES]=x, 设置允许的USB驱动器的数目。X取值从0到3。如果设置为0的话表示禁止USB驱动器的支持。默认值为1。 <br />4: NOD[RIVES], 禁止对USB驱动器的支持。此参数将覆盖DRIVES参数设置。 <br />5: NOC[DROM], 禁止对USB CD-ROM光驱的支持。 <br />6: MEM[POOL]=x, 设置分配附加的内存的大小。DUSE会根据USB控制器的数目、传输的速度等来进行计算，确定最佳分配内存的大小。而设置此参数将由用户决定内存分配的大小，x值的单位为KB，合法值在0到128之间。 <br />7: XFER[SIZE]=x, 设置允许的最大传输缓冲区，x值单位为KB来。增加传输缓冲区将增强传输性能，但也需要占用更多的内存。默认值为16。 <br />8: SEC[TORSIZE]=x, 设置USB驱动器的扇区大小。x的值用字节来表示。合法值为512，1024或2048，默认为512。 <br />9: APM[STATE]=x, 设置APM（高级电源管理）功能已启用的USB设备中APM的级别。增加此级别将增加设备的性能，但会增加电源的损耗。下面列出了合法的APM的状态x值： <br />* 最大性能 FEh <br />* 无挂起功能时中间的电源管理级别 81h-FDh <br />* 无挂起功能时最小电源损耗 80h <br />* 带挂起功能时中间的电源管理级别 02h-7Fh <br />* 带挂起功能时最小电源损耗 01h <br />x的默认值为0x7F。 <br />10: INT[13], 启用硬盘的INT13功能支持. 此功能对一些磁盘工具（如FDISK）提供支持。 <br />11: DMA[SAFE], 分配在数据传输中使用的DMA安全缓冲区。在运行一些需要从扩展内存中分配的缓冲的应用程序时此参数是必须指定的。 <br />12: NOU[HCI], 防止初始化UHCI USB控制器。 <br />13: NOO[HCI], 防止初始化OHCI USB控制器。 <br />14: NOE[HCI], 防止初始化EHCI USB控制器。 <br />15: UHCN=x, 指定DUSE初始化的UHCI控制器的最大数目为x。 <br />16: OHCN=x, 指定DUSE初始化的OHCI控制器的最大数目为x。 <br />17: EHCN=x, 指定DUSE初始化的EHCI控制器的最大数目为x。 <br />18: LATE[INIT], 启用“延时初始化”的功能. 当使用此功能时，驱动程序在DOS启动阶段从CONFIG.SYS文件中加载，但是直到在DOS命令中使用INIT参数运行DUSE时才会正式启用USB 设备，典型是在AUTOEXEC.BAT文件的结尾。可看下面的“延时初始化”和“将DUSE当作应用程序来运行”的部分。 <br />19: EBAR=x, 指定EHCI BAR（基地址寄存器）将被分配到内存中的地址。x的值必须是四位的16进制数字并带上前缀0x，例如要将EHCI BAR的地址置为0xE000，那么正确的命令行选项就是EBAR=0xE000。合法的地址区域在0xA000到0xF400之间。 <br />20: OBAR=x, 指定OHCI BAR将被分配到内存中的地址。上面对EBAR的描述可应用于OBAR。 <br />21: UBAR=x, 指定UHCI BAR将被分配到内存中的地址。上面对EBAR的描述可应用于UBAR，不过它的合法的地址区域在0x0400到0xF400之间。 <br />22: CDW[AIT][=x], 指示DUSE的初始化要等到第一个USB CD-ROM光驱的盘符被分配，或在x秒钟之内不要结束。x的合法值在0到30之间。x=0是一个特殊值，它表示DUSE将一直等到第一个USB CD-ROM光驱的盘符被分配或用户按下键盘上的ESC键。如果没有指定x的值的话，默认为x=0。 <br />23: CDD[EVICE]=&lt;设备名&gt;, 指定USB CD-ROM光驱的设备名。默认设备名是USBCDROM。 <br />24: VFLOP[PY], 初始化时建立一个启动软盘的虚拟映像。 <br /><br />以下是使用一个命令行参数的例子。可参考此行把DUSE加入到CONFIG.SYS文件中： <br /><br />DEVICE=C:\DUSE\DUSE.EXE VERBOSE DRIVES=2 XFER=8 SEC=2048 NOCD <br /><br />此例子设置： <br />* 显示弹出式状态窗口 <br />* 支持两个USB驱动器 <br />* 将最大传输缓冲区大小设为8K <br />* 将默认扇区大小设为2048字节 <br />* 禁止对USB CD-ROM光驱提供支持 <br /><br />* 关于“延时初始化”的功能 <br />当在CONFIG.SYS中以LATE[INIT]参数来运行DUSE（例如使用DEVICE=DUSE.EXE LATE）时，要真正使用USB设备还需进行一次真正的初始化。真正的初始化的方法是在DOS命令行下（包括批处理文件中）使用DUSE INIT命令。 <br /><br />* 关于“将DUSE当作应用程序来运行”的功能 <br />将DUSE当作应用程序来在DOS命令行下运行时，DUSE只支持INIT参数。此参数在上面的“延时初始化”以后于DOS命令行上加载，使得DUSE真正初始化USB设备，以真正使用USB设备。 </p><img src ="http://www.blogjava.net/sk8boy/aggbug/43102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2006-04-25 19:20 <a href="http://www.blogjava.net/sk8boy/articles/43102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>RedHat下服务的启动配置</title><link>http://www.blogjava.net/sk8boy/articles/37924.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Tue, 28 Mar 2006 15:01:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/37924.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/37924.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/37924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/37924.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/37924.html</trackback:ping><description><![CDATA[<p class="a0" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span>
				<font face="宋体">
						<span lang="EN-US">RedHat</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下，发现有三个命令可以用来配置系统服务的启动，分别是：</span>
				</font>
		</p>
		<p class="a0" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt">
				<span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">
						<span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">         </span></span>
				</span>
				<span lang="EN-US">
						<font face="宋体">ntsysv</font>
				</span>
		</p>
		<p class="a0" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt">
				<span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">
						<span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">         </span></span>
				</span>
				<span lang="EN-US">
						<font face="宋体">chkconfig</font>
				</span>
		</p>
		<p class="a0" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt">
				<span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">
						<span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">         </span></span>
				</span>
				<span lang="EN-US">
						<font face="宋体">serviceconf</font>
				</span>
		</p>
		<p class="a0" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中，</span>
				<font face="宋体">
						<span lang="EN-US">serviceconf</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是在</span>
						<span lang="EN-US">X</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面的图形化的配置，很方便，就不作过多的介绍。剩下的两个都是可以在终端启动的。其中，</span>
						<span lang="EN-US">ntsysv</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是终端下面的图形化配置程序，默认是用来配置当前运行级别的启动服务。但是可以通过在后面加入参数</span>
						<span lang="EN-US">--level xxx</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来指定修改所影响的运行级别。其中</span>
						<span lang="EN-US">“xxx”</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示运行级别的数字，从</span>
						<span lang="EN-US">0</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">到</span>
						<span lang="EN-US">9</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，不加任何空格。如：</span>
				</font>
		</p>
		<div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #bad4ff; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 17.85pt; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0cm; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div; mso-border-alt: solid windowtext .5pt">
				<p class="a" style="BACKGROUND: #bad4ff; MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US">
								<font face="Courier New" size="2">ntsysv --level 345</font>
						</span>
				</p>
		</div>
		<p class="a0" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-char-indent-count: 0">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示要对运行在</span>
				<font face="宋体">
						<span lang="EN-US">3</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">4</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
						<span lang="EN-US">5</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">级的相应服务的启动配置作修改。启动之后，就简单的选择希望在指定级别下自动启动的服务了。</span>
				</font>
		</p>
		<p class="a0" style="MARGIN: 0cm 0cm 0pt">
				<font face="宋体">
						<span lang="EN-US">chkconfig</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以用来列出、添加和删除系统服务的信息。这里需要特别指出的是，当我们向系统中添加一个服务时，如</span>
						<span lang="EN-US">Mysql Server</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如果不是</span>
						<span lang="EN-US">RPM</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">安装，需要手动进行启动。这时，我们可以将</span>
						<span lang="EN-US">MySQL</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的启动脚本，可能是</span>
						<span lang="EN-US">mysql.server</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拷贝到</span>
						<span lang="EN-US">/etc/init.d/</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目录下。根据喜好，也可以将其更名为</span>
						<span lang="EN-US">mysqld</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。这样比较符合系统的命名习惯。这时，为了使该服务可以在系统启动的时候自动运行，可以采用如下命令来添加：</span>
				</font>
		</p>
		<div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #bad4ff; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 17.85pt; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0cm; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div; mso-border-alt: solid windowtext .5pt">
				<p class="a" style="BACKGROUND: #bad4ff; MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US">
								<font face="Courier New" size="2">chkconfig –add mysqld on</font>
						</span>
				</p>
		</div>
		<p>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">默认情况下，参数</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">on</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">off</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">reset</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">只影响</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">2</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">3</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">4</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">5</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">级的系统启动信息。如果需要特殊定制，可以使用参数</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">--level</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">对其进行指定。方式跟</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">ntsysv</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">--level</span>
				<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-hansi-font-family: 'Times New Roman'">参数一致。</span>
		</p><img src ="http://www.blogjava.net/sk8boy/aggbug/37924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2006-03-28 23:01 <a href="http://www.blogjava.net/sk8boy/articles/37924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CVS的安装配置</title><link>http://www.blogjava.net/sk8boy/articles/15649.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Sun, 16 Oct 2005 08:34:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/15649.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/15649.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/15649.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/15649.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/15649.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1 准备在安装之前，首先通过运行下面命令查看系统上是否已经安装了CVS：root# rpm –q cvs这是我系统上输出的内容：cvs-1.11.19-8说明系统上已经安装了CVS，要卸载再安装新的版本或者重新安装。可以输入如下命令进行卸载：root# rpm –e cvs这时系统输出如下提示：warning: /etc/xinetd.d/cvs s...&nbsp;&nbsp;<a href='http://www.blogjava.net/sk8boy/articles/15649.html'>阅读全文</a><img src ="http://www.blogjava.net/sk8boy/aggbug/15649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2005-10-16 16:34 <a href="http://www.blogjava.net/sk8boy/articles/15649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一些有用的工具</title><link>http://www.blogjava.net/sk8boy/articles/15648.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Sun, 16 Oct 2005 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/15648.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/15648.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/15648.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/15648.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/15648.html</trackback:ping><description><![CDATA[<P>Iperf&nbsp; <A href="http://dast.nlanr.net/Projects/Iperf/">http://dast.nlanr.net/Projects/Iperf/</A></P>
<P>&nbsp;Iperf was developed as a modern alternative for measuring TCP and UDP bandwidth performance. </P>
<P>
<P>Hping <A href="http://www.hping.org/">http://www.hping.org/</A></P>
<P>Hping is a command-line oriented TCP/IP packet assembler/analyzer. <BR></P>
<P>Curl <A href="http://curl.haxx.se/">http://curl.haxx.se/</A></P>
<P>curl is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE and LDAP. Curl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos...), file transfer resume, proxy tunneling and a busload of other <A href="http://curl.haxx.se/docs/features.html">useful tricks</A>. </P>
<P>adore-ng <A href="http://stealth.openwall.net/">http://stealth.openwall.net/</A>&nbsp; rootkits</P>
<P>AIRT <A href="http://159.226.5.93/projects/airt.htm">http://159.226.5.93/projects/airt.htm</A></P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A href="http://159.226.5.93/projects.htm">http://159.226.5.93/projects.htm</A></P>
<P>AIRT(Advanced incident response tool) is a set of incident response assistant tools on linux platform.</P>
<P>openhids <A href="http://www.openhids.com/download.html">http://www.openhids.com/download.html</A></P>
<P>stunnel&nbsp;&nbsp; <A href="http://www.stunnel.org/">http://www.stunnel.org/</A></P>
<P>&nbsp;engage&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A href="http://www.engagesecurity.com/">http://www.engagesecurity.com/</A></P>
<P>&nbsp;Analog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A href="http://www.analog.cx/">http://www.analog.cx/</A></P>
<P>logfile analyser</P>
<P><STRONG><EM></EM></STRONG></P>
<P>sysinternals &nbsp;<A href="http://www.sysinternals.com/">http://www.sysinternals.com/</A>&nbsp;Tools for windows</P>
<P>FreeMind&nbsp; <A href="http://freemind.sourceforge.net/wiki/index.php/Main_Page">http://freemind.sourceforge.net/wiki/index.php/Main_Page</A></P>
<P>free mind mapping software </P><img src ="http://www.blogjava.net/sk8boy/aggbug/15648.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2005-10-16 16:30 <a href="http://www.blogjava.net/sk8boy/articles/15648.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从程序员角度看ELF（转载）</title><link>http://www.blogjava.net/sk8boy/articles/15646.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Sun, 16 Oct 2005 08:27:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/15646.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/15646.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/15646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/15646.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/15646.html</trackback:ping><description><![CDATA[（转载自<A href="http://www.xfocus.net/articles/200109/260.html">http://www.xfocus.net/articles/200109/260.html</A>）<BR><BR>原文:《 ELF:From The Programmer's Perspective》<BR><BR>作者：Hongjiu Lu &lt;mailto: hjl@nynexst.com&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;NYNEX Science &amp; Technology, Inc. <BR>&nbsp;&nbsp;&nbsp;&nbsp;500 Westchester Avenue <BR>&nbsp;&nbsp;&nbsp;&nbsp;White Plains, NY 10604, USA <BR><BR>翻译：alert7 &lt;mailto: <A href="mailto:alert7@21cn.com">alert7@21cn.com</A>&nbsp;<A href="mailto:alert7@xfocus.org">alert7@xfocus.org</A>&gt;<BR><BR>主页: <A href="http://www.xfocus.org/" target=_blank>http://www.xfocus.org</A><BR>时间: 2001-9-10<BR><BR><BR>★概要：<BR><BR>这片文档从程序员的角度讨论了linux的ELF二进制格式。介绍了一些ELF执行<BR>文件在运行控制的技术。展示了如何使用动态连接器和如何动态装载ELF。<BR>我们也演示了如何在LINUX使用GNU C/C++编译器和一些其他工具来创建共享的<BR>C/C++库。<BR><BR>★1前言<BR><BR>最初，UNIX系统实验室(USL)开发和发布了Executable and linking Format<BR>(ELF)这样的二进制格式。在SVR4和Solaris 2.x上，都做为可执行文件默认的<BR>二进制格式。ELF比a.out和COFF更强大更灵活。结合一些适当的工具，程序员<BR>使用ELF就可以在运行时控制程序的流程。<BR><BR><BR>★2 ELF类型<BR><BR>三种主要的ELF文件类型：<BR><BR>.可执行文件：包含了代码和数据。具有可执行的程序。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;例如这样一个程序<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;# file dltest<BR>&nbsp;&nbsp;&nbsp;&nbsp;dltest: ELF 32-bit LSB executable, Intel 80386, version 1, <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dynamically linked (uses shared libs), not stripped<BR><BR>.可重定位文件：包含了代码和数据（这些数据是和其他重定位文件和共享的<BR>&nbsp;&nbsp;&nbsp;&nbsp;object文件一起连接时使用的）<BR>&nbsp;&nbsp;&nbsp;&nbsp;例如这样文件<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;# file libfoo.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;libfoo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1, <BR>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;not stripped<BR><BR>.共享object文件（又可叫做共享库）：包含了代码和数据（这些数据是在连接<BR>&nbsp;&nbsp;&nbsp;&nbsp;时候被连接器ld和运行时动态连接器使用的）。动态连接器可能称为<BR>&nbsp;&nbsp;&nbsp;&nbsp;ld.so.1,libc.so.1 或者 ld-linux.so.1。<BR>&nbsp;&nbsp;&nbsp;&nbsp;例如这样文件<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;# file libfoo.so<BR>&nbsp;&nbsp;&nbsp;&nbsp;libfoo.so: ELF 32-bit LSB shared object, Intel 80386, version<BR>&nbsp;&nbsp;&nbsp;&nbsp;1, not stripped<BR><BR>ELF section部分是非常有用的。使用一些正确的工具和技术，程序员就能<BR>熟练的操作可执行文件的执行。<BR><BR>★3 .init和.fini sections<BR><BR>在ELF系统上，一个程序是由可执行文件或者还加上一些共享object文件组成。<BR>为了执行这样的程序，系统使用那些文件创建进程的内存映象。进程映象<BR>有一些段(segment),包含了可执行指令，数据，等等。为了使一个ELF文件<BR>装载到内存，必须有一个program header(该program header是一个描述段<BR>信息的结构数组和一些为程序运行准备的信息)。<BR><BR>一个段可能有多个section组成.这些section在程序员角度来看更显的重要。<BR><BR>每个可执行文件或者是共享object文件一般包含一个section table,该表<BR>是描述ELF文件里sections的结构数组。这里有几个在ELF文档中定义的比较<BR>特别的sections.以下这些是对程序特别有用的：<BR><BR>.fini<BR>&nbsp;&nbsp;&nbsp;&nbsp;该section保存着进程终止代码指令。因此，当一个程序正常退出时，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;系统安排执行这个section的中的代码。<BR>.init&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;该section保存着可执行指令，它构成了进程的初始化代码。<BR>&nbsp;&nbsp;&nbsp;&nbsp;因此，当一个程序开始运行时，在main函数被调用之前(c语言称为<BR>&nbsp;&nbsp;&nbsp;&nbsp;main)，系统安排执行这个section的中的代码。<BR><BR>.init和.fini sections的存在有着特别的目的。假如一个函数放到<BR>.init section，在main函数执行前系统就会执行它。同理，假如一<BR>个函数放到.fini section，在main函数返回后该函数就会执行。<BR>该特性被C++编译器使用，完成全局的构造和析构函数功能。<BR><BR>当ELF可执行文件被执行，系统将在把控制权交给可执行文件前装载所以相关<BR>的共享object文件。构造正确的.init和.fini sections,构造函数和析构函数<BR>将以正确的次序被调用。<BR><BR>★3.1 在c++中全局的构造函数和析构函数<BR><BR>在c++中全局的构造函数和析构函数必须非常小心的处理碰到的语言规范问题。<BR>构造函数必须在main函数之前被调用。析构函数必须在main函数返回之后<BR>被调用。例如，除了一般的两个辅助启动文件crti.o和crtn.o外，GNU C/C++<BR>编译器--gcc还提供两个辅助启动文件一个称为crtbegin.o，还有一个被称为<BR>crtend.o。结合.ctors和.dtors两个section，c++全局的构造函数和析构函数<BR>能以运行时最小的负载，正确的顺序执行。<BR><BR><BR>.ctors<BR>&nbsp;&nbsp;&nbsp;&nbsp;该section保存着程序的全局的构造函数的指针数组。<BR><BR>.dtors<BR>&nbsp;&nbsp;&nbsp;&nbsp;该section保存着程序的全局的析构函数的指针数组。&nbsp;&nbsp;&nbsp;&nbsp;<BR><BR>ctrbegin.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;有四个section:<BR>&nbsp;&nbsp;&nbsp;&nbsp;1 .ctors section<BR>&nbsp;&nbsp;&nbsp;&nbsp;local标号__CTOR_LIST__指向全局构造函数的指针数组头。在<BR>&nbsp;&nbsp;&nbsp;&nbsp;ctrbegin.o中的该数组只有一个dummy元素。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;[译注：<BR>&nbsp;&nbsp;&nbsp;&nbsp;# objdump -s -j .ctors &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtbegin.o<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtbegin.o:<BR>&nbsp;&nbsp;&nbsp;&nbsp;file format elf32-i386<BR>&nbsp;&nbsp;&nbsp;&nbsp;Contents of section .ctors:<BR>&nbsp;&nbsp;&nbsp;&nbsp;0000 ffffffff&nbsp;&nbsp;&nbsp;&nbsp;&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;这里说的dummy元素应该就是指的是ffffffff<BR>&nbsp;&nbsp;&nbsp;&nbsp;]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;2 .dtors section<BR>&nbsp;&nbsp;&nbsp;&nbsp;local标号__DTOR_LIST__指向全局析构函数的指针数组头。在<BR>&nbsp;&nbsp;&nbsp;&nbsp;ctrbegin.o中的该数组仅有也只有一个dummy元素。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;3 .text section<BR>&nbsp;&nbsp;&nbsp;&nbsp;只包含了__do_global_dtors_aux函数,该函数遍历__DTOR_LIST__<BR>&nbsp;&nbsp;&nbsp;&nbsp;列表，调用列表中的每个析构函数。<BR>函数如下：<BR><BR>Disassembly of section .text:<BR><BR>00000000 &lt;__do_global_dtors_aux&gt;:<BR>&nbsp;&nbsp; 0:&nbsp;&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; %ebp<BR>&nbsp;&nbsp; 1:&nbsp;&nbsp; 89 e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<BR>&nbsp;&nbsp; 3:&nbsp;&nbsp; 83 3d 04 00 00 00 00&nbsp;&nbsp;&nbsp;&nbsp;cmpl&nbsp;&nbsp; $0x0,0x4<BR>&nbsp;&nbsp; a:&nbsp;&nbsp; 75 38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jne&nbsp;&nbsp;&nbsp;&nbsp;44 &lt;__do_global_dtors_aux+0x44&gt;<BR>&nbsp;&nbsp; c:&nbsp;&nbsp; eb 0f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;1d &lt;__do_global_dtors_aux+0x1d&gt;<BR>&nbsp;&nbsp; e:&nbsp;&nbsp; 89 f6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esi,%esi<BR>&nbsp;&nbsp;10:&nbsp;&nbsp; 8d 50 04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lea&nbsp;&nbsp;&nbsp;&nbsp;0x4(%eax),%edx<BR>&nbsp;&nbsp;13:&nbsp;&nbsp; 89 15 00 00 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%edx,0x0<BR>&nbsp;&nbsp;19:&nbsp;&nbsp; 8b 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;(%eax),%eax<BR>&nbsp;&nbsp;1b:&nbsp;&nbsp; ff d0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp; *%eax<BR>&nbsp;&nbsp;1d:&nbsp;&nbsp; a1 00 00 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0x0,%eax<BR>&nbsp;&nbsp;22:&nbsp;&nbsp; 83 38 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmpl&nbsp;&nbsp; $0x0,(%eax)<BR>&nbsp;&nbsp;25:&nbsp;&nbsp; 75 e9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jne&nbsp;&nbsp;&nbsp;&nbsp;10 &lt;__do_global_dtors_aux+0x10&gt;<BR>&nbsp;&nbsp;27:&nbsp;&nbsp; b8 00 00 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;$0x0,%eax<BR>&nbsp;&nbsp;2c:&nbsp;&nbsp; 85 c0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp; %eax,%eax<BR>&nbsp;&nbsp;2e:&nbsp;&nbsp; 74 0a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; je&nbsp;&nbsp;&nbsp;&nbsp; 3a &lt;__do_global_dtors_aux+0x3a&gt;<BR>&nbsp;&nbsp;30:&nbsp;&nbsp; 68 00 00 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; $0x0<BR>&nbsp;&nbsp;35:&nbsp;&nbsp; e8 fc ff ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp; 36 &lt;__do_global_dtors_aux+0x36&gt;<BR>&nbsp;&nbsp;3a:&nbsp;&nbsp; c7 05 04 00 00 00 01&nbsp;&nbsp;&nbsp;&nbsp;movl&nbsp;&nbsp; $0x1,0x4<BR>&nbsp;&nbsp;41:&nbsp;&nbsp; 00 00 00<BR>&nbsp;&nbsp;44:&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<BR>&nbsp;&nbsp;45:&nbsp;&nbsp; c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>&nbsp;&nbsp;46:&nbsp;&nbsp; 89 f6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esi,%esi<BR><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;4 .fini section<BR>&nbsp;&nbsp;&nbsp;&nbsp;它只包含一个__do_global_dtors_aux的函数调用。请记住，它仅是<BR>&nbsp;&nbsp;&nbsp;&nbsp;一个函数调用而不返回的，因为crtbegin.o的.fini section是这个<BR>&nbsp;&nbsp;&nbsp;&nbsp;函数体的一部分。<BR>函数如下：<BR>Disassembly of section .fini:<BR><BR>00000000 &lt;.fini&gt;:<BR>&nbsp;&nbsp; 0:&nbsp;&nbsp; e8 fc ff ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp; 1 &lt;.fini+0x1&gt;<BR><BR><BR>crtend.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;也有四个section:<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;1 .ctors section<BR>&nbsp;&nbsp;&nbsp;&nbsp;local标号__CTOR_END__指向全局构造函数的指针数组尾部。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;2 .dtors section<BR>&nbsp;&nbsp;&nbsp;&nbsp;local标号__DTOR_END__指向全局析构函数的指针数组尾部。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;3 .text section<BR>&nbsp;&nbsp;&nbsp;&nbsp;只包含了__do_global_ctors_aux函数,该函数遍历__CTOR_LIST__<BR>&nbsp;&nbsp;&nbsp;&nbsp;列表，调用列表中的每个构造函数。<BR>函数如下：<BR>00000000 &lt;__do_global_ctors_aux&gt;:<BR>&nbsp;&nbsp; 0:&nbsp;&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; %ebp<BR>&nbsp;&nbsp; 1:&nbsp;&nbsp; 89 e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<BR>&nbsp;&nbsp; 3:&nbsp;&nbsp; 53&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; %ebx<BR>&nbsp;&nbsp; 4:&nbsp;&nbsp; bb fc ff ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;$0xfffffffc,%ebx<BR>&nbsp;&nbsp; 9:&nbsp;&nbsp; 83 3d fc ff ff ff ff&nbsp;&nbsp;&nbsp;&nbsp;cmpl&nbsp;&nbsp; $0xffffffff,0xfffffffc<BR>&nbsp;&nbsp;10:&nbsp;&nbsp; 74 0c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; je&nbsp;&nbsp;&nbsp;&nbsp; 1e &lt;__do_global_ctors_aux+0x1e&gt;<BR>&nbsp;&nbsp;12:&nbsp;&nbsp; 8b 03&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;(%ebx),%eax<BR>&nbsp;&nbsp;14:&nbsp;&nbsp; ff d0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp; *%eax<BR>&nbsp;&nbsp;16:&nbsp;&nbsp; 83 c3 fc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;$0xfffffffc,%ebx<BR>&nbsp;&nbsp;19:&nbsp;&nbsp; 83 3b ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmpl&nbsp;&nbsp; $0xffffffff,(%ebx)<BR>&nbsp;&nbsp;1c:&nbsp;&nbsp; 75 f4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jne&nbsp;&nbsp;&nbsp;&nbsp;12 &lt;__do_global_ctors_aux+0x12&gt;<BR>&nbsp;&nbsp;1e:&nbsp;&nbsp; 8b 5d fc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0xfffffffc(%ebp),%ebx<BR>&nbsp;&nbsp;21:&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<BR>&nbsp;&nbsp;22:&nbsp;&nbsp; c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>&nbsp;&nbsp;23:&nbsp;&nbsp; 90&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nop<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;4 .init section<BR>&nbsp;&nbsp;&nbsp;&nbsp;它只包含一个__do_global_ctors_aux的函数调用。请记住，它仅是<BR>&nbsp;&nbsp;&nbsp;&nbsp;一个函数调用而不返回的，因为crtend.o的.init section是这个函<BR>&nbsp;&nbsp;&nbsp;&nbsp;数体的一部分。<BR>函数如下：<BR>Disassembly of section .init:<BR><BR>00000000 &lt;.init&gt;:<BR>&nbsp;&nbsp; 0:&nbsp;&nbsp; e8 fc ff ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp; 1 &lt;.init+0x1&gt;<BR><BR><BR>crti.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;在.init section中仅是个_init的函数标号。<BR>&nbsp;&nbsp;&nbsp;&nbsp;在.fini section中的_fini函数标号。<BR><BR>crtn.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;在.init和.fini section中仅是返回指令。<BR><BR>Disassembly of section .init:<BR><BR>00000000 &lt;.init&gt;:<BR>&nbsp;&nbsp; 0:&nbsp;&nbsp; 8b 5d fc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0xfffffffc(%ebp),%ebx<BR>&nbsp;&nbsp; 3:&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<BR>&nbsp;&nbsp; 4:&nbsp;&nbsp; c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>Disassembly of section .fini:<BR><BR>00000000 &lt;.fini&gt;:<BR>&nbsp;&nbsp; 0:&nbsp;&nbsp; 8b 5d fc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;0xfffffffc(%ebp),%ebx<BR>&nbsp;&nbsp; 3:&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<BR>&nbsp;&nbsp; 4:&nbsp;&nbsp; c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<BR><BR>编译产生可重定位文件时，gcc把每个全局构造函数挂在__CTOR_LIST上<BR>（通过把指向构造函数的指针放到.ctors section中）。<BR>它也把每个全局析构函挂在__DTOR_LIST上（通过把指向析构函的指针<BR>放到.dtors section中）。<BR><BR>连接时，gcc在所有重定位文件前处理crtbegin.o,在所有重定位文件后处理<BR>crtend.o。另外，crti.o在crtbegin.o之前被处理，crtn.o在crtend.o之后<BR>被处理。<BR><BR>当产生可执行文件时，连接器ld分别的连接所有可重定位文件的ctors 和<BR>.dtors section到__CTOR_LIST__和__DTOR_LIST__列表中。.init section<BR>由所有的可重定位文件中_init函数组成。.fini由_fini函数组成。<BR><BR>运行时，系统将在main函数之前执行_init函数，在main函数返回后执行<BR>_fini函数。<BR><BR><BR>★4 ELF的动态连接与装载<BR><BR>★4.1 动态连接<BR><BR>当在UNIX系统下，用C编译器把C源代码编译成可执行文件时，c编译驱动器一般<BR>将调用C的预处理，编译器，汇编器和连接器。<BR><BR>. &nbsp;&nbsp;&nbsp;&nbsp;c编译驱动器首先把C源代码传到C的预处理器，它以处理过的宏和<BR>&nbsp;&nbsp;&nbsp;&nbsp;指示器形式输出纯C语言代码。<BR><BR>.&nbsp;&nbsp;&nbsp;&nbsp;c编译器把处理过的C语言代码翻译为机器相关的汇编代码。<BR><BR>.&nbsp;&nbsp;&nbsp;&nbsp;汇编器把结果的汇编语言代码翻译成目标的机器指令。结果这些<BR>&nbsp;&nbsp;&nbsp;&nbsp;机器指令就被存储成指定的二进制文件格式，在这里，我们使用的<BR>&nbsp;&nbsp;&nbsp;&nbsp;ELF格式。<BR><BR>.&nbsp;&nbsp;&nbsp;&nbsp;最后的阶段，连接器连接所有的object文件，加入所有的启动代码和<BR>&nbsp;&nbsp;&nbsp;&nbsp;在程序中引用的库函数。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;下面有两种方法使用lib库<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;--static library<BR>&nbsp;&nbsp;&nbsp;&nbsp;一个集合，包含了那些object文件中包含的library例程和数据。用<BR>&nbsp;&nbsp;&nbsp;&nbsp;该方法，连接时连接器将产生一个独立的object文件(这些<BR>&nbsp;&nbsp;&nbsp;&nbsp;object文件保存着程序所要引用的函数和数据)的copy。<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;--shared library<BR>&nbsp;&nbsp;&nbsp;&nbsp;是共享文件，它包含了函数和数据。用这样连接出来的程序仅在可执行<BR>&nbsp;&nbsp;&nbsp;&nbsp;程序中存储着共享库的名字和一些程序引用到的标号。在运行时，动态<BR>&nbsp;&nbsp;&nbsp;&nbsp;连接器（在ELF中也叫做程序解释器）将把共享库映象到进程的虚拟<BR>&nbsp;&nbsp;&nbsp;&nbsp;地址空间里去，通过名字解析在共享库中的标号。该处理过程也称为<BR>&nbsp;&nbsp;&nbsp;&nbsp;动态连接(dynamic linking)<BR><BR>程序员不需要知道动态连接时用到的共享库做什么，每件事情对程序员都是<BR>透明的。<BR><BR><BR>★4.2 动态装载(Dynamic Loading)<BR><BR>动态装载是这样一个过程：把共享库放到执行时进程的地址空间，在库中查找<BR>函数的地址，然后调用那个函数，当不再需要的时候，卸载共享库。它的执行<BR>过程作为动态连接的服务接口。<BR><BR>在ELF下，程序接口通常在&lt;dlfcn.h&gt;中被定义。如下：<BR><BR>void *dlopen(const char * filename,int flag);<BR>const char * dlerror(void);<BR>const void * dlsym (void handle*,const char * symbol);<BR>int dlclose(void * handle);<BR><BR>这些函数包含在libdl.so中。下面是个例子，展示动态装载是如何工作的。<BR>主程序在运行时动态的装载共享库。一方面可指出哪个共享库被使用，哪个<BR>函数被调用。一方面也能在访问共享库中的数据。 <BR><BR>[alert7@redhat62 dl]# cat dltest.c<BR>#include &lt;stdio.h&gt;<BR>#include &lt;stdlib.h&gt;<BR>#include &lt;getopt.h&gt;<BR>#include &lt;dlfcn.h&gt;<BR>#include &lt;ctype.h&gt;<BR><BR>typedef void (*func_t) (const char *);<BR><BR>void dltest(const char *s)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("From dltest:");<BR>&nbsp;&nbsp;&nbsp;&nbsp;for (;*s;s++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;putchar(toupper(*s));<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;putchar('\n');<BR>}<BR><BR>main(int argc,char **argv)<BR>{<BR>void *handle;<BR>func_t fptr;<BR>char * libname = "./libfoo.so";<BR>char **name=NULL;<BR>char *funcname = "foo";<BR>char *param= "Dynamic Loading Test";<BR>int ch;<BR>int mode=RTLD_LAZY;&nbsp;&nbsp;&nbsp;&nbsp;<BR><BR>while ((ch = getopt(argc,argv,"a:b:f:l:"))!=EOF)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;switch(ch)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;case 'a':/*argument*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;param=optarg;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;case 'b':/*how to bind*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch(*optarg)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 'l':/*lazy*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode = RTLD_LAZY;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 'n':/*now*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode = RTLD_NOW;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;case 'l':/*which shared library*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libname= optarg;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;case 'f':/*which function*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcname= optarg;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp; }<BR><BR>handle = dlopen(libname,mode);<BR>if (handle ==NULL)<BR>{<BR>fprintf(stderr,"%s:dlopen:'%s'\n",libname,dlerror());<BR>exit(1);<BR>}<BR><BR>fptr=(func_t)dlsym(handle,funcname);<BR>if (fptr==NULL)<BR>{<BR>fprintf(stderr,"%s:dlsym:'%s'\n",funcname,dlerror());<BR>exit(1);<BR>}<BR><BR><BR>name = (char **) dlsym(handle,"libname");<BR>if (name==NULL)<BR>{<BR>fprintf(stderr,"%s:dlsym:'libname'\n",dlerror());<BR>exit(1);<BR>}<BR><BR>printf("Call '%s' in '%s':\n",funcname,*name);<BR><BR>/*call that function with 'param'*/<BR>(*fptr)(param);<BR><BR>dlclose(handle);<BR>return 0;<BR><BR>}<BR><BR>这里有两个共享库，一个是libfoo.so一个是libbar.so。每个都用同样的全局<BR>字符串变量libname,分别各自有foo和bar函数。通过dlsym，对程序来说,他们<BR>都是可用的。<BR><BR>[alert7@redhat62 dl]# cat libbar.c<BR>#include &lt;stdio.h&gt;<BR><BR>extern void dltest(const char *);<BR>const char * const libname = "libbar.so";<BR><BR>void bar (const char *s)<BR>{<BR>dltest("Called from libbar.");<BR>printf("libbar:%s\n",s);<BR>}<BR><BR><BR>[alert7@redhat62 dl]# cat libfoo.c<BR>#include &lt;stdio.h&gt;<BR><BR>extern void dltest (const char *s);<BR>const char *const libname="libfoo.so";<BR><BR>void foo(const char *s)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;const char *saved=s;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;dltest("Called from libfoo");<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("libfoo:");<BR>&nbsp;&nbsp;&nbsp;&nbsp;for (;*s;s++);<BR>&nbsp;&nbsp;&nbsp;&nbsp;for (s--;s&gt;=saved;s--)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;putchar (*s);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;putchar ('\n');<BR>}<BR><BR>使用Makefile文件来编译共享库和主程序是很有用的。因为libbar.so和<BR>libfoo.so也调用了主程序里的dltest函数。<BR><BR>[alert7@redhat62 dl] #cat Makefile<BR>CC=gcc<BR>LDFLAGS=-rdynamic<BR>SHLDFLAGS=<BR>RM=rm<BR><BR>all:dltest<BR><BR>libfoo.o:libfoo.c<BR>&nbsp;&nbsp;&nbsp;&nbsp;$(CC) -c -fPIC $&lt;<BR><BR>libfoo.so:libfoo.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;$(CC) $(SHLDFLAGS) -shared -o $@ $^<BR><BR>libbar: libbar.c<BR>&nbsp;&nbsp;&nbsp;&nbsp;$(CC) -c -fPIC $&lt;<BR><BR>libbar.so:libbar.o<BR>&nbsp;&nbsp;&nbsp;&nbsp;$(CC) $(SHLDFLAGS) -shared -o $@ $^<BR><BR>dltest: dltest.o libbar.so libfoo.so<BR>&nbsp;&nbsp;&nbsp;&nbsp;$(CC) $(LDFLAGS) -o $@ dltest.o -ldl<BR><BR>clean:<BR>&nbsp;&nbsp;&nbsp;&nbsp;$(RM) *.o *.so dltest<BR><BR>处理流程：<BR><BR>[alert7@redhat62 dl]# export ELF_LD_LIBRARY_PATH=.<BR>[alert7@redhat62 dl]# ./dltest<BR>Call 'foo' in 'libfoo.so':<BR>From dltest:CALLED FROM LIBFOO<BR>libfoo:tseT gnidaoL cimanyD<BR>[alert7@redhat62 dl]# ./dltest -f bar<BR>bar:dlsym:'./libfoo.so: undefined symbol: bar'<BR>[alert7@redhat62 dl]# ./dltest -f bar -l ./libbar.so<BR>Call 'bar' in 'libbar.so':<BR>From dltest:CALLED FROM LIBBAR.<BR>libbar:Dynamic Loading Test<BR><BR><BR>在动态装载进程中调用的第一个函数就是dlopen,它使得共享可库对<BR>运行着的进程可用。dlopen返回一个handle,该handle被后面的dlsym<BR>和dlclose函数使用。dlopen的参数为NULL有特殊的意思---它使得在<BR>程序导出的标号和当前已经装载进内存的共享库导出的标号通过dlsym<BR>就可利用。<BR><BR>在一个共享库已经装载进运行着的进程的地址空间后，dlsym可用来<BR>获得在共享库中导出的标号地址。然后就可以通过dlsym返回的地址<BR>来访问里面的函数和数据。<BR><BR>当一个共享库不再需要使用的时候，就可以调用dlclose卸载该函数库。<BR>假如共享库在启动时刻或者是通过其他的dlopen调用被装载的话，该<BR>共享库不会从调用的进程的地址空间被移走。<BR><BR>假如dlclose操作成功，返回为0。dlopen和dlsym如果有错误，将返回<BR>为NULL。为了获取诊断信息，可调用dlerror.<BR><BR><BR>★5 支持ELF的LINUX上的编译器GNU GCC<BR><BR>感谢Eric Youngdale (eric@aib.com),lan Lance Taylor (ian@cygnus.com)<BR>还有许多为gcc支持ELF功能的默默做贡献的人。我们能用gcc和GNU的二进制<BR>工具很容易的创建ELF可执行文件和共享库。<BR><BR>★5.1 共享C库 Shared C Library<BR><BR>在ELF下构造一个共享库比其他的容易的多。但是需要编译器，汇编器，<BR>连接器的支持。首先，需要产生位置无关(position-independent)代码。<BR>要做到这一点，gcc需要加上编译选项-fPIC<BR>[alert7@redhat62 dl]# gcc -fPIC -O -c libbar.c<BR><BR>这时候就适合构造共享库了，加上-shared编译选项<BR>[alert7@redhat62 dl]# gcc -shared -o libbar.so libbar.o<BR><BR>现在我们构造的libbar.so就可以被连接器(link editor)和动态连接器<BR>(dynamic linker)。只要编译时带上-fPIC编译选项,可以把许多重定位<BR>文件加到共享库中。为了把baz.o和共享库连接在一起，可以如下操作：<BR># gcc -O -c baz.c<BR># gcc -o baz baz.o -L. -lbar<BR><BR>在把libbar.so安装到动态连接器能找到的正确位置上之后，运行baz将<BR>使libbar.so映象到baz的进程地址空间。内存中libbar.so的一份拷贝将<BR>被所有的可执行文件(这些可执行程序连接时和它一块儿连接的或者<BR>在运行时动态装载的)共享。<BR><BR>★5.2 共享C++库 Shared C++ Library<BR><BR>在共享c++库中主要的困难是如何对待构造函数和析构函数。<BR>在SunOS下，构造和使用一个共享的ELF C库是容易的，但是在SunOS下不能<BR>构造共享的C++库，因为构造函数和析构函数有特别的需求。为止，在ELF<BR>中的.init和.init section提供了完美的解决方法。<BR><BR>当构造共享C++库时，我们使用crtbegin.o和crtend.o这两个特殊的版本，<BR>(它们已经是经过-fPIC的)。对于连接器(link editor)来说，构造共享<BR>的C++库几乎是和一般的可执行文件一样的。全局的构造函数和析构函数<BR>被.init和.fini section处理(在上面3.1节中已经讨论过)。<BR><BR>但一个共享库被映射到进程的地址空间时，动态连接器将在传控制权给程序<BR>之前执行_init函数，并且将为_fini函数安排在共享库不再需要的时候被<BR>执行。<BR><BR>连接选项-shared是告诉gcc以正确的顺序放置必要的辅助文件并且告诉它将<BR>产生一个共享库。-v选项将显示什么文件什么选项被传到了连接器<BR>(link editor).<BR><BR>[alert7@redhat62 dl]# gcc -v -shared -o libbar.so libbar.o<BR>Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs<BR>gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)<BR>/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/collect2 -m elf_i386 <BR>-shared -o libbar.so /usr/lib/crti.o /usr/lib/gcc-lib/i386-redhat<BR>&nbsp;&nbsp;&nbsp;&nbsp;-linux/egcs-2.91.66/crtbeginS.o <BR>-L/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66 <BR>-L/usr/i386-redhat-linux/lib libbar.o -lgcc -lc --version-script <BR>/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/libgcc.map <BR>-lgcc /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtendS.o <BR>/usr/lib/crtn.o<BR><BR>crtbeginS.o和crtendS.o用-fPIC编译的两个特殊的版本。带上-shared<BR>创建共享库是重要的，因为那些辅助的文件也提供其他服务。我们将在<BR>5.3节中讨论。<BR><BR>★5.3 扩展的GCC特性<BR><BR>GCC有许多扩展的特性。有些对ELF特别的有用。其中一个就是__attribute__。<BR>使用__attribute__可以使一个函数放到__CTOR_LIST__或者__DTOR_LIST__里。<BR>例如：<BR><BR>[alert7@redhat62 dl]# cat miss.c<BR><BR>#include &lt;stdio.h&gt;<BR>#include &lt;stdlib.h&gt;<BR><BR>static void foo(void) __attribute__ ((constructor));<BR>static void bar(void) __attribute__ ((destructor));<BR><BR><BR>int main(int argc, char *argv[])<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("foo == %p\n", foo);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("bar == %p\n", bar);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<BR>}<BR><BR>void foo(void)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("hi dear njlily!\n");<BR>}<BR><BR>void bar(void)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("missing u! goodbye!\n");<BR>}<BR><BR>[alert7@redhat62 dl]# gcc -o miss miss.c<BR>[alert7@redhat62 dl]# ./miss<BR>hi dear njlily!<BR>foo == 0x8048434<BR>bar == 0x8048448<BR>missing u! goodbye!<BR><BR>我们来看看是否加到了.ctors和.dtors中。<BR>[alert7@redhat62 dl]# objdump -s -j .ctors miss<BR><BR>miss:&nbsp;&nbsp;&nbsp;&nbsp; file format elf32-i386<BR><BR>Contents of section .ctors:<BR>8049504 ffffffff 34840408 00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....4.......<BR><BR>[alert7@redhat62 dl]# objdump -s -j .dtors miss<BR><BR>miss:&nbsp;&nbsp;&nbsp;&nbsp; file format elf32-i386<BR><BR>Contents of section .dtors:<BR>8049510 ffffffff 48840408 00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....H.......<BR><BR>已经把foo和bar地址分别放到了.ctors和.dors，显示34840408只是因为<BR>x86上是LSB编码的，小端序。<BR><BR>__attribute__ ((constructor))促使函数foo在进入main之前会被自动调用。<BR>__attribute__ ((destructor))促使函数bar在main返回或者exit调用之后<BR>会被自动调用。foo和bar必须是不能带参数的而且必须是static void类型的<BR>函数。在ELF下，这个特性在一般的可执行文件和共享库中都能很好的工作。<BR><BR><BR>我们也可以创建自己的section,在这里我创建了一个alert7 section.<BR>[alert7@redhat62 dl]# cat test.c<BR>#include &lt;stdio.h&gt;<BR>#include &lt;stdlib.h&gt;<BR><BR>static void foo(void) __attribute__ ((section ("alert7")));<BR>static void bar(void) __attribute__ ((section ("alert7")));<BR><BR><BR>int main(int argc, char *argv[])<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("foo == %p\n", foo);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("bar == %p\n", bar);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<BR>}<BR><BR>void foo(void)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("hi dear njlily!\n");<BR>}<BR>void bar(void)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("missing u! goodbye!\n");<BR>}<BR>[alert7@redhat62 dl]# gcc -o test test.c<BR>[alert7@redhat62 dl]# ./test<BR>hi dear njlily!<BR>foo == 0x804847c<BR>bar == 0x8048490<BR>missing u! goodbye!<BR><BR>[alert7@redhat62 dl]# objdump -x test<BR>....<BR>Sections:<BR>Idx Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File off&nbsp;&nbsp;Algn<BR>&nbsp;&nbsp;0 .interp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00000013&nbsp;&nbsp;080480f4&nbsp;&nbsp;080480f4&nbsp;&nbsp;000000f4&nbsp;&nbsp;2**0<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS, ALLOC, LOAD, READONLY, DATA<BR>...<BR>12 alert7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00000026&nbsp;&nbsp;0804847c&nbsp;&nbsp;0804847c&nbsp;&nbsp;0000047c&nbsp;&nbsp;2**2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTENTS, ALLOC, LOAD, READONLY, CODE<BR>...<BR><BR>[alert7@redhat62 dl]# objdump -D test<BR>Disassembly of section alert7:<BR><BR>0804847c &lt;foo&gt;:<BR>804847c:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; %ebp<BR>804847d:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 89 e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<BR>804847f:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 68 de 84 04 08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; $0x80484de<BR>8048484:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e8 a3 fe ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp; 804832c &lt;_init+0x70&gt;<BR>8048489:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 83 c4 04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;$0x4,%esp<BR>804848c:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<BR>804848d:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>804848e:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 89 f6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esi,%esi<BR><BR>08048490 &lt;bar&gt;:<BR>8048490:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; %ebp<BR>8048491:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 89 e5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;%esp,%ebp<BR>8048493:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 68 ef 84 04 08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp; $0x80484ef<BR>8048498:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e8 8f fe ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp; 804832c &lt;_init+0x70&gt;<BR>804849d:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 83 c4 04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;$0x4,%esp<BR>80484a0:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave<BR>80484a1:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<BR><BR>在这里，我创建了一个自己的alert7 section,并把foo,bar两个函数放到了这个<BR>section中。一般定义的函数都会放在.text section中。<BR><BR><BR><BR>★5.3.1 在C库中的初始化函数<BR><BR>另外一个GCC的特性是__attribute__( section ("sectionname") ).使用这个，<BR>能把一个函数或者是数据结构放到任何的section中。<BR><BR>static void<BR>foo (int argc,char **argc,char **envp)<BR>&nbsp;&nbsp;&nbsp;&nbsp;__attribute__ ((section ("_libc_foo")));<BR><BR>static void <BR>foo (int argc,char **argv,char **envp)<BR>{<BR>}<BR><BR>static void <BR>bar (int argc,char **argv,char **envp)<BR>{<BR>}<BR><BR>static void * __libc_subinit_bar__<BR>&nbsp;&nbsp;&nbsp;&nbsp;__attribute__ (( section ("_libc_subinit")))=&amp;(bar);<BR><BR>这里，我们把foo放到了_libc_foo section，把__libc_subinit_bar__放<BR>到了_libc_subinit section中。在Linux C库中，_libc_subinit 是一个特别<BR>的section，它包含了一个函数指针（有如下原型）的数组。<BR><BR>void (*) (int argc,char **argv,char **envp);<BR><BR>这里的argc,argv,envp跟在main中的有同样的意义。该section中的函数在进入<BR>main函数之前就会被调用。这是很有用的，可用来在Linux C库中初始化一些<BR>全局变量。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;[译注：_libc_subinit section真有这个特别的功能吗？我是没有试<BR>&nbsp;&nbsp;&nbsp;&nbsp;成功，如果有人试成功或者认为我理解有误的地方，千万记得mail给<BR>&nbsp;&nbsp;&nbsp;&nbsp;我:) <BR>&nbsp;&nbsp;&nbsp;&nbsp;测试程序如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;#include &lt;stdio.h&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;#include &lt;stdlib.h&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;static void foo(int argc,char **argv,char **envp)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("hi dear njlily!\n");<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;int main(int argc, char *argv[])<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("foo == %p\n", foo);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;static void * __libc_subinit_bar__<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__attribute__ (( section ("_libc_subinit")))=&amp;(foo);<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;[alert7@redhat62 dl]# gcc -o test1 test1.c<BR>&nbsp;&nbsp;&nbsp;&nbsp;[alert7@redhat62 dl]# ./test1<BR>&nbsp;&nbsp;&nbsp;&nbsp;foo == 0x8048400<BR>&nbsp;&nbsp;&nbsp;&nbsp;:( 用objdump，显示已经创建了一个_libc_subinit section,并且<BR>&nbsp;&nbsp;&nbsp;&nbsp;该section前四个字节就是foo地址0x8048400<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;]<BR><BR><BR><BR>★5.4 利用GCC和GNU ld<BR><BR>这一些命令行的选项对GCC和GNU ld创建ELF时特别有用。-shared告诉gcc<BR>产生一个共享库，该共享库能在连接时和其他的共享文件一起形成可执行<BR>文件，该共享库也能在运行时装载进可执行文件的地址空间。使用-shared<BR>是创建一个共享ELF库的首选方法。<BR><BR>另外一个有用的命令行选项是-Wl,ldoption,传递参数ldoption作为连接器<BR>的选项。假如ldoption包含多个逗号，将分离成多个选项。<BR><BR>-static选项将产生一个和static库一道连接的可执行文件。当没有开启<BR>-static选项时，连接器首先试着用共享库，假如共享版本不可用，然后<BR>再试着用静态(static)库。<BR><BR>这里还有些特别的命令行选项对ELF来说特别的或者说是有用的。<BR><BR>-dynamic-linker file<BR>&nbsp;&nbsp;&nbsp;&nbsp;设置动态连接器(dynamic linker)的名字。默认的动态连接器<BR>&nbsp;&nbsp;&nbsp;&nbsp;或者是/usr/lib/libc.so.1或者是/usr/lib/libd1.so.1<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR><BR>-export-dynamic<BR>&nbsp;&nbsp;&nbsp;&nbsp;告诉连接器使在可执行文件中的所有标号对动态连接器可用。当一个<BR>&nbsp;&nbsp;&nbsp;&nbsp;动态装载进的共享库参考可执行文件中的标号，该标号一般在动态连<BR>&nbsp;&nbsp;&nbsp;&nbsp;接时是不可用时，这时候就特别有用。<BR><BR>-lfile<BR>&nbsp;&nbsp;&nbsp;&nbsp;加文件到需要连接的列表中。该选项可用在许多时候。ld将搜索它的<BR>&nbsp;&nbsp;&nbsp;&nbsp;path-list查找文件libfile.so(也就是说假如库为libbar.so，那么<BR>&nbsp;&nbsp;&nbsp;&nbsp;使用的时候就这样使用，-lbar),或者libfile.a（static版本的）。<BR>&nbsp;&nbsp;&nbsp;&nbsp;一些情况下，共享库名libfile.so会被存储在resulting executable<BR>&nbsp;&nbsp;&nbsp;&nbsp;或者是共享库中。当resulting executable或者是共享库被装载进内<BR>&nbsp;&nbsp;&nbsp;&nbsp;存，动态连接器也将把使用记录过的共享库装载到进程的地址空间去。<BR>&nbsp;&nbsp;&nbsp;&nbsp;在以后的事情情况下，把必要的函数和数据被拷贝到可执行文件，减<BR>&nbsp;&nbsp;&nbsp;&nbsp;少代码长度。<BR><BR>-m emulation<BR>&nbsp;&nbsp;&nbsp;&nbsp;仿效emulation连接器r.-V参数可列出所有可用的选项.<BR><BR>-M | -Map mapfile<BR>&nbsp;&nbsp;&nbsp;&nbsp;把连接map输出到标准输出或者一个mapfile文件里，该连接map含有<BR>&nbsp;&nbsp;&nbsp;&nbsp;关于标号被ld映象到了哪里的一些诊断信息，还有全局共同的存储<BR>&nbsp;&nbsp;&nbsp;&nbsp;分配信息。<BR><BR>-rpath directory<BR>&nbsp;&nbsp;&nbsp;&nbsp;加一个目录到运行时library的搜索路径。所有的-rpath参数被连接<BR>&nbsp;&nbsp;&nbsp;&nbsp;在一起然后传给动态连接器。它们被用来在运行时定位共享库。<BR><BR>-soname name<BR>&nbsp;&nbsp;&nbsp;&nbsp;当创建一个共享库时，指定的名字被放在共享库中。当和这个共享<BR>&nbsp;&nbsp;&nbsp;&nbsp;库连接的可执行文件被运行，动态连接器将试着map记录着的指定<BR>&nbsp;&nbsp;&nbsp;&nbsp;名字的共享库而不是传给连接器的文件名。<BR><BR>-static<BR>&nbsp;&nbsp;&nbsp;&nbsp;告诉连接器不要和任何共享库连接。<BR><BR>-verbose<BR>&nbsp;&nbsp;&nbsp;&nbsp;告诉连接器打印它每个要打开的文件名。<BR><BR>linux下gcc beta版本使用-dynamic-linker file选项设置动态连接器为<BR>/lib/ld-linker.so.1。该选项可以使ELF和a.out共享库很好的共存。<BR><BR>有件事情是另人感兴趣的。<BR><BR>[alert7@redhat62 dl]# gcc -shared -o libbar.so libbar.o -lfoo<BR><BR>假如libfoo.so被用来创建共享库时，有趣的时候就会发生了。当libbar.so<BR>被映象到进程的地址空间的时候，动态连接器也把libfoo.so映象到内存。<BR>假如libbar.so需要libfoo.so的时候，这个特性非常有用。实际上使用<BR>libbars.o库的程序编译时是不需要-lfoo的。假如archive版本的libfoo.a<BR>被使用，当在libbar.a中的标号被libbar.o引用时，它将会被搜索到。假使在<BR>libbar.so中包含libfoo.a甚至它们根本不被libbar.o使用，在这样的情况下<BR>必须逐步把.o文件加到libbar.o中：<BR><BR># rm -rf /tmp/foo<BR># mkdir /tmp/foo<BR># (cd /tmp/foo/;ar -x ....../libfoo.a)<BR># gcc -shared -o libbar.so libbar.o /tmp/foo/*.o<BR># rm -rf /tmp/foo<BR><BR>在libfoo.a中的.o文件必须用-fPIC编译或者至少和PIC（位置无关）是<BR>兼容的。<BR><BR>当使用<BR><BR>static void * __libc_subinit_bar__<BR>&nbsp;&nbsp;&nbsp;&nbsp;__attribute__&nbsp;&nbsp;&nbsp;&nbsp;((section ("_libc_subinit")))=&amp;(bar);<BR><BR>来把一个标号放到一个没有被连接器定义的section中（在这里是<BR>_libc_subinit).连接器将所有在_libc_subinit section中的标号共同<BR>创建两个标号，一个是__start__libc_subinit和__stop__libc_subinit,<BR>它们作为C的标志符被使用。<BR><BR>警告：<BR>下面是完全可能的：连接器可能不能搜索到包含_libc_subinit section<BR>的文件(该section中没有程序执行需要的标号)。这就使程序要确定使<BR>_libc_subinit section能被连接器搜索得到。<BR><BR>一种解决的办法是：把一个dummy标号放到_libc_subinit section中，<BR>在文件中定义它，使它参考引用_libc_subinit section.<BR><BR><BR>★5.5 Linux下的ELF<BR><BR>在Linux下ELF的执行有独特的特性，这些特性对Linux的使用者来说是很有用<BR>的。一些Linux自己的扩展跟Solaris ELF的执行很类似。<BR><BR>★5.5.1 ELF的宏(macros)<BR><BR>&lt;gnu-stabs.h&gt;中，定义了能维护标号的一些宏。<BR><BR>elf_alias(name1,name2)<BR>&nbsp;&nbsp;&nbsp;&nbsp;为标号name1定义一个化名name2.当文件中标号名已经被定义的时候<BR>&nbsp;&nbsp;&nbsp;&nbsp;应该是有很用的。<BR><BR>weak_alias(name1,name2)<BR>&nbsp;&nbsp;&nbsp;&nbsp;为标号name1定义一个弱化名name2。仅当name2没有在任何地方定义<BR>&nbsp;&nbsp;&nbsp;&nbsp;时，连接器就会用name1解析name2相关的符号。在文件中定义的<BR>&nbsp;&nbsp;&nbsp;&nbsp;标号name1也会同样处理。<BR><BR>elf_set_element(set,symbol)<BR>&nbsp;&nbsp;&nbsp;&nbsp;强迫标号成为set集合的元素。为每个set集合创建一个section.<BR><BR>symbol_set_declare(set)<BR>&nbsp;&nbsp;&nbsp;&nbsp;在该模块中宣告一个集合set.事实上宣告了两个标号：<BR>&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;一个set的开始标号<BR>&nbsp;&nbsp;&nbsp;&nbsp;extern void * const __start_set<BR>&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;一个set的结尾标号<BR>&nbsp;&nbsp;&nbsp;&nbsp;extern void * const __stop_set<BR><BR>symbol_set_first_element(set)<BR>&nbsp;&nbsp;&nbsp;&nbsp;返回一个指针(void * const *),指向set集合第一个元素。<BR><BR>symbol_set_end_p(set,ptr)<BR>&nbsp;&nbsp;&nbsp;&nbsp;假如ptr(void * const *)逐渐增加指向set的最后一个元素，<BR>&nbsp;&nbsp;&nbsp;&nbsp;就返回为true.<BR><BR>使用这些宏，程序员能任意从不同的源文件中创建列表。<BR><BR><BR>★5.5.2 library(库)的定位和搜索路径<BR><BR>在Linux下，大部分系统的library库被安装在/usr/lib目录下。只有一些<BR>基本的共享库被安装在/lib目录下。例如：libc.so,libcurses.so,libm.so<BR>,libtermcap.so(各个版本对应的文件会有些不同)，在其他部分被mount上<BR>之前，那些文件是启动Linux系统所必须的。连接器默认的搜索路径是<BR>/lib,/usr/lib,/usr/local/lib,/usr/i486-linux/lib。<BR><BR>环境变量LD_LIBRARY_PATH也可保存目录列表，用(:)分开，该变量被动态<BR>连接器检查并用该变量指出的目录查找共享库。<BR>例如：/usr/X11R6/lib:/usr/local/lib:告诉动态连接器查找共享库除了<BR>现在在默认的目录查找外，然后在/usr/X11R6/lib目录，然后再是<BR>/usr/local/lib目录，然后再是当前目录。<BR><BR>新的环境变量ELF_LD_LIBRARY_PATH扮演着和LD_LIBRARY_PATH类似的角色。<BR>因为LD_LIBRARY_PATH也被老的a.out DLL linux的共享库使用。为了避免<BR>来自DLL连接器的不必要的警告，对于在Linux下ELF的动态连接器来说，<BR>最好使用LD_LIBRARY_PATH环境变量。<BR><BR>另外一个特性是/etc/ld.so.conf文件，该文件包含了一些目录列表。<BR>例如：<BR><BR>/usr/X11R6/lib<BR>/usr/lib<BR>/usr/kerberos/lib<BR>/usr/i486-linux-libc5/lib<BR>/usr/lib/gconv<BR>/usr/lib/qt-2.1.0/lib<BR>/usr/lib/qt-1.45/lib<BR><BR>程序ldconfig将把/etc/ld.so.conf文件中列出的搜索目录中的所有的<BR>共享库存储到/etc/ld.so.cache中。假如共享库已经被从默认的目录中<BR>移走，Linux ELF动态连接库将在/etc/ld.so.cache文件中找该共享库。<BR><BR><BR><BR>★5.5.3 共享库的版本<BR><BR>在ELF系统上，假如两个共享库有同样的应用程序二进制接口(ABI)的子集<BR>的话,对那些仅仅使用那些ABI子集的程序来说，这两个共享库是可以互相<BR>通用的（当然那两个共享库有同样的函数功能）。<BR><BR>当一个库被改变，只要新的ABI和前面一个版本的共享库有100%的兼容的话，<BR>所有和前面版本连接的程序在新的共享库下也能很好的运行。为了支持这，<BR>foo库必须小心的维护：<BR><BR>1.这个共享库应该如下构造：<BR><BR>[alert7@redhat62 dl]# gcc -shared -Wl,-soname,libfoo.so.major \<BR>&nbsp;&nbsp;&nbsp;&nbsp;-o libfoo.so.major.minor.patch-level libfoo.o<BR><BR>动态连接器运行时将试着定位和映象libfoo.so.major而不管事实上用的共享<BR>文件名libfoo.so.major.patch-level。<BR><BR>2.一个符号连接应该指向正确的共享库<BR><BR>[alert7@redhat62 dl]# ln -s libfoo.so.major.minor.patch-level \<BR>&nbsp;&nbsp;&nbsp;&nbsp;libfoo.so.major<BR><BR>3.当ABI改变和原来版本不兼容的时，主(major)版本号应该升级。<BR><BR>当搜索共享库的时候，Linux连接器将使用最新的共享库（它们有最高的<BR>major,minor和patch level的版本号）。<BR><BR><BR>★5.5.4 共享(shared)库和静态(static)库的混合连接<BR><BR>默认情况下，假如共享库可用，连接器会使用共享库。但是-Bdynamic和<BR>-Bstatic提供了很好控制库的方法。它们可以决定用共享库还是用静态库。<BR><BR>传-Bdynamic和-Bstatic选项给连接器，如下操作：<BR># gcc -o main main.o -Wl,-Bstatic \<BR>&nbsp;&nbsp;&nbsp;&nbsp;-lfoo -Wl,-Bdynamic -lbar<BR><BR># gcc -o main main.o -Wl,-Bstatic<BR>告诉连接器所有的库(象libc等等)都使用静态的版本。<BR><BR><BR>★5.5.5 装载附加的共享库<BR><BR>在ELF系统上，为了执行一个ELF文件，内核要把控制权交给动态连接器<BR>ld-linux.so.1(在linux上动态连接器是ld-linux.so.1，版本不同也会不同的，<BR>在默认的redhat6.2上是/lib/ld-linux.so.2)。在绝对路径/lib/ld-linux.so.1<BR>以二进制存放着。假如动态连接器不存在，没有哪个ELF可执行文件能运行。<BR><BR>动态连接器执行以下一个步骤完成从程序到进程映象：<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;1.分析可执行文件中的动态信息section，决定需要哪些库。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;2.定位和映象(map)那些共享库，并且分析它们动态信息section<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;决定是否需要附加的共享库。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;3.为可执行程序和那些需要的共享库执行重定位。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;4.调用共享库中提供的任何初始化函数并且安排共享库提供的<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;清除(cleanup)函数在共享库卸栽出进程空间的时候运行。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;5.传控制给程序<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;6.为应用程序提供函数的迟延装定服务<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;7.为应用程序提供动态转载服务。<BR><BR>环境变量LD_PRELOAD设置共享库名或者用":"把文件名隔开。动态连接器在<BR>任何那些请求的共享库之前把环境变量LD_PRELOAD的共享库装载到进程地址<BR>空间去。例如：<BR><BR># LD_PRELOAD=./mylibc.so myprog<BR><BR>这里./mylibc.so将第一时间map到程序myprog的空间。因为动态连接器在找<BR>寻标号的时候总是使用第一次碰到的标号，所以我们可以使用LD_PRELOAD来<BR>覆盖标准共享库中的函数。这个特性对程序员来说是很有用的，可用来在还<BR>没有建好整个共享库的时候对单个函数功能先做调试实验。<BR><BR>我们可以这样：<BR>#gcc -c -fPIC -O3 print.c<BR>#gcc -shared print.o -o print.so.1.0<BR>创建自己的共享连接库<BR><BR>★5.5.6 Linux下动态装载(Dynamic loading)<BR><BR>_dlinfo是动态连接接口库的一个函数。它列出所有映射到执行程序和通过<BR>dlopen打开的每个共享库。它的输出类试以下：<BR><BR>List of loaded modules<BR>&nbsp;&nbsp;&nbsp;&nbsp;00000000 50006163 50006200 Exe 1<BR>&nbsp;&nbsp;&nbsp;&nbsp;50007000 5000620c 50006200 Lib 1 /lib/elf/libd1.so.1<BR>&nbsp;&nbsp;&nbsp;&nbsp;5000a000 500062c8 50006200 Lib 2 /lib/elf/libc.so.4<BR>&nbsp;&nbsp;&nbsp;&nbsp;50000000 50006000 00000000 Int 1 /lib/elf/ld-linux.so.1<BR>&nbsp;&nbsp;&nbsp;&nbsp;500aa000 08006f00 08005ff0 Mod 1 ./libfoo.so<BR><BR>Modules for application (50006200):<BR>&nbsp;&nbsp;&nbsp;&nbsp;50006163<BR>&nbsp;&nbsp;&nbsp;&nbsp;5000620c /lib/elf/libdl.so.1<BR>&nbsp;&nbsp;&nbsp;&nbsp;500062c8 /lib/elf/libc.so.4<BR>&nbsp;&nbsp;&nbsp;&nbsp;50006000 /lib/ld-linux.so.1<BR>Modules for handle 8005ff0<BR>&nbsp;&nbsp;&nbsp;&nbsp;08006f00 ./libfoo.so<BR>&nbsp;&nbsp;&nbsp;&nbsp;500062c8 /lib/elf/lib.so.4<BR>&nbsp;&nbsp;&nbsp;&nbsp;50006163 <BR>&nbsp;&nbsp;&nbsp;&nbsp;5000620c /lib/elf/libd1.so.1<BR>&nbsp;&nbsp;&nbsp;&nbsp;500062c8 /lib/elf/libc.so.4<BR>&nbsp;&nbsp;&nbsp;&nbsp;50006000 /lib/elf/ld-linux.so.1<BR><BR>以上可被用来解释动态的连接和动态的装载。<BR><BR>在linux支持ELF上配置的GCC假如使用了-rdynamic选项，它将把<BR>-export-dynamic传给连接器。强烈建议使用动态装载。这就是为什么在<BR>我们的Makefile例子中使用了LDFLAGS=-rdynamic。暂时，这个选项只能在<BR>linux下使用。但是-Wl,-export-dynamic能在其他的平台上把-export-dynamic<BR>传给GNU的连接器。<BR><BR>你能在GNU link editor的[3]和[4]部分找到它详细的描述。<BR><BR><BR>★6 位置无关代码(PIC)的汇编语言编程<BR><BR>当用gcc指定-fPIC的时候，gcc将从C源代码中产生PIC的汇编语言代码。但有<BR>时候，我们需要用汇编语言来产生PIC代码。<BR><BR>在ELF下，PIC的实现是使用基寄存器(base register)。在PIC下，所有的<BR>标号引用都是通过基寄存器实现的，为此，要用汇编写PIC的话，必须保存<BR>基寄存器(base register)。由于位置无关代码，控制传送指令的目的地址<BR>必须被替换或者是在PIC情况下计算的。对X86机器来说，该基寄存器<BR>(base register)就是ebx.这里我们将介绍在X86上安全的PIC汇编代码的<BR>两种方法。这些技术在Linux C库中也被使用到。<BR><BR><BR>★6.1 在C中内嵌汇编<BR><BR>gcc支持内嵌汇编的声明，可让程序员在C语言中使用汇编语言。当写LINUX系<BR>统调用接口的时候这是很有用的，而无须使用机器相关指令。<BR><BR>在linux 下系统调用是通过int $0x80的。一般的，系统调用会有三个参数:<BR><BR>#include &lt;sys/syscall.h&gt;<BR><BR>extern int errno;<BR><BR>int read( int fd,void *buf ,size count)<BR>{<BR>long ret;<BR><BR>__asm__ __volatile__ ("int $0x80"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:"=a"(ret)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:"O"(SYS_read),"b"((long)fd),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "c"((long)buf),"d"((long)count):"bx");<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (ret&gt;=0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;return (int) ret:<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;errno=-ret;<BR>retrun -1;<BR>}<BR><BR>以上汇编代码把系统调用号SYS_read放到了eax中，fd到ebx中，buf到<BR>ecx中，count到edx中，从int $0x80中返回值ret放在eax中。在不用<BR>-fPIC的情况下，这样定义运行良好。带-fPIC的gcc应该要检查ebx是否被<BR>被改变，并且应该在汇编代码里保存和恢复ebx。但是不幸的是，事实上不是<BR>这样的。我们为了支持PIC必须自己写汇编代码。<BR><BR>#include &lt;sys/syscall.h&gt;<BR><BR>extern int errno;<BR><BR>int read( int fd,void *buf ,size count)<BR>{<BR>long ret;<BR><BR>__asm__ __volatile__ ("pushl %%ebx\n\t"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"movl %%esi,%%ebx\n\t"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"int $0x80\n\t"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"popl %%ebx"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:"=a"(ret)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:"O"(SYS_read),"S"((long)fd),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "c"((long)buf),"d"((long)count):"bx");<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (ret&gt;=0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;return (int) ret:<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;errno=-ret;<BR>return -1;<BR>}<BR><BR>这里首先把fd放到esi中，然后保存ebx,把esi移到ebx，在int $0x80后恢复<BR>ebx。这样保证ebx不被改变(除了在int $0x80中断调用中)。同样的原则也<BR>适用于其他内嵌的汇编。<BR><BR>在任何时候，当ebx可能要被改变时，千万要记得保存和恢复ebx.<BR><BR><BR>★6.2 用汇编语言编程<BR><BR>假如我们在系统调用时需要传5个参数时候，内嵌的汇编代码即使是PIC<BR>的，也不能工作，因为x86没有足够的寄存器。我们需要直接用汇编语言<BR>编写。<BR><BR>syscall(int syscall_number,...)的一般汇编代码如下：<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;.file "syscall.S"<BR>&nbsp;&nbsp;&nbsp;&nbsp;.text<BR>&nbsp;&nbsp;&nbsp;&nbsp;.global syscall<BR>&nbsp;&nbsp;&nbsp;&nbsp;.global errno<BR>&nbsp;&nbsp;&nbsp;&nbsp;.align 16<BR><BR>syscall:<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl 5ebp<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %esp,%ebp<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %edi<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %esi<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 8(%ebp),%eax&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 12(%ebp),%ebx&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 16(%ebp),%ecx&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 20(%ebp),%edx&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 24(%ebp),%esi&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 28(%ebp),%edi&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;int $0x80<BR>&nbsp;&nbsp;&nbsp;&nbsp;test %eax,%eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;jpe .LLexit<BR>&nbsp;&nbsp;&nbsp;&nbsp;negl %eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %eax,errno<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl $-1, %eax<BR><BR>.LLexit:<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %esi<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %edi<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %ebp,%esp<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %ebp<BR>&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>&nbsp;&nbsp;&nbsp;&nbsp;.type syscall,@function<BR>.L_syscall_end:<BR>&nbsp;&nbsp;&nbsp;&nbsp;.size syscall,.L_syscall_end -syscall<BR><BR>在PIC下，我们必须通过GOT(global offset table)来访问任何全局变量<BR>(除了保存在基寄存器ebx中的)。修改的代码如下：<BR><BR>.file "syscall.S"<BR>.text<BR>.global syscall<BR>.global errno<BR>.align 16<BR>syscall:<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %ebp<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %esp,%ebp<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %edi<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %esi<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;call .LL4<BR>.LL4:<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;addl $_GLOBAL_OFFSET_TABLE_+[.- .LL4],%ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;pushl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 8(%ebp),%eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 12(%ebp),%ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 16(%ebp),%ecx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 20(%ebp),%edx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 24(%ebp),%esi<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl 28(%ebp),%edi<BR>&nbsp;&nbsp;&nbsp;&nbsp;int $0x80<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %eax,%edx<BR>&nbsp;&nbsp;&nbsp;&nbsp;test %edx,%edx<BR>&nbsp;&nbsp;&nbsp;&nbsp;jge .LLexit<BR>&nbsp;&nbsp;&nbsp;&nbsp;negl %edx<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl errno@GOT(%ebx),%eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %edx,(%eax)<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl $-1,%eax<BR>.LLexit:<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %ebx<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %esi<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %edi<BR>&nbsp;&nbsp;&nbsp;&nbsp;movl %ebp,%esp<BR>&nbsp;&nbsp;&nbsp;&nbsp;popl %ebp<BR>&nbsp;&nbsp;&nbsp;&nbsp;ret<BR>&nbsp;&nbsp;&nbsp;&nbsp;.type syscall,@function<BR>.L_syscall_end:<BR>&nbsp;&nbsp;&nbsp;&nbsp;.size syscall,.L_syscall_end-syscall<BR><BR>假如要得到PIC的汇编代码，但是又不知道如何写，你可以写一个C的，然后如下<BR>编译：<BR><BR>#gcc -O -fPIC -S foo.c<BR><BR>它将告诉gcc产生汇编代码foo.s输出,根据需要，可以修改它。<BR><BR><BR>★7 结束语<BR><BR>根据以上讨论的，我们可以得出这样的结论：ELF是非常灵活的二进制格式。<BR>它提供了非常有用的功能。这种规范没有给程序和程序员太多限制。它使<BR>创建共享库容易，使动态装载和共享库的结合更加容易。在ELF下，在C++<BR>中，全局的构造函数和析构函数在共享库和静态库中用同样方法处理。<BR><BR><BR>[译注：<BR>&nbsp;&nbsp;&nbsp;&nbsp;到此，文章是翻译好了，但里面的一些东西看起来可能<BR>&nbsp;&nbsp;&nbsp;&nbsp;有点问题，比如说_libc_subinit section没有他说的<BR>&nbsp;&nbsp;&nbsp;&nbsp;那个功能，-dynamic-linker选项在默认的redhat 6.2系统<BR>&nbsp;&nbsp;&nbsp;&nbsp;上不能用，_dlinfo动态连接接口库函数好象在linux没有实现<BR>&nbsp;&nbsp;&nbsp;&nbsp;等等一系列问题，欢迎讨论指正<BR>&nbsp;&nbsp;&nbsp;&nbsp;mailto: alert7@21cn.com <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert7@xfocus.org<BR>]<BR><BR>参考：<BR><BR>1. Operating System API Reference:UNIX SVR4.2,UNIX Press,1992<BR><BR>2. SunOs 5.3 Linker and Libraries Manual,SunSoft ,1993.<BR><BR>3. Richard M.Stallman,Using and porting GNU CC for version 2.6,<BR>&nbsp;&nbsp; Free Software Foundation,September 1994.<BR><BR>4. Steve Chamberlain and Roland Pesch,Using ld:The GNU linker,ld<BR>&nbsp;&nbsp; version 2,Cygnus Support,January 1994.<img src ="http://www.blogjava.net/sk8boy/aggbug/15646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2005-10-16 16:27 <a href="http://www.blogjava.net/sk8boy/articles/15646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>convert+批处理文件实现png2eps转换</title><link>http://www.blogjava.net/sk8boy/articles/2458.html</link><dc:creator>思考</dc:creator><author>思考</author><pubDate>Fri, 25 Mar 2005 18:20:00 GMT</pubDate><guid>http://www.blogjava.net/sk8boy/articles/2458.html</guid><wfw:comment>http://www.blogjava.net/sk8boy/comments/2458.html</wfw:comment><comments>http://www.blogjava.net/sk8boy/articles/2458.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/sk8boy/comments/commentRss/2458.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sk8boy/services/trackbacks/2458.html</trackback:ping><description><![CDATA[<P>边学习LaTeX，边把自己的毕业论文从原先的Word文档改成LaTeX的。进度比较慢<IMG height=19 src="http://www.blogjava.net/Emoticons/red_smile.gif" width=19 border=0>，所以现在菜开始向文档中加入图片。因为以前作图用的是Visio 2003，所以考虑怎样将图片格式转换成eps的。<BR><BR>因为Visio 2003不能将图片直接另存为eps格式的，所以开始只选择了另存为png的。但是又如何将png格式的图片转换位eps的呢？这个我想了半天。后来尝试使用Adobe的Acrobat 7.0对其进行转换，首先保存为pdf格式的，后来有另存为eps的。高兴ed，可是插入tex文档的时候发现出了问题。发现一个页面里面只有一张图片。所以翻开LaTeX graphics又看了看，才发可能是eps文件格式的问题。<BR><BR>但是用UltraEdit打开看了看又Acrobat生成的这个文件，虽然多了很多其他的东西，但是BoundingBox的值是对的。不知道为什么会发生这种情况。后来下载安装了ImageMagick，它有一个图片浏览器，可以看eps文件。用这个浏览器打开发现，Acrobat生成的eps文件居然被放在了屏幕的中间（应该是放在左下角的）。因为对eps文件的语法规范不是很熟，所以没有搞懂是怎么回事。<BR><BR>后来在ImageMagick里面找到了convert这个工具，试着用了一下，结果可以生成我想要的eps文件了。但是又面临的一个问题是我又很多png文件需要转换，不想一个一个调用命令。也是尝试使用命令：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">convert  </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">.png  </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">.eps</SPAN></DIV></DIV>
<P>但是生成的文件名都乱了，都被改成数字编号了。怎么办呢？所以就想着自习写一个程序来完成，但是转念一想，为什么不用DOS的批处理文件试一试呢，说不定也可以搞定。<BR><BR>可是面临的问题是不知道怎么得到一个文件的文件名（没有.和后缀）。在网上看了几篇关于批处理命令的文章，发现写得都差不多。而且也没有找到我想要的（其实当时看露了，是有的）。正当我在郁闷的时候，同学告诉我Windows XP自带的帮助里面就有DOS下批处理的命令的语法介绍。于是我就如获至宝的开始看来起来。果然被我找到了，而且比网上的要好理解一些。下面就是我写得一个简单的程序：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">echo off<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">  </SPAN><SPAN style="COLOR: #000000">%%</SPAN><SPAN style="COLOR: #000000">f  </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">  (</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">.png)  </SPAN><SPAN style="COLOR: #0000ff">do</SPAN><SPAN style="COLOR: #000000">  convert  </SPAN><SPAN style="COLOR: #000000">%%</SPAN><SPAN style="COLOR: #000000">f   </SPAN><SPAN style="COLOR: #000000">%%~</SPAN><SPAN style="COLOR: #000000">nf.eps<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>pause</SPAN></DIV></DIV><BR>嘿嘿，搞定了！<BR><BR>不过后来有在网上发现了<FONT face=Arial><A href="http://www.hooklee.com/tex/xConvert.zip">xConvert</A></FONT>这个软件，是用C写的。它对GhostView和ImageMagick进行了封装，通过命令行可以方便的实现上述功能。当然还有其他更强大的功能等着你去发现啊！<BR><BR>今天有安装了TechSmith公司的SnagIt，发现这个软件除了可以抓屏外，也可以方便地将png格式转换成eps格式。<img src ="http://www.blogjava.net/sk8boy/aggbug/2458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sk8boy/" target="_blank">思考</a> 2005-03-26 02:20 <a href="http://www.blogjava.net/sk8boy/articles/2458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>