静态库和动态库

  首先要明白一个概念,静态库和动态库的目的是为了使二进制代码重用。

  静态库:假设一个场景,我们现在做了一个项目A,如果我们希望项目A中的代码能够用于以后的项目B中,该怎么办呢?最简单的想法就是将项目A的各个源文件编译生成的目标文件和其他项目的目标文件拼接起来,有两种方法可以做到这一点

    1、将项目A的目标文件转存至项目B的位置,然后进行链接

    2、将项目A的目标文件打包成一个二进制的文件--静态库

  可以看出,第二种方法更好,静态库可以更简洁的为其他项目提供单个的二进制文件,而不是提供一组分离的目标文件。注意,生成静态库的文件的过程是可逆的,也就是说我们可以向一个静态库中添加目标文件,也可以将静态库文件解压成原来的一组二进制文件。

  动态库:再假设一种场景,在多任务的系统中,无论有多少个并行的任务,特性的系统资源总是唯一的,比如键盘和网卡等,如果每一个想访问共享资源的应用程序都需要包含访问资源的控制代码,那么控制代码在内存中会出现多个副本,重复的代码会使系统的效率变得低下。怎么办呢?---避免代码冗余。

  正确的解决方案:1、在动态库中提供通用的功能;

          2、需要使用通用功能的应用程序只需要在运行时加载动态库即可。

  现在通用的解决方案是利用内存映射实现共享,即PIC(位置无关代码position independent code)技术。只需一份加载到某一进程中内存映射的动态库副本,就能映射到任何应用程序的进程中。

  创建一个静态库的步骤:

   gcc -c first.c second.c

   ar rcs libstaticlib.a first.o second.o

  创建一个动态库的步骤:

    通常来说,构建动态库都需要以下两个选项

      -fPIC  编译器选项

      -shared 链接器选项

  gcc -fPIC -c first.c second.c

  gcc -shared first.o second.o -o libdynamiclib.so

  注意: -fPIC的PIC是位置无关代码,在PIC出现以前,也能够创建动态库,装载器将动态库加载到进程内存空间中,但是只有第一次加载这个动态库的进程能够使用它。根本原因是,在将动态库加载到进程中前,加载器需要修改动态库的代码段即.text段,使得动态库对于该进程来说是有意义的,但是这种修改是不可逆的,所以一旦动态库被修改再被其他的进程加载后,这个动态库对于后面的进程就是不可用的,而出现PIC后,采用内存映射的技术避免了将加载的动态库代码绑定到第一个加载该动态库的进程中。

  参考书籍《高级C/C++编译技术》

  

 

posted @ 2015-08-27 21:20  大城市小葫芦  阅读(257)  评论(0编辑  收藏  举报