分享

静态库&动态库

 guoliangyu 2012-12-03

linux下的共享库和静态库  

(1)linux下文件的类型是不依赖于其后缀名的,但一般来讲:
  .o,是目标文件。
  .so 为共享库,是shared object,用于动态连接的。
  .a为静态库,是好多个.o合在一起,用于静态连接。
(2)静态库的生成和使用
 概述静态库文件的扩展名一般为.a,其编写步骤很简单。
    ⑴编写函数代码
    ⑵编译生成各目标文件
    ⑶用ar文件对目标文件归档,生成静态库文件。
    注意归档文件名必须以lib打头。
    使用要点:
       ⑴在gcc 的-I参数后加上静态库头文件的路径。
       ⑵在gcc 的-L参数后加上库文件所在目录
       ⑶在gcc 的-l参数后加上库文件名,但是要去掉lib和.a扩展名。比如库文件名是    libtest.a 那么参数就是 -l test
细节:静态库的后缀是.a,它的产生分两步:
Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表。
Step 2.ar命令将很多.o转换成.a,成文静态库。
例如生成静态库 :库名 libmylib.a
gcc -c mylib.c -o mylib.o 
ar rcs libmylib.a mylib.o
将静态库copy到 /usr/lib/ 或/lib/ 目录下
cp libmylib.a /usr/lib/
静态库的使用
比如测试文件为test.c
gcc -0 test test.c -lmylib
-l为选项, mylib为库名。mylib为libmylib的中间部分,Linux下约定所有库都以前缀lib开始.在test.c中要包含头文件。
(3)动态库的生成和使用
1.生成步骤:
先写好头文件和程序文件,如mylib.h和mylib.c。

再编译下面命令把mylib.c程序创建成了一个动态库
(1)、gcc -fPIC -o mylib.o -c mylib.c
(2)、gcc -shared -o libtest.so mylib.o
也可以直接使用一条命令
gcc -fPIC -shared -o libtest.so mylib.c
由以上命令生成动态库libtest.so,为了不需要动态加载动态库,在命令时需以lib开头以.so为后缀。
–fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
–shared:指明编译成动态库。
-soname name 选项,可以指定 soname 是什么。
-o name 指定了共享对象的 real name。
-Wl选项把参数传递给连接器ld。
-lc选项,表示使用c语言库,一般都要用到。
总结就是g++/gcc -g -shared -Wl,-soname,lib***.so -o lib***.so.1.0.0 library1.o library2.o .... -lc 

2.使用动态库
在源程序中添加头文件,假设原程序名为test.c
编译命令:gcc test.c –ltest –o test
      或者
     gcc test.c /usr/lib/libtest.so -o test
这是把libtest.so 复制到了/usr/lib/,如果没有复制到该目录下就要用–L:指明动态库所在的目录。gcc中-l:指明动态库的名称,该名称是处在头lib和后缀.so中的名称,如上动态库libtest.so的l参数为-l test。

     测试:
     ldd test
     ldd 测试可执行文件所使用的动态库。
注意:引用动态库时,必须含有路径,如果只是使用libttt.so,则必须确保这个库所在目录包括再PATH 环境变量中 。
(4)动态库的显式调用
显式调用的含义是代码出现库文件名,用户需要自己去打开和管理库文件。其要点为:
⑴把dlfcn.h系统头文件包含进来
⑵用dlopen函数打开库文件,并指定打开方式:
   dllope的的第一个参数为共享库的名称,将会在下面位置查找指定的共享库:
    ①环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。
    ②文件/etc/ld.so.cache中找到的库的列表,由ldconfig命令刷新。
    ③目录usr/lib。
    ④目录/lib。
    ⑤当前目录。
  第二个参数为打开共享库的方式。有两个取值
    ①RTLD_NOW:将共享库中的所有函数加载到内存
    ②RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数
⑶用dlerror()函数测试是否打开成功,并进行错误处理;
⑷用dlsym()获得函数地址,存放在一个函数指针中
⑸用获得的函数指针进行函数调用。
⑹程序结束时用dlclose关闭打开的动态库,防止资源泄露。
⑺用ldconfig工具把动态库的路径加到系统库列表中.
---------------------------------------
1.什么是库在windows平台和linux平台下都大量存在着库。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
由于windows和linux的本质不同,因此二者库的二进制是不兼容的。
本文仅限于介绍linux下的库。
2.库的种类
linux下的库有两种:静态库和共享库。
二者的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
3.库存在的意义
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
4.库文件是如何产生的在linux下
静态库的后缀是.a,它的产生分两步
Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表
Step 2.ar命令将很多.o转换成.a,成文静态库
动态库的后缀是.so,它由gcc加特定参数编译产生。
例如:
$ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.
5.库文件是如何命名的,有没有什么规范
在linux下,库文件一般放在/usr/lib /lib下,
静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号
6.如何知道一个可执行程序依赖哪些库
ldd命令可以查看一个可执行程序依赖的共享库,
例如# ldd /bin/lnlibc.so.6
=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
=> /lib/ld- linux.so.2 (0×40000000)
可以看到ln命令依赖于libc库和ld-linux库
7.可执行程序在执行的时候如何定位共享库文件
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径
此时就需要系统动态载入器(dynamic linker/loader)
对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索
elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录
找到库文件后将其载入内存
8.在新安装一个库之后如何让系统能够找到他
如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
2.运行ldconfig,该命令会重建/etc/ld.so.cache文件
 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多