⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 038.htm

📁 LINUX的操作系统分析文件和使用文件
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<br><br>6.4. 建立你自己的程式库(Building your own libraries) <br>6.4.1. 版本控制(Version control) <br>与其它任何的程式一样,程式库也有修正不完的bugs的问题存在.它们也可能产生出一些新的特点,更改目前存在的模组的功效,或是将旧的移除掉.这对正在使用它们的程式而言,可能会是一个大问题.如果有一支程式是根据那些旧的特点来执行的话,那怎麽办? <br><br>所以,我们引进(introduce)了程式库版本编号(versioning)的观念.我们将程式库*次要(minor)*与*主要(major)*的变更分门别类(categorize),同时我们规定*次要*的变更是不允许用到这程式库的旧程式发生中断的现象(break).你可以从程式库的档名分辨出它的版本(实际上,严格来讲,对ELF而言仅仅是一场天大的谎言;继续读将下去,便可明白为什麽了): libfoo.so.1.2的主要版本是1,次要版本是2.次要版本的编号可能真有其事,也可能什麽都没有---libc在这一点上用了*修正程度(patch-level)*的观念,而给出了名称像libc.so.5.2.18这样的程式库.次要版本的编号内若是放一些字母,底线,或是任何可以列印的ASCII字元,也是很合理的说. <br><br>ELF与a.out格式最主要的差别之一就是在建立共享程式库上.我们先看ELF,因为它比较简单一些. <br><br>6.4.2. ELF? 它到底是什麽东东ㄋㄟ? <br>ELF (Executable and Linking Format) 最初是由USL(UNIX System Laboratories)所发展的二进位格式(binary format),而目前正应用於Solaris与System V Release 4上面.由於ELF所增涨的弹性(flexibility)远远超过Linux过去所用的a.out格式,因此GCC与C程式库的发展人士於去年(1995)决定改用ELF为Linux标准的二进位格式. <br><br>6.4.2.1. 怎麽又来了? <br>这一节是来自於'/news-archives/comp.sys.sun.misc'的文件. <br><br><br>ELF(&quot;Executable Linking Format&quot;)是於SVR4所引进的新式改良目的档格式.ELF比起COFF可是多出了不少的功能.以ELF而言,它*是*可由使用者自行延伸的(user-extensible).ELF视一目的档为节区(sections)如串列般的组合,而且此串列可为任意的(arbitrarily)长度(而不是一固定大小的阵列).这些节区与COFF的不一样,并不需要固定在某个地方,也不需要以某种顺序排列.如果users希望能补捉到新的资料,他们便可以加入新的节区到目的档内.ELF也有一个更强而有力的除错格式,称为DWARF(Debugging With Attribute Record Format)-目前Linux并不完全支援.DWARF DIEs(Debugging Information Entries)的连结串列会在ELF内形成.debug的节区.DWARF DIEs的每一个.debug节区并非一些少量的(small)且固定大小的(fixed-size)资讯记录(information records)的集合(collection),而是一任意长度的串列,拥有复杂的属性,而且程式的资料会以□围为根据的树状资料结构(scope-based tree)写出来.DIEs所能补捉到的大量资讯是COFF的.debug节区无法望其项背的.(像是C++的继承图). <br><br><br>ELF档案是从SVR4(Solaris 2.0 ?)ELF存取程式库(ELF access library)内存取的.此程式库可提供一简便快速的介面予ELF.使用ELF存取程式库最主要的恩惠之一便是,你不再需要去察看一个ELF档的qua了.就UNIX的档案而言,它是以Elf*的型式来存取;呼叫elf_open()之後,从此时开始,你只需呼叫elf_foobar()来处理档案的某一部份(components)即可,并不需要把档案实际在磁碟上的image搞得一团乱. <br><br>ELF的优缺点与升级至ELF等级所需经历的种种痛苦(contortions),已在ELF-HOWTO内论及;我并不打算在这儿涂浆糊.ELF HOWTO应该与这份文件相同之处有同样的主题才是. <br><br>6.4.2.2. ELF共享程式库 <br>若想建立libfoo.so成为共享程式库,基本的步骤会像下面这样: <br><br><br>$ gcc -fPIC -c *.c <br>$ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o <br>$ ln -s libfoo.so.1.0 libfoo.so.1 <br>$ ln -s libfoo.so.1 libfoo.so <br>$ LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ; export LD_LIBRARY_PATH <br><br><br>这会产生一个名为libfoo.so.1.0的共享程式库,以及给予ld适当的连结(libfoo.so)还有使得动态载入程式(dynamic loader)能找到它(libfoo.so.1).为了进行测试,我们将目前的目录加到LD_LIBRARY_PATH里. <br><br><br>当你津津乐道於程式库制做成功之时, 别忘了把它移到如/usr/local/lib的目录底下,并且重新建立正确的连结路径. libfoo.so.1与libfoo.so.1.0的连结会由ldconfig依日期不断的更新;就大部份的系统来说,ldconfig会在开机程序中执行. libfoo.so的连结必须由手动方式更新.如果你对程式库所有组成份子(如标头档等)的升级,总是抱持著一丝不□的态度(scrupulous),那麽最简单的方法就是让libfoo.so -&gt; libfoo.so.1;如此一来,ldconfig便会替你同时保留最新的连结.要是你没有这麽做,你自行设定的东东就会在数日後造成千奇百怪的花样出现.到时候,可别说我没提醒你啊! <br><br><br>$ su <br># cp libfoo.so.1.0 /usr/local/lib <br># /sbin/ldconfig <br># ( cd /usr/local/lib ; ln -s libfoo.so.1 libfoo.so ) <br><br><br>6.4.2.3. 版本编号, soname与符号连结 <br>每一个程式库都有一个soname.当连结器发现它正在搜寻的程式库中有这样的一个名称,连结器便会将soname箝入(embed)连结中的二进位档内, 而不是它正在运作的实际的档名.在程式执行期间,动态载入程式会搜寻拥有soname这样的档名的档案,而不是程式库的档名.因此,一个名为libfoo.so的程式库,就可以有一个libbar.so的soname了.而且所有连结到libbar.so的程式,当程式开始执行时,会寻找的便是libbar.so了. <br><br>这听起来好像一点意义也没有,但是这一点,对於了解数个不同版本的同一个程式库是如何在单一系统上共存(coexist)的原因,却是关键之钥.Linux程式库标准的命名方式,比如说是libfoo.so.1.2,而且给这个程式库一个libfoo.so.1的soname.如果此程式库是加到标准程式库的目录底下(e.g. /usr/lib),ldconfig会建立符号连结libfoo.so.1 -&gt; libfoo.so.1.2,使其正确的image能於执行期间(run-time)找到.你也需要连结libfoo.so -&gt; libfoo.so.1,使ld能於连结期间(link-time)找到正确的soname. <br><br>所以罗,当你修正程式库内的bugs,或是添加了新的函数进去(任何不会对现存的程式造成不利的(adversely)影响的改变),你会重建此程式库,保留原本已有的soname,然後更改程式库档名.而当你对程式库的变更会使得现有的程式(binaries)中断(break),那麽你只需增加soname中的编号---此例中,称新版本为libfoo.so.2.0,而soname变成libfoo.so.2.紧接著,再将libfoo.so的连结转向新的版本;至此,世界又再度恢复了和平! <br><br>其实你不须要以此种方式来替程式库命名,不过这的确是个好的传统(convention).ELF所赋予你在程式库命名上的弹性,会使得人气喘呼呼的搞不清楚状况;有这样的弹性在,也并不表示你就得去用它. <br><br>ELF总结:假设经由你睿智的观察发现有个惯例说:程式库主要的升级会破坏(break)相容性(compatibility);而次要的升级则可能不会;那麽以下面的方式来连结,所有的一切就都会相安无事了. <br><br><br>gcc -shared -Wl,-soname,libfoo.so.major -o libfoo.so.major.minor <br><br><br>6.4.3. a.out---旧旧的格式~ <br>建立共享程式库的便利性(ease)是升级至ELF的主要原因之一.那也是说,a.out可能还是有用处在的.上ftp站去抓ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz;解压缩後你会发现有20页的文件可以慢慢的读哩.我很不喜欢自己党派的偏见(partisan)表现得那麽的淋璃尽致,可是从上下文间,应该也可以很清楚的嗅出我从来不拿石头砸自己的脚的脾气吧!:-) <br><br>6.4.3.1. ZMAGIC vs QMAGIC <br>QMAGIC是一种类似旧格式的a.out(亦称为ZMAGIC)的可执行档格式,这种格式会使得第一个分页无法map.当0-4096的□围内没有mapping存在时,则可允许NULL dereference trapping更加的容易.所产生的边界效应(side effect)是你的执行档会比较小(大约是1K左右). <br><br>只有即将作废的连结器有支援ZMAGIC,一半已埋入棺材的连结器有支援这两种格式;而目前的版本仅支援QMAGIC而已.事实上,这并没有多大的影响,那是因为目前的核心两种格式都能执行. <br><br>*file*命令应该可以确认程式是不是QMAGIC的格式的. <br><br>6.4.3.2. 档案配置(File Placement) <br>一a.out(DLL)的共享程式库包含两个真实的档案与一个符号连结.就*foo*这个用於整份文件做为□例的程式库而言,这些档案会是libfoo.sa与libfoo.so.1.2;符号连结会是libfoo.so.1,而且会指向libfoo.so.1.2.这些是做什麽用的? <br><br>在编译时, ld会寻找libfoo.sa.这是程式库的*stub*档案,而且含有所有执行期间连结所需的exported的资料与指向函数的指标. <br><br>执行期间,动态载入程式会寻找libfoo.so.1.这仅仅是一个符号连结,而不是真实的档案,故程式库可更新成较新的且已修正错误的版本,而不会损毁任何此时正在使用此程式库的应用程式.在新版---比如说libfoo.so.1.3---已完整呈现时,ldconfig会以一极微小的操作,将连结指向新的版本,使得任何原本使用旧版的程式不会感到丝毫的不悦. <br><br>DLL程式库(我知道这是无谓的反覆(tautology)---所以对我提出告诉吧!)通常会比它们的静态副本(static counterparts)要来得大多了.它们是以*洞(holes)*的形式来保留空间以便日後的扩充.这种*洞*可以不占用任何的磁碟空间.一个简单的cp呼叫,或是使用makehole程式,就可以达到这样效果(achieve).因为它们的位址是固定在同一位置上,所以在建立程式库後,你可以把它们拿掉.千万不要试著夺走ELF的程式库. <br><br>6.4.3.3. ``libc-lite''? <br>libc-lite是轻量级(light-weight)的libc版本.可用来存放在磁碟片上,与替大部份低微的(menial)UNIX任务收尾(suffice).它没有包含curses, dbm, termcap等等的程式码.如果你的/lib/libc.so.4是连结到一个lite的libc,那麽建议你以完整的版本取代它. <br></p><hr SIZE="0"><p align="center"><a href="linux.htm">返回</a></p><p><br></p></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -