前言

静态链接库会编译进可执行文件,并被加载到内存,会造成空间浪费

静态链接库对程序的更新、部署、发布带来麻烦。如果静态库更新了,使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)

动态库在程序编译时并不会被链接到目标代码中,而是在执行文件中记录对动态库的引用,在程序运行时才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布带来的麻烦,用户只需要更新动态库即可,增量更新。

Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。

特点

  • 动态库把对一些库函数的链接载入推迟到程序运行的时期
  • 可以实现进程之间的资源共享。(因此动态库也称为共享库)
  • 将一些程序升级变得简单。
  • 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)

生成动态链接库

  1. 编写源文件
  2. 将一个或几个源文件编译链接,生成共享库。
  3. 通过 -L<path> -lxxx 的gcc选项链接生成的libxxx.so。
  4. 把 libxxx.so 放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。

例子

源文件

add.c

int add(int a, int b)
{
return a + b;
}

subtract.c

int subtract(int a, int b)
{
return a - b;
}

编译

gcc -fPIC -c add.c
gcc -fPIC -c subtract.c

其中,PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码,这是动态库需要的特性

链接

gcc -shared -o libmymath.so subtract.o add.o

-shared是链接选项,告诉gcc生成动态库而不是可执行文件

这两步可以合并成一个命令:

gcc -o libmymath.so -fPIC -shared subtract.c add.c

编写头文件

#ifndef _MYMATH_H_
#define _MYMATH_H_ int add(int, int);
int subtract(int, int); #endif

使用链接库

main.c

#include <stdio.h>
#include "mymath.h" int main()
{
printf("%d, %d\n", add(, ), subtract(, )); return ;
}

链接

gcc main.c -L. -lmymath

如果同一目录下同时存在同名的动态库和静态库,比如 libmymath.so 和 libmymath.a 都在当前路径下,则gcc会优先链接动态库。

运行

当执行 ./a.out,发现程序报错

./a.out: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

这涉及到程序如何定位共享库文件

  1. 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)
  2. 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段 -- 环境变量LD_LIBRARY_PATH -- /etc/ld.so.cache文件列表 -- /lib/,/usr/lib 目录找到库文件后将其载入内存。

/etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的

所以,我们想让程序找到自己写的动态链接库,有如下方法:

  • 指定 LD_LIBRARY_PATH 环境变量为 libmymath.so 文件所在的目录
  • 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径; 同时,运行ldconfig ,该命令会重建/etc/ld.so.cache文件
  • 把 libmymath.so 拷贝到/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作

我们可以执行:

LD_LIBRARY_PATH=. ./a.out

Makefile

.PHONY: all

all: build target

build: libmymath.so
libmymath.so: add.o subtract.o
gcc -o $@ -shared $^
add.o: add.c
gcc -c -fPIC $<
subtract.o: subtract.c
gcc -c -fPIC $< target: a.out
a.out: main.c
gcc main.c -L. -lmymath .PHONY: clean
clean:
rm *.o a.out libmymath.so

最新文章

  1. iOS开发需要哪些图片?
  2. MaterialUp - 寻找材料设计灵感必备的网站
  3. 高质量C++[转]
  4. HashMap代码示例
  5. 夺命雷公狗---node.js---10之POST的接收
  6. ES6:JavaScript 新特性
  7. 101个直接可以拿来用的JavaScript实用功能代码片段(转)
  8. Android 使用HttpClient方式提交GET请求
  9. Errore HTTP 404.2 - Not Found&quot; IIS 7.5 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理
  10. Asp.Net中的消息处理---MSMQ系列学习(一)
  11. Windows 8/7下还原系统默认扩展名打开方式类型
  12. [转载] 基于Dubbo的Hessian协议实现远程调用
  13. EBS R12安装升级(FRESH)(四)
  14. Arduino语法-变量和常量
  15. Python成绩雷达图
  16. Android开发者的Anko使用指南(二)之Dialogs
  17. 通过WifI开发调试Android设备
  18. 从vue渲染想到的数组方法
  19. class类的使用
  20. A profile to detect when a SMS database has been changed

热门文章

  1. HBase编程 API入门系列之put(客户端而言)(1)
  2. 跨域问题时的Filter无效
  3. 「bzoj 3944: Sum」
  4. programming-languages学习笔记--第2部分
  5. Jmeter实例计划(查询天气)
  6. Word中高效输入公式:内嵌公式和Mathtype
  7. Servlet是线程安全的吗
  8. Filter实现字符集统一设置
  9. CSU - 2031 Barareh on Fire (两层bfs)
  10. php auto_prepend_file和auto_append_file的妙用