📄 038.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><!-- saved from url=(0056)http://data.km169.net/wsxx/showjq.asp?id=1346&type=LINUX --><html><head><title>New Page 1</title><meta content="text/html; charset=gb2312" http-equiv="Content-Type"><meta content="Microsoft FrontPage 3.0" name="GENERATOR"><meta content="FrontPage.Editor.Document" name="ProgId"><!--webbot bot="HTMLMarkup" startspan TAG="XBOT" --></SCRIPT><!--webbot bot="HTMLMarkup" endspan--><style>A:link { COLOR: #4444ff; TEXT-DECORATION: underline}A:visited { COLOR: #4444ff; TEXT-DECORATION: underline}A:active { TEXT-DECORATION: none}A:hover { COLOR: #ff0000; TEXT-DECORATION: none}BODY { COLOR: #505050; FONT-FAMILY: 宋体; FONT-SIZE: 9pt}TD { FONT-FAMILY: 宋体; FONT-SIZE: 9pt}TD.a { FONT-FAMILY: 宋体; FONT-SIZE: 9pt}TD.b { FONT-FAMILY: 宋体; FONT-SIZE: 11pt; font-color: #ff0000}.other1 { FONT-SIZE: 9pt; LETTER-SPACING: 0px; LINE-HEIGHT: 18px}.other2 { FONT-SIZE: 10.5pt}</style></head><body bgColor="#FFFFFF" leftMargin="7" topMargin="7"><hr SIZE="0"><p><b><font color="#fe3a42">标题: ■ </font><font color="#9b004e"> </font>The Linux GCC HOWTO中译版V0.1: 连结(Linking)</b><br>姓名 :Daniel Barlow<br>Email:dan@detached.demon.co.uk<br>地址 :<br>转摘 :http://member.netease.com/</p><p align="center"><a href="linux.htm">返回</a></p><hr SIZE="0"><p><br><br>6. 连结(Linking) <br>由於静态(static)与共享(shared)程式库两者间不相容的格式(incompatible binary formats)的差异性(distinction)与动词*link*过量使用(overloading)於指称*编译完成後的事情*与*当编译过的程式使用时(invoke)所发生的事情*这两件事上头,使得这一章节变得复杂了许多.( and, actually, the overloading of the word `load' in a comparable but opposite sense)不过,再复杂也就是这样了,所以阁下不必过於担心. <br><br>为了稍微减轻读者的困惑,我们称执行期间(runtime)所发生的事为*动态载入(dynamic loading)*,这一主题会在下一章节中谈到.你也会在别的地方看到我把动态载入描述成*动态连结(dynamic linking)*,不过不会是在这一章节中.换句话说,这一章节所谈的,全部是指发生在编译结束後的连结(linking). <br><br>6.1. 共享程式库 vs静态程式库 <br>建立程式的最後一个步骤便是连结;也就是将所有分散的小程式(pieces)组合起来,看看是否遗漏了些什麽.很明显的,有一些事情是很多程式都会想做的---例如,开启档案(open files),接著所有与开档有关的小程式(pieces)就会以程式库的档案型态提供给你的程式.在普通的Linux系统上,这些小程式可以在/lib与/usr/lib/目录底下找到. <br><br><br>当你用的是一静态的程式库时,连结器会找出程式所需的模组(bits),然後实际(physically)将它们拷贝到执行档内.然而,对共享程式库而言,就不是这样了.共享程式库会在执行档内留下一个符号(note),指明*当程式执行时,首先必须载入这个程式库*.很明显的,共享程式库是试图使执行档变得更小;也等同於使用更少的记忆体与磁碟空间.Linux内定的行为是连结共享程式库,只要Linux能找到这些共享程式库的话,就没什麽问题;不然,Linux就会连结静态的了.如果你想要共享程式库的话,检查这些程式库(*.sa for a.out, *.so for ELF)是否住在它们该在的地方,而且是可读取的. <br><br>在Linux上,静态程式库会有类似libname.a这样的名称;而共享程式库则称做libname.so.x.y.z,此处的x.y.z是指版本序号的样式.共享程式库通常都会有连结符号指向静态程式库(很重要的)与(on a.out configurations)相关联的.sa档案.标准的程式库会包含共享与静态程式库两种格式. <br><br>你可以用ldd (List Dynamic Dependencies)来查出某支程式需要哪些共享程式库. <br><br>$ ldd /usr/bin/lynx <br>libncurses.so.1 => /usr/lib/libncurses.so.1.9.6 <br>libc.so.5 => /lib/libc.so.5.2.18 <br><br><br>这是说在我的系统上,WWW浏览器(browser)*lynx*会依赖libc.so.5 (the C library)与libncurses.so.1(终端机萤幕的控制)的存在(presence).若某支程式缺乏独立性(dependencies), ldd就会说`statically linked'或是`statically linked (ELF)'. <br><br>6.2. Interrogating libraries (`which library is sin() in?') <br>nm 程式库名称 应该会列出此程式库名称所参考到的所有符号(symbols).这个指令可以应用在静态与共享程式库上.假设你想知道tcgetattr()是在哪儿定义的:你可以如此做 <br><br><br>$ nm libncurses.so.1 |grep tcget <br>U tcgetattr <br><br><br>*U*说明了*未定义(undefined)*---也就是说ncurses程式库有用到tegetattr(),但是并没有定义它.你也可以这样做, <br><br><br>$ nm libc.so.5 | grep tcget <br>00010fe8 T __tcgetattr <br>00010fe8 W tcgetattr <br>00068718 T tcgetpgrp <br><br><br>*W*说明了*弱势(weak)*,意指符号虽已定义,但可由不同程式库中的另一定义所取代(overridden).而最直接的(straightforward)*正常(normal)*定义(像是tcgetpgrp)是由*T*所标示. <br><br><br>标题所谈的问题,最简明的答案便是libm.(so|a)了.所有定义在<math.h>的函数都保留在maths程式库内;因此,当你用到其中任何一个函数时,都需要以-lm的参数连结此程式库. <br><br>6.3. X档案??? <br>ld: Output file requires shared library `libfoo.so.1` <br><br>ld与其相类似的命令在搜寻档案的策略(strategy)上,会依据版本的差异而有所不同,但是唯一一个你可以合理假设的内定目录便是/usr/lib了.如果你希望身处它处的程式库也列入搜寻的行列中,那麽你就必须以-L选项告知gcc或是ld. <br><br>要是你发现一点效果也没有,就赶紧察看看那档案是不是还乖乖的躺在原地.就a.out而言,以-lfoo参数来连结,会驱使ld去寻找libfoo.sa (shared stubs);如果没有成功,就会换成寻找libfoo.a (static).就ELF而言, ld会先找libfoo.so,然後是libfoo.a.libfoo.so通常是一个符号连结,连结至libfoo.so.x.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -