1 库的概念

库是一种可执行代码的二进制文件,可以被操作系统载入内存执行。

2 库的分类

库可以分为两种:静态库和动态库

静态库:静态库就是一些目标文件的集合,以.a结尾。静态库在程序链接的时候使用,链接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中。一旦链接完成,在执行程序的时候就不需要静态库了。由于每个使用静态库的应用程序都需要拷贝所用函数的代码,所以静态链接的文件会比较大。

动态库:某个程序在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。在程序运行的时候,被调用的动态链接库函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此,这些代码必须使用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器,这些对象文件是用来做动态链接库的,所以要用地址不无关代码(Position Independent Code (PIC))

二者的不同点在于:

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

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

3 库存在的意义

库是别人写好的现有的、成熟的、可以复用的代码,现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。

4 库的产生

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

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

Step2.ar命令将很多.o转换成.a,成为静态库

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

5 库的命名规则

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

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

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

6 查询一个可执行程序所依赖的库

ldd命令可以查看一个可执行程序依赖的共享库

7 静态链接库的创建

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将

创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令

8 动态链接库的创建

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so

根据加载和链接共享库的时机又可分为

l  隐式链接

应用程序自身加载时动态链接和加载共享库

基本思路是:当创建可执行文件时,静态执行一些链接(共享库的重定位和符号表信息,而非代码和数据),然后在应用程序加载时,动态完成链接过程。

 

l  显示链接

应用程序运行过程中动态链接和加载共享库

A情况不同,此情况下:应用程序在运行过程中要求动态链接器加载和链接任意共享库,而无需编译时链接那些库到应用中。

此种情况下,源程序需要包含dlfcn.h头文件,此文件定义了调用动态链接库的函数的原型。

 

发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会优先使用动态库

 -------------------------------------------------------------------------------------------------------------------------------------------------------

下面以简单计算器的例子来进行实验验证

1 编写实例文件(OSUbuntu15.04  gcc version 4.9.2

/*add.c*/

int add(int a,int b)

{

        return a+b;

}

/*sub.c*/

int sub(int a, int b)

{

        return a-b;

}

#ifndef ADD_H

#define ADD_H

int add(int a,int b);

#endif
#ifndef SUB_H

#define SUB_H

int sub(int a,int b);

#endif

            
#include<stdio.h>

#include"add.h"

#include"sub.h"

 
int main(void)

{

        printf("5 + 3 = %d\n",add(5,3));

        printf("5 - 3 = %d\n",sub(5,3));

        return 0;

}

 

2 add.csub.c编译生成.o文件

gcc -c add.c sub.c

输入ls指令,发现多出2个文件,add.osub.o

3 创建静态库

静态库创建指令为ar

ar rcs libmath.a add.o sub.o

此处ar中的rcs的意思是:r表明将模块加入到静态库中,c表示创建静态库,s表示生产索引。

此时多了一个文件:libmath.a

4 使用静态库,此处切记将所生成的库拷贝到系统的库文件目录,一般为/usr/lib/

cp mylib.so /usr/lib/mylib.so

5 删除静态库看查看运行结果

仍然可以正常运行,表明静态库中的公用函数已经连接到目标文件中了。

6 生成动态链接库

此处生成动态库的参数-fPIC-fpic都可以产生目标独立代码,具体应用取决于平台,-fPICalways work,尽管其产生的目标文件可能会大些; -fpic产生的代码小,执行速度快,但可能有平台依赖限制。

7 删除动态库后

程序运行出错。也进一步证明动态库在程序运行时是需要的。

Logo

更多推荐