一、基本概念

Linux下的库有两种:静态库和动态库(又称共享库),.a表示静态库,.os表示动态库
两者的区别为载入到代码的时刻不同。静态库的代码在编译过程中就已经载入到可执行程序中,类似于头文件加载一般,产生的程序体积较大。动态库的代码是在可执行程序在运行的时候才载入到内存中,在编译中仅做一个简单的引用,因此生成的体积较小
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. 编译目标代码时指定的动态库搜索路径;
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
  4. 默认的动态库搜索路径/lib;
  5. 默认的动态库搜索路径/usr/lib。

    静态库

  • 优点:程序稳定,便于传播
  • 缺点:生成程序体积大,且更新主程序时需要全部重新编译链接,耗费时间长。
    静态库链接时搜索的路径顺序
  1. ld会去找GCC命令中的参数-L
  2. 再找gcc的环境变量LIBRARY_PATH
  3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

二、执行代码

静态库的使用

  1. 创建静态库

    $ar rcs libmyhello.a hello.o
    //ar rcs创建静态链接库命令
  2. 链接

    $gcc -o hello main.c -static -L. -lmyhello 
    //hello 指的是生成的可执行文件名
    //-static 创建静态链接库参数
    // -L.  静态链接库的位置
    //-lmyhello   -l部分是调用链接库的参数,myhello指的是静态链接库名

    动态库的使用

  3. 创建动态库

    $gcc -shared -fPIC -c hello.c
    $gcc -shared -fPIC -o libmyhello.so hello.o
    //“PIC”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。
  4. 重定位动态链接库
    如果直接执行第三步后运行程序会直接报错:
    error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
    原因是因为程序运行时找不到动态库文件的位置。有三种解决方法:

  • $sudo mv libmyhello.so /usr/lib //放入用户动态库中
  • $export LD_LIBRARY_PATH=$(pwd) //修改环境变量(指示动态连接器可以装载动态库的路径)
  • $sudo ldconfig ~/testso //ldconfig将制定目录下的动态链接库被系统共想起来 ,意即:在缓存文件/etc/ld.so.cache中追加进指定目录下的共享库.本例让系统共享了~/tests目录下的动态链接库。
  1. 编译链接
    $ gcc -o hello main.c -L. -lmyhello
    //-lmyhello   告诉GCC驱动程序在连接阶段引用共享函数库libmyhello.so  
    //-L.  (网上都说是告诉GCC函数库可能位于当前目录,但是实际上并不是这样)

    本篇文章大部分内容摘自 牛顿的小脑,侵删