静态链接库、动态链接库和动态加载库


静态链接库

前言

静态库是obj文件的一个集合(目标文件中通常仅解析了文件内部的变量和函数,对于引用的函数和变量还没有解析,这需要将引用进来,将没有解析的函数和变量进行解析,通常引用的目标是),通常静态库以".a"为后缀,名字格式一般为libxxx.a静态库由程序ar生成

实例程序如下:

Main.c

Print_hello.c

 

生成静态链接库,或者将一个obj文件加入到已经存在的静态库的命令格式为:

ar –rcs 库文件obj_1 obj_2 …

使用上面的实例程序print_hello.c创建静态链接库:

  • 使用静态链接库

    使用方式一:

    使用方式二:

    注意,在方法二中"-L./"不可少,否则出现如下错误:

    这是因为上面的命令在系统默认的路径下查找hello函数库,而我们并没有将libhello.a库放在系统默认搜索路径下,所以需要显示指定库函数的路径为当前目录。

    另外还需注意,

    下面两个图分别是头文件和库文件的默认搜索路径:

  • 动态链接库

    前言

    动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的 程序都可以使用动态库来运行程序。

        动态链接库的名称有别名(soname)、真名(realname)和链接名(linker name):

        别名:libxxx.so,这种形式的库名正是执行编译命令时编译器要搜索的名字。

        真名:动态链接库的真实名称,一般总是在别名的基础上加上一个小版本号、发布版本等构成。

        链接名:程序链接时使用的库的名字。

    把当前工作目录(libhello.so.1所在的目录)加入动态链接库的搜索路径配置文件/etc/ld.so.conf中:

    执行ldconfig命令刷新缓存文件/etc/ld.so.cache:

    在编译程序时,使用动态链接库和静态链接库是一致的,使用"-lxxx"的方式:

    打开/etc/selinux/config,将selinux=enforcing或permissive改成disabled。然后存盘退出,重启系统。

    cannot open shared object file: No such file or directory,这是由于程序运行时没有找到动态链接库造成的。程序编译时链接动态链接库和运行时使用动态链接库的概念是不同的,在运行时,程序链接的动态链接库需要在系统目录下才行。有几种办法可以解决此种问题:

      将动态链接库的目录放到程序搜索路径中,可以将库的路径添加到环境变量LD_LIBRARY_PATH中实现:

      使用ld-Linux.so.2来加载程序,命令格式为:

    /lib/ ld-Linux.so.2 –library-path 路径 程序名

    注意,如果系统的搜索路径下同时存在静态链接库和动态链接库,默认情况下会链接动态链接库。如果需要强制链接静态链接库,需要加上"-satic"选项。

    动态加载库

    前言

        动态加载库和一般的动态链接库所不同的是,一般动态链接库在程序启动时就要寻找动态库,找到库函数;而动态加载库可以用程序的方法来控制什么时候加载。动态加载库主要有函数dlopen()、dlerror()、dlsym()和dlclose()来控制动态库的使用。函数原型如下:

    小发现:

      有没有注意到,我们并没有使用用到include <hello.h>(假设我们为print_hello.c写了一个hello.h的头文件)。其实,只要编译命令中加入选项-lhello,hello.h头文件包含不包含都没有问题。为了验证这个问题,使用http://www.cnblogs.com/nufangrensheng/p/3518411.html中的程序清单11-1这个实例进行了测试:

      在http://www.cnblogs.com/nufangrensheng/p/3518411.html程序清单11-1编译过程中,曾遇到undefined reference to ‘pthread_create’这样的错误,原因在于没有在编译命令中加入-lpthread选项。

      如果我们加入了-lpthread选项,此时尝试着把程序中的#include <pthread.h>去掉,重新编译你会发现同样也是可以的。

      总结:如果使用的是标准库中的函数,则只需将头文件包含进来。如果使用的函数所在的库不是标准库(例如我们自己编写的库或标准以外扩展的库),则在编译时必须加入-lxxx选项,而头文件则可以包含也可以不包含,包含进来显得规范而已。

     

    相关内容