制作、使用动静态库(只带简单讲解,适于直接使用)

动静态库的定义

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码

静态库的制作

例子:将自己编写的my_sub.c、my_add.c具体实现文件和my_sub.h、my_add.h头文件生成静态库,首先在makefile文件中编写以下代码

​
libmymatch.a:my_sub.o my_add.o
    ar -rc $@ $^
my_sub.o:my_sub.c
    gcc -c -o my_sub.o my_sub.c
my_add.c:my_add.c
    gcc -c -o my_add.o my_add.c

​

在上述文件所在目录,执行make语句,会将my_sub.c和my_add.c通过gcc  -c命令,分别编译生成.o文件,再通过ar -rc将两个.o文件打包成一个.a文件(注意.a文件的开头以lib开头,中间是自己给的命名)。至此,我们生成了静态库libmylib.a。这之后在makefile中编写下面代码

.PHONY:output
output:
    makedir -p mylib/lib
    makedir -p mylib/include
    cp *.h mylib/include
    cp *.a mylib/lib

在上述文件所在目录,执行make output语句,将会创建一个mylib文件夹,并在其中创建lib和include文件夹,然后分别把刚才生成的.a和.h文件放入对应文件夹中。

静态库的使用

使用者拿到了我们生成的静态库,mylib之后,在自己的程序main.c中正常包含头文件,使用库中函数。将mylib放在与main.c相同路径下(也可以放在其他路径,接下来的步骤只需根据该种情况进行修改即可)。

gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath

-I./mylib/include:头文件路径,如果未标明,只会在默认路径或当前路径进行搜索,所以我们要标明头文件所在位置
-L./mylib/lib:库路径未标明也只会在默认路径下进行搜索,所以要指明库路径
-lmymath:一个库路径下,还可能有多个库文件,还需要指明到底是那一个库,注意要去掉开头的lib和后缀.a

动态库的制作

libmymath.so:my_sub.o my_add.o
    gcc -shared -o $@ $^
my_sub.o:my_sub.c
    gcc -fPIC -c -o my_sub.o my_sub.c
my_add.c:my_add.c
    gcc -fPIC -c -o my_add.o my_add.c

.PHONY:output
output:
    mkdir -p mylib/lib
    mkdir -p mylib/include
    cp *.so mylib/lib
    cp *.h mylib/include

在命令行输入make,会将my_sub.c和my_add.c分别生成.o文件,加上-fPIC选项,表示的是生成与位置无关码。之后使用gcc自带的打包工具,加上-shared选项,表示生成共享库格式。即可生成动态库库libmymath.so。
之后,我们输入make output,创建一个目录mylib,在其中创建两个目录lib和include,分别将.so文件和.h文件放入对应的文件夹中。未来使用者拥有了mylib整个文件夹后,就可以使用该动态库。

动态库的使用

对于编译阶段,与静态库的使用完全一样

gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath

但是如果直接运行,会出现以下情况结果显示,无法找到动态库。虽然我们在编译阶段已经告诉了gcc,我们使用的库的路径和库名称。但是程序一旦编译完成,和gcc就脱离了关系。而程序一旦运行起来,操作系统和shell也需要知道库在哪里,而我们的库又不在系统路径下,所以OS无法找到。
这里我们提供两种运行程序的方法
①将.so库文件放到系统默认路径下,一般是/usr/lib
②运行下面三行Linux命令,更改LD_LIBRARY_PATH,编译程序,运行程序。但是此方法不进行特殊设置的话,重启后会失效

​
export LD_LIBRARY_PATH=.
gcc main.c -lmymath
./a.out

动静态库的加载原理

下面附待两张自己画的原理图和简单说明。

静态库的加载,在程序编译时期,把对应的静态库代码拷贝到程序中,最后跟随程序一同加载到内存中的代码区动态库的加载,在编译时期,不会将库的代码直接拷贝,而是只将指定函数的地址(gcc是生成的与位置无关码),写入到可执行程序中。该地址可以看做是对应库起始位置的偏移量。待程序加载到内存中运行时,动态库也加载到内存,通过页表映射到共享区。库有了实际的物理位置之后,起始位置确定,通过保存的函数的偏移地址,就可以找到库中对应函数的具体位置。

  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值