Linux库文件

来源:互联网 发布:手机淘宝抢拍技巧 编辑:程序博客网 时间:2024/06/07 14:22

1. 什么是库

在windows平台和linux平台下都存在着大量的库。

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

由于windows和linux的本质不同,因此二者库的二进制是不兼容的。

2. 库的种类

linux下的库有两种:静态库和共享库(动态库)。

二者的不同点在于代码被载入的时刻不同。

静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

对于静态库和动态库的选择,需要结合二者的优缺点折中考虑。一般来说,比较通用的库,应该做成共享库。

3. 库存在的意义

库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。

现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。共享库的好处是,不同的应用程序如果调用相同的库,那么 在内存里只需要有一 份该共享库的实例。

4. 库文件在linux下是如何生成的

静态库的后缀是.a,它的产生分两步

Step 1:由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表;

Step 2:ar命令将很多.o转换成.a,成为静态库;

动态库的后缀是.so,它由gcc加特定参数编译产生。例如:
gccfPICc.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.可执行程序在执行的时候如何定位共享库文件

静态库:生成可执行文件时,静态库已经作为自身一部分链接进了可执行文件中,故执行时不需要再定位,也就是说再不依赖于库文件;

动态库:需要知道动态库的路径,参考另一篇博客;

8.在新安装一个库之后如何让系统能够找到他

如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:

  1. 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径;

  2. 运行ldconfig,该命令会重建/etc/ld.so.cache文件;

  3. ldconfig命令需要root权限;

库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的。

一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选其一使用:

  1. 在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。

例如:export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH

  2. 在/etc/ld.so.conf 文件中添加库的搜索路径(需要root权限)。

   将自己可能存放库文件的路径都加入到/etc/ld.so.conf中是明智的选择添加方法也极其简单,将库文件的绝对路径直接写进去就OK了,一行一个。

例如:

   /usr/X11R6/lib

   /usr/local/lib

   /opt/lib

需要注意的是:第二种搜索路径的设置方式对于程序连接时的库(包括共享库和静态库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是因为为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令要以 root 权限执行)。因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中进行了库搜索路径的设置之后,还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf列出的路径下的库文件缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib),或者修改ld.so.conf增加新的库路径后,需要运行一下/sbin/ldconfig使所有的库文件都被缓存到ld.so.cache中,如果没做,即使库文件明明就在/usr/lib下的,也是不会被使用的,结果编译过程中抱错,缺少xxx库,去查看发现明明就在那放着,让人觉得很诡异。

在程序连接时,对于库文件(静态库和共享库)的搜索路径,除了上面的设置方式之外,还可以通过 -L 参数显式指定。因为用 -L 设置的路径将被优先搜索,所以在连接的时候通常都会以这种方式直接指定要连接的库的路径。

第二种设置方式需要 root 权限,以改变 /etc/ld.so.conf 文件并执行 /sbin/ldconfig 命令。而且,当系统重新启动后,所有的基于GTK2的程序在运行时都将使用新安装的GTK+ 库。不幸的是,由于 GTK+ 版本的改变,这有时会给应用程序带来兼容性的问题,造成某些程序运行不正常。为了避免出现上面的这些情况,在 GTK+及其依赖库的安装过程中对于库的搜索路径的设置将采用第一种方式进行。这种设置方式不需要root权限,设置也简单。

因为我是通过终端登陆到服务器上工作的(做自己的private build),没有root权限,所以第一种设置路径的方法自然成了我的选择。我想,对于和我一样在集成环境下工作的同学,使用第一种方法就可以很方便的解决问题。当然,在客户那儿部署最终的Release产品时,可以采用第二种方法。

库文件的创建和使用,通过具体的例子来介绍。
1. 准备源文件
建立一个新目录libtest,在libtest下新建两个目录a和so,a和so目录下均有cacl.h cacl.C test_cacl.C三个文件,内容如下:

#ifndef CACL_H   #define CACL_H    int Add(int nLeft, int nRight);  #endif   ****************************************************************************************************************************************      cacl.C#include <stdio.h>   int Add(int nLeft, int nRight)  {      return nLeft + nRight;  }   ****************************************************************************************************************************************    test_cacl.C#include "cacl.h"   #include <stdio.h>   int main()  {      int nA   = 100;      int nB   = 200;      int nRev = Add(nA, nB);      printf("The sum is %d\n", nRev);      return 0;  }  
  1. 静态库的创建和使用
    (1) 在a目录下,编译生成cacl.o文件;
    g++ -c cacl.C

    (2) 在a目录下,使用ar命令封装生成静态库文件libcacl.a;
    ar crv libcacl.a cacl.o
    静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a

    (3) 在a目录下,编译连接libcacl.a生成测试程序;
    g++ -o testcacl test_cacl.C -L. -lcacl

    (4) 在a目录下,可以正确运行testcacl,即使删除了libcacl.a文件(正是静态库的特点);

  2. 动态库的创建和使用
    (1) 在so目录下,编译生成cacl.o文件;
    g++ -fPIC -c cacl.C
    P.S.此处编译参数 -fPIC 一定不能省略,否则下一步将会失败;因为g++默认生成的.o文件是不带-fPIC选项,即生成的是静态链接文件,故下一步封装 生成动态库时会失败。

    (2) 在so目录下,使用ar命令生成静态库文件libcacl.so;
    g++ -shared -fPIC -o libcacl.so cacl.o
    动态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.so

    (3) 在so目录下,编译连接libcacl.a生成测试程序;
    g++ -o testcacl test_cacl.C -L. -lcacl

    (4) 在so目录下,可以正确运行testcacl;

原文链接:
http://www.linuxidc.com/Linux/2012-03/57023p3.htm

0 0