静态库和动态库

我们的软件体系中,位于最上层的是应用程序,比如我们平时用到的网络浏览器、Email客户端、多媒体播放器、图片浏览器等。从整个层次结构来看,开发工具与应用程序属于同一个层次的,因为它们都使用一个接口,那就是操作系统应用程序编程接口(Application Programming Interface)。应用程序接口的提供者是运行库。什么样的运行库提供什么样的API,比如Linux下的Glibc库提供POSIX的API;Windows的运行库提供Windows API,最常见的32为Windows提供的API又被称为Win32。
本质上来说,库是一种可执行代码的二进制形式,包含的代码可被程序调用,库也可以是源码。库有两种:静态库(.a、.lib)和动态库(.so、.dll),Windows和Linux下库文件的格式不兼容。

静态库

  • 编译(链接)时把静态库中相关代码复制到可执行文件中,程序中调用了库中的哪些函数,就把这些函数实现复制进来,并不是把整个库文件复制进来。
  • 程序中已包含代码,运行时不再需要静态库
  • 程序运行时无需加载库,执行速度快
  • 程序的可执行文件大,运行时占用更多的内存
  • 静态库升级后,程序需要重新编译链接

静态库的创建

/* hello.c */
#include <stdio.h>
void hello(void)
{
    printf("hello world\n");
    return;
}

编译生成目标文件
gcc -c hello.c -Wall
Linux下通过ar工具创建静态库hello
ar crs libhello.a hello.o
Linux静态库命名规范,必须是"lib[library_name].a":lib为前缀,中间是静态库名,扩展名为.a
调用静态库

/* test.c */
#include <stdio.h>
void hello(void); /* 也可使用创建库文件的头文件形式 */
void main(void)
{
   hello();
    return;
}

Linux下使用静态库,需要在编译的时候,指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,-l选项)。
gcc -o test test.c -L -Ihello
-L表示要连接的库所在目录,编译器不会去当前路径去找库文件。
-l指定链接时需要的库,编译器查找连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库的名称。

动态库

静态库对程序的更新、部署和发布页会带来麻烦。如果静态库更新了,所有使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,只是一个很小的改动,却导致整个程序重新下载,全量更新)。而且静态库占用空间,所以有了动态库。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。

  • 编译(链接)时仅记录用到哪个动态库中的哪个符号,不复制动态库中相关代码
  • 程序中不包含库中代码,所以体积小
  • 多个程序可以共享同一个库,不同程序可以调用同一个库中代码
  • 程序运行时需要加载库,效率低;不能脱离库运行(与单片机一般不同)
  • 库升级方便,无需重新编译程序

动态库的创建
使用上面的hello.c编译创建,与创建静态库不同的是,不需要打包工具ar,直接使用编译器即可创建动态库
gcc -c -fPIC hello.c -Wall
-fPIC创建与地址无关的编译程序(pic,position independent code),即生成的*.o文件代码可以被加载到任意地址执行,而不是只能在固定地址执行;动态库的特点就是被不同的程序加载到不同的地址执行,所以库中的代码必须是和位置无关的。
动态链接库的名字形式为libxxx.so,前缀是lib,后缀名为“.so”
gcc -shared -o libhello.so.1 hello
-shared指定生成动态链接库
so后面加数字代表库的版本,支持同一个库的多版本
为动态库创造链接文件
当编译器在编译文件时,知道其所依赖的库的名字,但却找不到库文件,所以需要创建链接文件,让编译器能找到库文件
In -s libhello.so.1 libhello.so
符号链接文件命名规则为libxxx.so,名称后面不能跟数字
调用动态库库
编译test.c并链接动态库hello.so
gcc -o test test.c -L -Ihello
编译命令和使用形式和静态库一样,gcc默认先找动态库hello.so,如果动态库不存在,就会去链接hello.a;
也可加-static选项直接链接静态库。
为了让系统能找到要加载的动态库,有三种方法:

  • 把库文件拷贝到/usr/lib/lib目录下
  • 在LD_LIBRARY_PATH环境变量中添加库所在的路径
  • 编辑etc/ld.so.conf文件,加入库文件所在的路径,执行ldconfig刷新
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值