来源: ChinaUnix博客 日期: 2007.04.18 08:18 (共有0条评论) 我要评论
http://hi.baidu.com/yanyulou
类型是不依赖于其后缀名的,但一般来讲:
相当于windows中的.obj文件
shared object,用于动态连接的,和dll差不多
.o合在一起,用于静态连接
vi编辑查看,主要记录了一些配置信息。可以用如下命令查看*.la文件的格式
.o库文件:
ello();
,是好多个自动生成的一些共享库, $file *.la
CII English text
来查看其内容。@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@和host perl_c2]$ pwd
perl_c2
host perl_c2]$ cat mylib.c
\"success call from perl to c library\\n\");
host perl_c2]$ cat mylib.h
host perl_c2]$ gcc -c mylib.c
host perl_c2]$ dir
b.h mylib.o
host perl_c2]$ ar -r mylib.a mylib.o
mylib.a
host perl_c2]$ dir
b.c mylib.h mylib.o
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
1111111111111111111111111111111111111111111111111111111111111111111111111111111
so的编译与使用- -
linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前
做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。
译
例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,
个动态库:libtest.so。
;
;
;
_test.h\"
s is in test_a...\\n\");
_test.h\"
s is in test_b...\\n\");
_test.h\"
s is in test_c...\\n\");
编译成一个动态库:libtest.so
c test_b.c test_c.c -fPIC -shared -o libtest.so
接
们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件
_test.h\"
t.c与动态库libtest.so链接生成执行文件test:
L. -ltest -o test
是否动态连接,如果列出libtest.so,那么应该是连接正常了
est,可以看到它是如何调用动态库中的函数的。
析
CC命令行的一个选项:
red 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),
接。相当于一个可执行文件
:表示编译为位置的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来
能达到真正代码段共享的目的。
表示要连接的库在当前目录中
:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
IBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没
输出LD_LIBRARY_PATH的方法了。
库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通
,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改
_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。
怎么正确的编译和连接生成.so库文件,然后又是在其他程序的makefile里面如何编译和连接才能调用这个库文件
告诉动态链接器、加载器ld.so在哪里才能找到这个共享库,可以设置环境变量把库的路径添加到库目录/lib和/usr/
_PATH=$(pwd),这种方法采用命令行方法不太方便,一种替代方法
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^注释
^^^^^^^^^^^^^^^^^^^^
_PATH可以在/etc/profile还是 ~/.profile还是 ./bash_profile里设置,或者.bashrc里,
urce /etc/profile或 . /etc/profile
添入/etc/ld.so.conf, 然后执行 /sbin/ldconfig
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^注释
^^^^^^^^^^^^^^^^^^^^
加到/etc/ld.so.conf,然后以root身份运行ldconfig
连接的时候指定文件路径和名称 -I -L.
c
all -ggdb -fPIC
st
o func1.o
) -shared -Wl,-soname,libfunc.so.1 -o libfunc.so.1.1 $
时使用gcc的-fPIC选项,产生与位置无关的代码并能被加载到任何地址:
–c liberr.c –o liberr.o
hared和-soname选项;
l选项把参数传递给连接器ld;
选项显示的连接C库,以保证可以得到所需的启动(startup)代码,从而避免程序在使用不同的,可能不兼容版本
行。
ed –Wl,-soname,liberr.so –o liberr.so.1.0.0 liberr.o –lc
号连接:
o.1.0.0 liberr.so.1;
o.1.0.0 liberr.so;
中:
中的目标文件集。在模式规则中,如果有多个目标,那么,\"$@\"就是匹配于目标中模式定义的集合。
数库文件中,表示规则中的目标成员名。例如,如果一个目标是\"foo.a(bar.o)\",那么,\"$%\"就是\"bar.o\",\"$@\"
目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
***********************************注释
*************************************************************
bfunc
) -o test test.o -L. -lfunc
) -c $(CFLAGS) -o $@ $ref:http://niefei.blog.ccidnet.com/blog/ccid/do_showone/tid_42855.html
的工具我们如何在Linux下创建自己的程序函数库?一个“程序 函数库”简单的说就是一个文件包含了一些编译好的代
数据可以在事后供其他的程序使用。程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级。程
静态函
braries)、共享函数库(shared libraries)和动态加载函数库(dynamically loaded
库是在程序执行前就加入到目标程序中去了;而共享函数库则是在程序启动的时候加载到程序中,它可以被
享;动态加载函数库则可以在程序运行的任何时候动态的加载。实际上,动态函数库并非另外一种库函数格式,区别
程序员
我们将举例说明。
要参考Program Library HOWTO,作者是luster(
.edu
业目的的再次发行本文档都是允许的,但是请保留作者信息和本版权声明。本文档首先在
d.com.cn
实际上就是简单的一个普通的目标文件的集合,一般来说习惯用“.a”作为文件的后缀。可以用ar这个程序来产生静
缩写。静态函数库现在已经不在像以前用得那么多了,主要是共享函数库与之相比较有很多的优势的原因。慢慢地
在一些场所静态函数库仍然在使用,一来是保持一些与以前某些程序的兼容,二来它描述起来也比较简单。
数允许程序
起来而不用重新编译代码,节省了重新编译代码的时间。不过,在今天这么快速的计算机面前,一般的程序的重新编
以
不是像它以前那么明显了。静态函数库对开发者来说还是很有用的,例如你想把自己提供的函数给别人使用,但是又
,你就
供一个静态函数库文件。理论上说,使用ELF格式的静态库函数生成的代码可以比使用共享函数库(或者动态函数
行速度上快一些,大概1-5%。
静态函数库文件,或者往一个已经存在地静态函数库文件添加新的目标代码,可以用下面的命令:
rary.a file1.o file2.o
是把目标代码file1.o和file2.o加入到my_library.a这个函数库文件中,如果my_library.a不存在
的文件。在用ar命令创建静态库函数的时候,还有其他一些可以选择的参数,可以参加ar的使用帮助。这里不再赘
静态函数库,你可以使用它了。你可以把它作为你编译和连接过程中的一部分用来生成你的可执行代码。如果你用g
,你可以用“-l”参数来指定这个库函数。你也可以用ld来做,使用它的“-l”和“-L”参数选项。具体用法,可以参考in
库
库中的函数是在当一个可执行程序在启动的时候被加载。如果一个共享函数库正常安装,所有的程序在重新运行的时
数库中的函数。对于Linux系统还有更多的可以实现的功能:
库但是仍然允许程序使用老版本的函数库。 o 当执行某个特定程序的时候可以覆盖某个特定的库或者库中指定的函
的过程中修改这些函数库。
约定
写的共享函数库支持所有有用的特性,你在编写的过程中必须遵循一系列约定。你必须理解库的不同的名字间的区别
real
区别和它们是如何相互作用的。你同样还要知道你应该把这些库函数放在你文件系统的什么位置等等。下面我们具体
库的命名
函数库都有个特殊的名字,称作“soname”。Soname名字命名必须以“lib”作为前缀,然后是函数库的名字,然后
。不过有个特例,就是非常底层的C库函数都不是以lib开头这样命名的。
函数库都有一个真正的名字(“real name”),它是包含真正库函数代码的文件。真名有一个主版本号,和一个发行
号是可选的,可以没有。主版本号和发行版本号使你可以知道你到底是安装了什么版本的库函数。
个名字是编译器编译的时候需要的函数库的名字,这个名字就是简单的soname名字,而不包含任何版本号信息。
库的关键是区分好这些名字。当可执行程序需要在自己的程序中列出这些他们需要的共享库函数的时候,它只要用s
要创建一个新的共享函数库的时候,你要指定一个特定的文件名,其中包含很细节的版本信息。当你安装一个新版本
将这些
贝到一些特定的目录中,运行ldconfig这个实用就可以。Ldconfig检查已经存在的库文件,然后创建soname的符
时设置/etc/ld.so.cache这个缓冲文件。这个我们稍后再讨论。
并不设置链接的名字,通常
装过程中完成这个链接名字的建立,一般来说这个符号链接就简单的指向最新的soname
的函数库文件。最好把这个符号链接指向soname,因为通常当你升级你的库函数的后,你就可以自动使用新版本的
例看看:
readline.so.3
完整的soname,ldconfig可以设置一个符号链接到其他某个真正的函数库文件,例如是
adline.so.3.0。同时还必须有一个链接名字,例如/usr/lib/libreadline.so
链接指向/usr/lib/libreadline.so.3。
系统中函数库文件的位置
文件必须放在一些特定的目录里,这样通过系统的环境变量设置,应用程序才能正确的使用这些函数库。大部分的源
准,我们可以看info帮助文件获得相信的说明,info信息的位置是:info:
irectory_Variables。GNU标准建议所有的函数库文件都放在/usr/local/lib目录下,而且建议命令
放在/usr/local/bin目录下。这都是一些习惯问题,可以改变的。
层次化标准FHS(Filesystem Hierarchy Standard)(
pathname.com/fhs
个发行包中大部分的函数库文件应该安装到/usr/lib目录 下,但是如果某些库是在系统启动的时候要加载的,则放
统本身一部分的库则放到/usr/local/lib下面。
路径的不同并没有本质的冲突。GNU提出的标准主要对于开发者开发源码的,而FHS的建议则是针对发行版本的路
看/etc/ld.so.conf里面的配置信息。
库如何使用
glibc的系统里,包括所有的linux系统,启动一个ELF格式的二进制可执行文件会自动启动和运行一个program
Linux系统,这个loader的名字是/lib/ld-linux.so.X(X是版本号)。这个loader启动后,反过来就会
他本程序要使用的共享函数库。
些目录里查找共享函数库呢?这些定义缺省的是放在
nf文件里面,我们可以修改这个文件,加入我们自己的一些
求。大多数RedHat系列的发行包的/etc/ld.so.conf文件里面不包括/usr/local/lib这个目录,如果没有这个目
可以修改/etc/ld.so.conf,自己手动加上这个条目。
覆盖某个库中的一些函数,用自己的函数替换它们,同时保留该库中其他的函数的话,你可以在/etc/ld.so.preload
结尾的文件),这些preloading的库函数将有优先加载的权利。
的时候搜索所有的目录显然会效率很低,于是Linux系统实际上用的是一个高速缓冲的做法。Ldconfig缺省情况下
nf相关信息,然后设置适当地符号链接,然后写一个cache到/etc/ld.so.cache这个文件中,而这个
che则可以被其他程序有效的使用了。这样的做法可以大大提高访问函数库的速度。这就要求每次新增加一个动态加
dconfig来更新这个cache,如果要删除某个函数库,或者某个函数库的路径修改了,都要重新运行ldconfig来更
的一些包管理器在安装一个新的函数库的时候就要运行ldconfig。
eBSD使用cache的文件不一样。FreeBSD的ELF cache是/var/run/ld-elf.so.hints,而a.out的cache责是
o.hints。它们同样是通过ldconfig来更新。
变量
环境变量控制着一些关键的过程。例如你可以临时为你特定的程序的一次执行指定一个不同的函数库。Linux系统中
_PATH就是可以用来指定函数库查找路径的,而且这个路径通常是在查找标准的路径之前查找。这个是很有用的,
,或者在特殊的场合使用一个肥标准的函数库的时候。环境变量LD_PRELOAD列出了所有共享函数库中需要优先加
eload类似。这些都是有/lib/ld-linux.so这个loader来实现的。值得一提的是,
_PATH可以在大部分的UNIX-linke系统下正常起作用,但是并非所有的系统下都可以使用,例如HP-UX系统下
这个变量,而在AIX下则使用LIBPATH这个变量。
ARY_PATH在开发和调试过程中经常大量使用,但是不应该被一个普通用户在安装过程中被安装程序修改,大家可
visi.com/~barr/ldpath.html
档专门介绍为什么不使用LD_LIBRARY_PATH这个 变量。
有更多的环境变量影响着程序的调入过程,它们的名字通常就是以LD_或者RTLD_打头。大部分这些环境变量的使
得人头昏眼花的,如果要真正弄清楚它们的用法,最好去读loader的源码(也就是gcc的一部分)。
制动态链接函数库将涉及到setuid/setgid这个函数如果特殊的功能需要的话。因此,GNU
制或者忽略用户对这些变量使用setuid和setgid。如果loader通过判断程序的相关环境变量判断程序的是否使用
tgid,如果uid和euid不同,或者gid和egid部一样,那么loader就假定程序已经使用了setuid或者
就大大的器控制这个老链接的权限。如果阅读GNU
源码,就可以清楚地看到这一点,特别的我们可以看elf/rtld.c和sysdeps/generic/dl-sysdep.c这两
意味着如果你使得uid和gid与euid和egid分别相等,然后调用一个程序,那么这些变量就可以完全起效。
共享函数库
始学习如何创建一个共享函数库。其实创建一个共享函数库非常容易。首先创建object文件,这个文件将加入通过
到共享函数库里面。PIC的意思是“位置无关代码”(Position Independent Code)。下面是一个标准的格式:
-Wl,-soname,your_soname -o library_name file_list library_list
一个例子,它创建两个object文件(a.o和b.o),然后创建一个包含a.o和b.o的共享函数库。例子中”-g”和“-
-c -Wall a.cgcc -fPIC -g -c -Wall b.cgcc -shared -Wl,
usterstuff.so.1 -o liblusterstuff.so.1.0.1 a.o b.o -lc
些需要注意的地方:
t-frame-pointer这个编译参数除非你不得不这样。虽然使用了这个参数获得的函数库仍然可以使用,但是这使得
跟踪调试。 · 使用-fPIC来产生代码,而不是-fpic。 · 某些情况下,使用gcc
文件,需要使用“-Wl,-export-dynamic”这个选项参数。通常,动态函数库的符号表里面包含了这些动态的对象的
建ELF格式的文件时候,会将所有的符号加入到动态符号表中。可以参考ld的帮助获得更详细的说明。
和使用共享函数库
一个共享函数库,你还需要安装它。其实简单的方法就是拷贝你的库文件到指定的标准的目录(例如/usr/lib),然后
权限去做这件事情,例如你不能修改/usr/lib目录,那么你就只好通过修改你的环境变量来实现这些函数库的使用了
函数库;然后,设置一些必须得符号链接,特别是从soname到真正的函数库文件的符号链接,简单的方法就是运
rectory_with_shared_libraries
可以设置你的LD_LIBRARY_PATH这个环境变量,它是一个以逗号分隔的路径的集合,这个可以用来指明共享函数
sh,就可以这样来启动一个程序my_program:
_PATH=.:$LD_LIBRARY_PATH my_program
的是重载部分函数,则你就需要创建一个包含需要重载的函数的object文件,然后设置LD_PRELOAD环境变量。
的函数库,如果某个API改变了,创建库的程序会改变soname。然而,如果一个函数升级了某个函数库而保持了原来
的函数库拷贝到某个位置,然后重新命名这个文件(例如使用原来的名字,然后后面加.orig后缀),然后创建一个小
函数和相关的东西。例如下面的例子:
port LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH exec
program.orig $*
通过运行ldd来看某个程序使用的共享函数库。例如你可以看ls这个实用工具使用的函数库:
p.so.2 => /lib/libtermcap.so.2 (0x4001c000)
=> /lib/libc.so.6 (0x40020000)
ux.so.2 => /lib/ld-linux.so.2 (0x40000000)
可以看到一个soname的列表,包括路径。在所有的情况下,你都至少可以看到两个库:
.so.N(N是1或者更大,一般至少2)。
加载其他所有的共享库的库。
应该大于或者等于6)。这是C语言函数库。
是,不要在对你不信任的程序运行ldd命令。在ldd的manual里面写得很清楚,ldd是通过设置某些特殊的环境变
设置LD_TRACE_LOADED_OBJECTS),然后运行这个程序。这样就有可能使得某地程序可能使得ldd来执行某
不安全的隐患。
函数库
新版的函数库要和老版本的二进制的库不兼容,则soname需要改变。对于C语言,一共有4个基本的理由使得它
:
数的行文改变了,这样它就可能与最开始的定义不相符合。
数据项改变了。
出的函数删除了。
出函数的接口改变了。
避免这些地方,你就可以保持你的函数库在二进制代码上的兼容,或者说,你可以使得你的程序的应用二进制接口(AB
ace)上兼容。
载的函数库Dynamically Loaded (DL) Libraries
函数库Dynamically loaded (DL)
类函数库,它可以在程序运行过程中的任何时间加载。它们特别适合在函数中加载一些模块和plugin扩展模块的场
个plugin模块时才动态的加载。例如,Pluggable Authentication
)系统就是用动态加载函数库来使得管理员可以配置和重新配置身份验证信息。
统下,DL函数库与其
式上没有特殊的区别,我们前面提到过,它们创建的时候是标准的object格式。主要的区别就是
是在程序链接的时候或者启动的时候加载,而是通过一个API来打开一个函数库,寻找符号表,处理错误和关闭函数
要包
。
使用的函数和Solaris中一样,都是dlpoen()
是所有的平台都使用同样的接口,例如HP-UX使用shl_load()机制,而Windows平台用另外的其他的调用接口。
码有很强的移植性,你应该使用一些wrapping函数库,这样的wrapping函数库隐藏不同的平台的接口区别。一种
的对动态加载模块的支持,它使用一些潜在的动态加载函数库界面使得它们可以夸平台使用。具体可以参考http:
gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html.
是使用libltdl,是GNU libtool的一部分,可以进一步参考CORBA相关资料。
en()
数打开一个函数库然后为后面的使用做准备。C语言原形是:
n(const char *filename, int flag);
名filename是以“/”开头,也就是使用绝对路径,那么dlopne就直接使用它,而不去查找某些环境变量或者系统设
否则dlopen()
下面的次序查找函数库文件:
D_LIBRARY指明的路径。 2. /etc/ld.so.cache中的函数库列表。 3. /lib目录,然后/usr/lib。不过一些很老的a
的次序,也就是先查/usr/lib,然后是/lib。
数中,参数flag的值必须是RTLD_LAZY或者RTLD_NOW,RTLD_LAZY的意思是resolve
mbols as code from the dynamic library is
RTLD_NOW的含义是resolve all undefined symbols before dlopen()
ail if this cannot be done'。
几个函数库,它们之间有一些依赖关系的话,例如X依赖Y,那么你就要先加载那些被依赖的函数。例如先加载Y,
)函数的返回值是一个句柄,然后后面的函数就通过使用这个句柄来做进一步的操作。如果打开失败dlopen()就返
库被多次打开,它会返回同样的句柄。
函数库里面有一个输出的函数名字为_init,那么_init就会在dlopen()这个函数返回前被执行。我们可以利用这个
些初始化的工作。我们后面会继续讨论这个问题的。
ror()
dlerror()函数,我们可以获得最后一次调用dlopen(),dlsym(),或者dlclose()的错误信息。
载了一个DL函数库而不去使用当然是不可能的了,使用一个DL函数库的最主要的一个函数就是dlsym(),这个函
里面查找给定的符号。这个函数如下定义:
(void *handle, char *symbol);
参数handle就是由dlopen打开后返回的句柄,symbol是一个以NIL结尾的字符串。
()函数没有找到需要查找的symbol,则返回NULL。如果你知道某个symbol的值不可能是NULL或者0,那么就
根据这个返回结果判断查找的symbol是否存在了;不过,如果某个symbol的值就是NULL,那么这个判断就有问
or(),清除以前可能存在的错误,然后调用dlsym()来访问一个symbol,然后再调用dlerror()来判断是否出
的过程如下:
clear error code */
ype) dlsym(handle, symbol_being_searched_for);
rror()) != NULL)
or, the symbol wasn't found */
und, its value is in s */
se()
数的反过程就是dlclose()函数,dlclose()函数用力关闭一个DL函数库。Dl函数库维持一个资源利用的计数
lose的时候,就把这个计数器的计数减一,如果计数器为0,则真正的释放掉。真正释放的时候,如果函数库里面
用_fini()这个函数,做一些必要的处理。Dlclose()返回0表示成功,其他非0值表示错误。
ibrary Example
个例子。例子中调入math函数库,然后打印2.0的余弦函数值。例子中每次都检查是否出错。应该是个不错的范例
argc, char **argv)
dle;
cosine)(double);
or;
dlopen (\"/lib/libm.so.6\
e) {
dlerror(), stderr);
;
dlsym(handle, \"cos\");
= dlerror()) != NULL)
error, stderr);
;
%f \
andle);
程序名字叫foo.c,那么用下面的命令来编译:
oo.c -ldl
命令
以列出一个函数库文件中的符号表。它对于静态的函数库和共享的函数库都起作用。对于一个给定的函数库,nm命
包括每个符号的值和类型。还可以给出在原程序中这个函数(符号)是在多少行定义的,不过这必须要求编译该函数
类型,这里我们再多讨论一下。符号的类型是以一个字母的形式显示的,小写字母表示这个符号是本地(local)的,
局的(global,externel)。一般来说,类型有一下几种:T、D、B、U、W。各自的含义如下:T表示在代码段中定
时初始化过的数据段;B表示初始化的数据段;U表示没有定义的,在这个库里面使用了,但是在其他库中定义的符
如
中也有对这个符号的定义,则其他符号的定义可以覆盖这个定义。
道一个函数的名字,但是你不知道这个函数在什么库中定义的,那么可以用mn的“-o”选项和grep命令来查找库的
一行都有这个函数库文件名。例如,你要查找“cos”这个是在什么地方定义的,大致可以用下面的命令:
/usr/lib/* /usr/lib/*/* /usr/local/lib/* 2> /dev/null
的更详细的用法我们可以参考info文档,位置是info:binutils#nm。
函数_init和_fini
有两个特殊的函数,_init和_fini,这个我们在前面已经说过了。主要是分别用来初始化函数库和关闭的时候做一些
己认为需要的代码放到这两个函数里面,它们分别在函数库被加载和释放的时候被执行。具体说,如果一个函数库里
么在第一次通过dlopen()函数打开这个函数库,或者只是简单的作为共享函数库被打开的时候,_init函数被自动调
数,当一个程序调用dlclose()去释放对这个函数库的引用的时候,如果该函数库的被引用计数器为0了,或者这个
被使用而使用它的程序正常退出的时候,_fini就会被调用执行。C语言定义它们的原型如下:
d); void _fini(void);
编译源程序为“.o”文件的时候,需要加一个“-nostartfiles”选项。这个选项使得C编译器不链接系统的启动函数库里
到一个“multiple-definition”的错误。
函数库也可以使脚本(Scripts)
ader允许使用特殊格式的脚本语言来写一个函数库。这对于那些需要间接包含其他函数库的情况还是有用的。例如
so的例子:
ript Use the shared library, but some functions are only in
ary, so try that secondarily. */GROUP ( /lib/libc.so.6
nonshared.a )
息可以参考texinfo文档中关于ld链接的脚本部分。一般的信息还可以参考: info:ld#Options 和info:ld#Comm
Option Commands。
libtool
编译的系统相很方便的移植到其他操作系统下,你可以使用GNU libtool来创建和安装这个函数库。GNU
函数库支持的典型的脚本。Libtool隐藏了使用一个可移植的函数库的负责性。Libtool提供了一个可以移植的界面
链接函数库(静态或者共享的),并且安装这些库。它还包含了libltdl,一个可移植的动态函数库调入程序的wra
以在
gnu.org/software/libtool/manual.html
一些符号
产的文件中很多符号都是为了debug而包含的,占用了不少空间。如果空间不够,而且这些符号也许不再需要,就
就是先正常的生成你需要的object文件,然后debug和测试你需要的一些东西。一旦你完全测试完毕了,就可以用
的符号了。Strip命令可以使你很方便的控制删除什么符号,而保留什么符号。Strip的具体用法可以参考其帮助文
法就是使用GNU ld的选项“-S”和“-s”;“-S”会删除一些debugger的符号,而“-s”则是将所有的符号信息都删除。
样的参数“-Wl,-S”和“-Wl,-s”来达到这个目的。
,例子中我们会使用三种函数库(静态的、共享的和动态加载的函数库)。文件libhello.c是一个函数库,libhello
;demo_use.c则是一个使用了libhello函数库的。Script_static和script_dynamic分别演示如何以
式使用函数库,而后面的demo_dynamic.c和script_dynamic则表示演示如何以动态加载函数库的方式来使用它
17:38:37)
例子
例子,例子中我们会使用三种函数库(静态的、共享的和动态加载的函数库)。文件libhello.c是一个函数库,
它的头文件;demo_use.c则是一个使用了libhello函数库的。Script_static和
mic分别演示如何以静态和共享方式使用函数库,而后面的demo_dynamic.c和script_dynamic则表示演示
载函数库的方式来使用它。
libhello.c
- demonstrate library use. */
id)
library world.
libhello.h
- demonstrate library use. */
id);
demo_use.c
.c -- demonstrate direct use of the \"hello\" routine */
hello.h\" )
script_static
ry demo
tic library's object file, libhello-static.o.
he name libhello-static to clearly
te the static library from the
brary examples, but you don't need to use
the names of your
or static libraries.
-c -o libhello-static.o libhello.c
tic library.
o-static.a libhello-static.o
nt we could just copy libhello-static.a
e else to use it.
purposes, we'll just keep the library
ent directory.
emo_use program file.
-c demo_use.c -o demo_use.o
mo_use program; -L. causes \".\" to be searched during
the program. Note that this command causes
nt object file in libhello-static.a to be
ed into file demo_use_static.
mo_use_static demo_use.o -L. -lhello-static
e program.
static
script_shared
rary demo
red library's object file, libhello.o.
all -g -c libhello.c
red library.
ink it against C library, since libhello
n the C library.
d -Wl,-soname,libhello.so.0 –o libhello.so.0.0 libhello.o –lc
nt we could just copy libhello.so.0.0 into
tory, say /usr/local/lib.
eed to call ldconfig to fix up the symbolic links.
soname. We could just execute:
llo.so.0.0 libhello.so.0
t ldconfig figure it out.
g -n .
linker name.
sophisticated setting, we'd need to make
f there was an existing linker name,
check if it should stay or not.
.so.0 libhello.so
emo_use program file.
-c demo_use.c –o demo_use.o
gram demo_use.
uses \".\" to be searched during creation
gram; note that this does NOT mean that \".\"
rched when the program is executed.
mo_use demo_use.o -L. -lhello
e program. Note that we need to tell the program
shared library is, using LD_LIBRARY_PATH.
_PATH=\".\" ./demo_use
demo_dynamic.c
namic.c -- demonstrate dynamic loading and
ello\" routine */
n.h for the routines to
oad libraries */
we don't have to include \"libhello.h\".
e do need to specify something related;
specify a type that will hold the value
to get from dlsym(). */
simple_demo_function\" describes a function that
guments, and returns no value: */
(*simple_demo_function)(void); )
error;
e;
o_function demo_function;
mically loaded library */
open(\"libhello.so\
rr, \"Couldn't open libhello.so: %s
ol */
on = dlsym(module, \"hello\");
lerror()))
rr, \"Couldn't find hello: %s
he function in the DL library */
tion)();
close things cleanly */
ule);
script_dynamic
ly loaded library demo
hat libhello.so and friends have
ed (see dynamic example).
emo_dynamic program file into an object file.
-c demo_dynamic.c
gram demo_use.
we don't have to tell it where to search for DL libraries,
nly special library this program uses won't be
il after the program starts up.
we DO need the option -ldl to include the library
the DL libraries.
mo_dynamic demo_dynamic.o -ldl
e program. Note that we need to tell the
here get the dynamically loaded library,
LIBRARY_PATH.
_PATH=\".\" ./demo_dynamic
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务