zoukankan      html  css  js  c++  java
  • linux下的静态库和共享库

    转载&&增加:

         我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期的代码维护。我们可以把他们制作成相应的功能函数,使用时直接调用就会很方便,还可以进行后期的功能升级。 

         例如我要在一段代码中多次交换两个变量的值,我可以在代码中多次写入

    i=x;
    x=y;
    y=i;

           不过这样未免有点麻烦我们可以编写一个change_two_int()函数进行简化。
    定义如下函数:
    void change_two_int(int *a,int *b)
      {
         int c;
         c=*a;
         *a=*b;
         *b=c;
       }
        这样每次要进行交换时只需调用 change_two_int(&x , &y);即可,是否方便了许多?

           那么我们要讨论的和这些有什么关系呢?库通俗的说就是把这些常用函数的目标文件打包在一起,提供相应函数的接口,便于程序员使用。库是别人写好的现有的,成熟的,可以复用的代码,我们只需要知道其接口如何定义,便可以自如使用。

           现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。比如我们常使用的printf函数,就是c标准库提供的函数。我们在使用时只需要包含相应的头文件就可以使用(非静态编译还要有相应的库文件)。而不用关心printf函数具体是如何实现的,这样就大大提高了程序员编写代码的效率。从使用方法上分库大体上可以分为两类:静态库和共享库。在windows中静态库是以 .lib 为后缀的文件,共享库是以 .dll 为后缀的文件。在Linux中静态库是以 .a 为后缀的文件,共享库是以 .so为后缀的文件。
    以linux下的静态库和动态库为例我们研究一下,首先我们看一下他们的生成方式

    静态库:
    首先将源文件编译成目标文件:gcc –c a.c b.c
    生成静态库:ar –rc libstatic.a a.o b.o

    共享库:
    同静态库一样编译成目标文件:gcc –c a.c b.c
    生成共享库:gcc –fPIC –shared –o libshared.so a.o b.o

           由此可见静态库和动态库都是对目标文件的处理,也可以说库文件已经是机器码文件了,静态库和共享库的加载过程有很大的区别。

    静态库的链接方法:
    gcc –o staticcode –L. –lstatic main.c –static(默认库在当前文件夹)

    共享库的链接方法: 
    gcc –o sharedcode  -L. –lshared main.c(默认库在当前文件夹)

           当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,这样运行起来相对就快些。不过会有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间.

           与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。这样就使可执行文件比较小, 节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率,没有好与坏的区别,只看具体需要了。

            另外,.一个程序编好后,有时需要做一些修改和优化,如果我们要修改的刚好是库函数的话,在接口不变的前提下,使用共享库的程序只需要将共享库重新编译就可以了,而使用静态库的程序则需要将静态库重新编译好后,将程序再重新编译一便。

    总结:

    一、库的类型

    (一) 在windows中

    .dll 动态库

    .lib 静态库

    库即为源代码的二进制文件

    (二) 在linux中

    .so 动态库

    .a      静态库

    (三) 静态库和动态库的优缺点

    我们通常把一些公用函数制作成函数库,供其它程序使用。

    函数库分为静态库和动态库两种。

    静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

    动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在

     总结的说就是静态库:便于移植,但是体积大,不易于维护和升级

    共享库就是便于升级维护,但是依赖性比较强,不易于移植,体积小,

    1.什么是库

    在windows平台和linux平台下都大量存在着库。

    本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。

    由于windows和linux的本质不同,因此二者库的二进制是不兼容的。

    本文仅限于介绍linux下的库

    2.库的种类

    linux下的库有两种:静态库和共享库(动态库)。

     二者的不同点在于代码被载入的时刻不同。

    静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

    共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

    3.库存在的意义

    库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。

    现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

    4.库文件是如何产生的在linux下

    静态库的后缀是.a,它的产生分两步

    Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表

    Step 2.ar命令将很多.o转换成.a,成文静态库

    动态库的后缀是.so,它由gcc加特定参数编译产生。

    例如:

    $ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -olibfoo.so.1.0 *.

      -fPIC:可重新定位的二进制文件:

    我们编译的时候或者程序运行的时候需要·将库加载到内存当中,如果库中有多个函数,涉及到了函数的库内的jump地址跳转,库里的地址存储的是绝对的地址,但是加载

    到内存后这个地址就改变了,所以使用绝对地址可能就是产生访问违规的问题,pic就是将jump中的绝对地址变成相对地址,那样在内存中毕竟是连续的内存,所以就不会

    受到影响

    gcc -fpic -o  *.c  -----------------》*.o

    生成与位置无关的二进制文件

    gcc -shared -WL -soname  ,libmylib.so.1   -o   libmylib.so.1.0.1   *.o    生成库

    gcc -I/test.h  main.c libmylib.so.1.0.1 -o app   生成app

    soname 主版本名

    realname真实名字

    linkname链接名字

    5.库文件是如何命名的,有没有什么规范

    在linux下,库文件一般放在/usr/lib和/lib下,

    静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称

    动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号

  • 相关阅读:
    2016年回家的大概经过
    [转载][记录]shell 批量修改文件名
    Tinymce4 中Ajax多次加载时,会出现菜单在第二次进入时,显示的下拉菜单在左上角
    PHP生成HTML页面顶部出现空白部分(&#65279字符?)
    tcpdf MultiCell line break
    [转载][记录]javascript生成不重复的随机数
    [转载]PHP 字符串替换中文
    PHP 使用get_class_methods()和array_diff() 兩個相同的類中方法差集
    mysql datetime 排序
    highcharts 去掉右下角链接
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/6380557.html
Copyright © 2011-2022 走看看