• linux下的库入门


    一、什么是库

           在 linux 平台存在着大量的库,库的本质是一种可执行的二进制代码(但不可以独立执行)集合,可以通过操作系统将其载入内存执行。windows 和 linux 的平台的差异性(预编译、编译器、汇编器和链接器的不同),因此二者库的二进制版本也是无法兼容。

    二、 库的种类

      linux 下的库有两种:静态库和动态库(共享库),他们的主要差别在被调用者调用时时代码被载入的时机不同。

      静态库的特征:1、以.a为后缀;2、前缀名以lib开始;3、生成的可执行程序体积较大;4、代码在编译过程中就会被加载进可执行程序程序中。

      共享库(动态库)的特征:1、用.so为后缀;2、前缀名以lib开始;3、生成的可执行程序代码体积较小;4、代码是在可执行程序运行中调用时才载入内存的,在编译过程中仅简单的引用。

      共享库(动态库)的优势: 若在不同的应用程序中如果调用相同的库,那么只会在内存里存在一份共享库的实例即可;可以在系统中存在库的多个版本。使用者需要自己搞定共享库问题。

      静态库的优势:若在不同的应用程序中如果调用相同的库,那么会在内存里存在多份共享库的实例;无需考虑库的问题。

          为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。

          ln -s libhello.so.1.31 libhello.so.1 

          ln -s libhello.so.1 libhello.so

    代码如下:

    #vector.h 
    
    1 #ifndef vector_h
     2 #define vector_h
     3 
     4 void addVec(int *xP, int *yP, int *zP, int Num);
     5 void mulVec(int *xP, int *yP, int *zP, int Num);                                        
     6 
     7 #endif
    
    #addVec.c
    
     1 #include "vector.h"
     2                                                                                         
     3 void addVec(int *xP, int *yP, int *zP, int Num){
     4     for(int i = 0; i < n; i++){
     5         zP[i] = xP[i] + yP[i];
     6     }
     7 
     8     return;
     9 }
    ~   
    
    #mulVec.c
    
     1 #include "vector.h"                                                                     
     2 
     3 void mulVec(int *xP, int *yP, int *zP, int Num){
     4     for(int i = 0; i < n; i++){
     5         zP[i] = xP[i] * yP[i];
     6     }
     7 
     8     return;
     9 }
    
    
    #testVec.c
    
     1 #include <stdio.h>                                                                      
     2 #include "vector.h"
     3 
     4 int x[2] = {1, 2};
     5 int y[2] = {3, 4};
     6 int z[2];
     7 
     8 int main(int argc, char **argv)
     9 {
    10     addVec(x, y, z, 2);
    11     printf("z = [%d %d]
    ", z[0],  z[1]);
    12 
    13     return 0;
    14 }

    三、生成静态库文件:

      1、gcc -Og -c *Vec.c            //生成目标文件

      2、ls *.o  或  ls | grep .o             //查看目标文件

      3、ar crs libVector.a addVec.o mulVec.o       //生成静态库文件

      4、ls *.a                   //查看生成的库文件

      5、file libVector.a                  //查看文件类型

      6、ar -t libVector.a                //查看文件内容

    四、动态库的生成:

      1、gcc -shared -fPIC -o libVector.so addVec.c mulVec.c     //生成动态库文件

      2、ls *.so  或  ls | grep .so                  //查看目标文件

      3、file libVector.a                       //查看文件类型

      4、ldd libVector.so                     //查看生成的库文件

      5、nm libVector.so                     //查看生成的库文件包含哪些函数 

    五、库文件的其他

    1、库文件的规范: linux中,库文件常放在/usr/lib和/lib下, 其中静态库名字常为libxxxx.a,其中xxxx是该库文件的名称;动态库的名字常为libxxxx.so,xxxx 是该库的名称,有的库会有主副等版本号

    2、定位共享库的时机 :当系统加载可执行代码(即库文件)的时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径,此时就需要系统动态载入器(dynamic linker/loader) ,对linux下的elf 格式的可执行程序,是由 ld-linux.so* 来完成的,它先后搜索 elf 文件的 DT_RPATH 段-->环境变量LD_LIBRARY_PATH—->/etc/ld.so.cache 文件列表--> /lib/,/usr/lib 目录找到库文件后将其载入内存。如: export LD_LIBRARY_PATH=’pwd’ ,将当前文件目录添加为共享目录。

    3、使用ldd工具,查看可执行程序依赖那些动态库或着动态库依赖于那些动态库:

       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 库  
    1.7、使用nm工具,查看静态库和动态库中有那些函数名;
        (T类表示函数是当前库中定义的,U类表示函数是被调用的,在其它库中定义的,W类是当前库中定义,被其它库中的函数覆盖)。
        有时候可能需要查看一个库中到底有哪些函数,nm工具可以打印出库中的涉及到的所有符号,这里的库既可以是静态的也可以是动态的。

      nm列出的符号有很多, 常见的有三种::

    T类:是在库中定义的函数,用T表示,这是最常见的;

    U类:是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;

    W类:是所谓的“弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。

    例如,假设开发者希望知道上文提到的hello库中是否引用了 printf():

       nm libhello.so | grep printf 

    发现printf是U类符号,说明printf被引用,但是并没有在库中定义。

    由此可以推断,要正常使用hello库,必须有其它库支持,使用ldd工具查看hello依赖于哪些库:

    ldd libhello.so

    libc.so.6=>/lib/libc.so.6(0x400la000)

    /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)

    从上面的结果可以继续查看printf最终在哪里被定义,有兴趣可以深入研究

     

    1.8、使用ar工具,可以生成静态库,同时可以查看静态库中包含那些.o文件,即有那些源文件构成。

    可以使用 ar -t libname.a 来查看一个静态库由那些.o文件构成。

    可以使用 ar q libname.a xxx1.o xxx2.o xxx3.o ... xxxn.o 生成静态库

     

    1.9、file查看动态库和静态库是32位,还是64位下的库:

    如果是动态库,可以使用file *.so;

    如果是静态哭,可以使用objdump -x *.a 

     
  • 相关阅读:
    【leetcode】1230.Toss Strange Coins
    2018.12.25 SOW
    L203 词汇题
    L202
    L201
    L200
    2018
    2018.12.21 Cmos- RF
    L198
    L196 Hospital educations
  • 原文地址:https://www.cnblogs.com/guochaoxxl/p/14165564.html
Copyright © 2020-2023  润新知