关于linux下的共享库(动态库)和静态库

1.什么是库
windows平台和linux平台下都大量存在着库。
质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
由于windowslinux的本质不同,因此二者库的二进制是不兼容的
本文仅限于介绍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.minorxxxx是该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文件

  

############################################################

  

 linux中编译静态库(.a)和动态库(.so)的基本方法

 

静态库 
 

linux环境中, 使用ar命令创建静态库文件.如下是命令的选项:
          d -----
从指定的静态库文件中删除文件

          m -----
把文件移动到指定的静态库文件中

          p -----
把静态库文件中指定的文件输出到标准输出

          q -----
快速地把文件追加到静态库文件中

          r -----
把文件插入到静态库文件中

          t -----
显示静态库文件中文件的列表

          x -----
从静态库文件中提取文件

     
还有多个修饰符修改以上基本选项,详细请man ar 以下列出三个
:
          a -----
把新的目标文件(*.o)添加到静态库文件中现有文件之后

          b -----***************************************
之前

          v -----
使用详细模式

ar 命令的命令行格式如下:
      ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...
参数archive定义库的名称, files是库文件中包含的目标文件的清单, 用空格分隔每个文件
.
 

比如创建一个静态库文件的命令如下:
      ar r libapue.a error.o errorlog.o lockreg.o
这样就了libapue.a静态库文件, 可以用 t 选项显示包含在库中的文件
 
创建库文件之后,可以创建这个静态库文件的索引来帮助提高和库连接的其他程序的编译速度

使用ranlib程序创建库的索引,索引存放在库文件内部.
      ranlib libapue.a
 

nm程序显示存档文件的索引,它可以显示目标文件的符号
nm libapue.a | more
如果是显示目标文件的符号
:
nm error.o | more
如何使用呢?如下所示
:
gcc -o test test.c libapue.a
这样就可以在test.c中调用在libapue.a中的函数了.

  

 

动态库


1.
创建共享库

     gcc -shared -o libapue.so error.o errorlog.o
这样就创建了共享库
!
2.
编译共享库

   
假设共享库位于当前目录(即跟程序文件相同的目录中
)
gcc -o test -L. -lapue test.c
这样就编译出了不包含函数代码可执行文件了,但是但你运行时会发现linux动态加载器找不到libapue.so文件
.
可以用ldd 命令查看可执行文件依赖什么共享库
:
ldd test
如何才能让动态加载器发现库文件呢?有两种方法可以解决

    
1.环境变量
       export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:."
    2.
修改/etc/ld.so.conf文件.

  

一般应用程序的库文件不与系统库文件放在同一个目录下,一般把应用程序的共享库文件放在/usr/local/lib,新建一个属于自己的目录apue,然后把刚才libapue.so复制过去就行了
同时/etc/ld.so.conf中新增一行
:
/usr/local/lib/apue


以后在编译程序时加上编译选项
:
-L /usr/local/lib/apue -lapue

 

/*

参数的配置通过man gcc可以看到

-llibrary

              连接名为 library 库文件. 

              连接器 标准搜索目录 寻找 这个 库文件, 库文件 真正  

              liblibrary.a.  连接器当做文件名这个文件.

 

              搜索目录 除了 一些 系统标准目录 , 还包括 用户 -L 选项路径.

   add by alphajay

*/

  

 

这样就可以使用这个libapue.so共享库了!!
全文结束
!!

你可能感兴趣的:(关于linux下的共享库(动态库)和静态库)