静态库&动态库

      这里将简单介绍下什么是静态库什么是动态库以及两者之间的区别,在介绍之前,先介绍下什么是函数库,什么时候会用到库。

什么是库?

     库就是一段编译好的二进制代码,加上头文件就可以供别人使用。

什么时候我们会用到库?

      一种情况是某些代码需要给别人使用,但是我们不希望别人看到源码,就需要以库的形式进行封装,只暴露出头文件,另外一种情况是,对于某些不会进行大的改动的代码,我们想减少编译的时间,就可以把它打包成库,因为库是已经编译好的二进制了,编译的时候只需要 Link 一下,不会浪费编译时间。

     上面提到库在使用的时候需要 Link,Link 的方式有两种,静态和动态,(依照是否编译到程序的内部)于是便产生了静态库和动态库。

静态库

    静态库即静态链接库。

    扩展名:(Windows 下的 .lib,Linux 和 Mac 下的 .a)。这类函数通常扩展名为libxxx.a类型。

    编译行为:这类函数库在编译的时候会直接整合到执行程序当中,所以利用静态函数编译成的文件会比较大一些。

    独立执行的状态:编译成功的可执行文件可以独立执行,而不需要再向外部要求读取函数库的内容。

    升级难易度:只要函数库升级了,所有将此函数库纳入的程序都需要重新编译。(因为函数库是直接整合到可执行文件中,因此若函数库升级时,整个可执行文件必须要重新编译才能将新版的函数库整合到程序当中。)

测试程序

//add.h

#ifndef __ADD_H__
#define __ADD_H__
int add(int a, int b);
#endif
//add.c
#include"add.h"
int add(int a, int b)
{
    return a+b;
}

//sub.h
#ifndef __ADD_H__
#define __ADD_H__
int sub(int a, int b);
#endif

//sub.c
int sub(int a, int b)
{
    return a-b;
}

//main.c

#include<stdio.h>
#include"add.h"
#include"sub.h"

int main()
{
    int a=10;
    int b = 5;
    printf("add(%d,%d)=%d\n",a,b,add(a,b));
    printf("sub(%d,%d)=%d\n",a,b,sub(a,b));

    return 0;
}

    生成静态库会使用到ar工具,这里先简单介绍下ar工具

    ar基本用法

    ar可以用来创建、修改库,也可以从库中提出单个模块。库是一单独的文件,里面包含了按照特定的结构组织起来的其他的一些文件。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件中。

    参数:

    指令参数

       -d  删除库文件中的成员文件。

       -m  变更成员文件在库文件中的次序。

       -p  显示库文件中的成员文件内容。

       -q  将问家附加在库文件末端。

       -r  将文件插入库文件中。

       -t  显示库文件中所包含的文件。

      -x  自库文件中取出成员文件。

选项参数

     c  建立库文件。

     f  为避免过长的文件名不兼容于其他系统的ar指令指令,因此可利用此参数,截掉要放入库文件中过长的成员文件名称。

     u  只将日期较新文件插入库文件中。

     v  程序执行时显示详细的信息。

     V  显示版本信息。

     ar用来管理一种文档。这种文档中可以包含多个其他任意类别的文件。这些被包含的文件叫做这个文档的成员。ar用来向这种文档中添加、删除、解出成员。成员的原有属性(权限、属主、日期等)不会丢失。

    实际上通常只有在开发中的目标连接库是这种格式的,所以尽管不是,我们基本可以认为ar是用来操作这种目标链接库(.a文件)的。

 

生成静态库

   搜索库路径

       1.  从左到右搜索-L指定的目录。 (如上面通过-L指定库的搜索路径)

       2. 由环境变量指定的目录  (LIBARAY_PATH). eg:上面的执行方式

         3. 由系统指定的目录 >*/usr/lib >*/usr/local/lib

动态库

     动态库即动态链接库

     扩展名:(Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib)。这类函数库通常扩展名为libxxx.so类型。

     编译行为:动态库库的内容并没有被整合到可执行文件当中,而是当可执行文件要使用到函数库的机制时,程序才会去读取函数库来使用。由于可执行文件要使用到函数库的机制时,程序才会去读取函数库来使用。由于可执行文件当中仅具有指向动态函数库所在的指标而已,并不包含函数库的内容,所以它的文件会比较小一点。

     独立执行的状态:这类函数库所编译出来的程序不能被独立执行,因为当我们使用到函数库的机制时,程序才会去读取函数库,所以函数库文件必须要存在才行,而且,函数库的所在目录也不能改变。

     升级难易度:当函数库升级后,可执行文件根本不需要进行重新编译的行为,因为可执行文件会直接指向新的函数库文件。

      注:动态库可以在多个程序间共享(又称共享库),所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

测试动态库

        运行动态库:

              1. 拷贝 .so文件到系统共享库路径下,一般指/usr/lib

              2. 更改LD_LIBRARY_PATH

              3. ldconfig配置/etc/ld.so.conf.d/ , ldconfig更新

   ldconfig与/etc/ld.so.conf

         我们知道内存的访问的速度是硬盘的好几倍,如果我们将常用到的动态函数库先加载内存当中,就不需要从头由硬盘里面读出,这样就可以增进函数库的读取速度。这个时候就可以是哟个ldconfig与/etc/ld.so.conf.

        如何将动态函数库加载到高速缓存当中?

        1. 在/etc/ld.so.conf里面写下想要读入高速缓存当中的动态函数库所在的目录。注:是目录而不是文件。(vi /etc/ld.so.conf)

        2. 利用ldconfig这个可执行文件将/etc/ld.so.confg的数据读入缓存中。(ldconfig)

        3. 同时也将数据记录一份在/etc/ld.so.cache这个文件当中

程序的动态函数库解析:ldd

猜你喜欢

转载自blog.csdn.net/smile_zhangw/article/details/81237759
今日推荐