GCC 动态链接库

获取更多嵌入式、Linux学习资料,获取独家嵌入式Linux学习路线地图,欢迎加群:398294860,观看更专业、更系统地嵌入式视频教程,请关注:wanglitao.taobao.com

静态库里实现的函数,可能被多个应用程序调用,那么在链接时,被调用的这个函数可能就会多次链接到不同的应用程序中。

比如C标准库的printf函数,可能被一个应用程序调用多次,被不同的应用程序调用,当这些应用程序加载到内存运行时,内存中也就存在多个printf函数代码的副本,太浪费了内存空间。而且,对于应用程序来说,每一个调用的库函数都被链接进来,自身的文件体积也会大增。是可忍孰不可忍,动态链接此时就粉墨登场了。

动态链接跟静态链接相比,具有以下优势

  • 库的代码不会链接到应用程序里
  • 同一份代码(如printf代码)可以被多个应用程序共享使用
  • 大大节省了内存空间

但动态库也有缺点,发布软件时,动态库需要和应用程序一起发布,否则你编译的应用程序到了一个新的平台可能就无法运行。

制作一个动态库

# gcc -shared -fPIC -o libmymath.so add.c sub.c

其中的参数说明:

  • -shared :动态库编译,链接动态库
  • -fPIC(或fpic) :生成使用相对地址无关的目标代码
  • -Ldir :在动态库的搜索路径中增加dir目录
  • -lname :链接静态库(libname.a)或动态库(libname.so)的库文件

使用动态链接

将动态链接库拷贝到main.c的同一目录下

# tree
.
├── inc
│   ├── add.h
│   └── sub.h
├── libmymath.so
└── main.c

在编译main.c,链接动态库libmymath.so的时候,直接指定当前目录下的libmymath.so文件:

# gcc main.c ./libmymath.so -I inc/
# ls
a.out  inc  libmymath.so  main.c

在当前目录下运行生成的可执行文件a.out,可以正常运行。将a.out拷贝到其他目录,比如/opt目录下,然后再运行,就会出现以下错误:

root@ubuntu:/opt# ls
a.out
root@ubuntu:/opt# ./a.out 
./a.out: error while loading shared libraries: ./libmymath.so: cannot open shared object file: No such file or directory

我们需要将对应的libmymath.so文件拷贝到a.out的同一目录下,然后a.out才能正常运行。

Linux的动态链接库一般都放在/lib官方默认目录下。如果想让a.out放在任何路径下都可以运行,我们可以把libmymath.so动态库拷贝到/lib下,然后在编译应用程序时,通过-L参数指定动态链接库的搜索路径。编译生成的a.out在运行时,就会到指定的/lib目录下去加载动态库libmyamth.so:

# cp libmymath.so /lib
# tree 
.
├── inc
│   ├── add.h
│   └── sub.h
├── libmymath.so
└── main.c

# gcc main.c -L/lib -lmymath -I inc
# tree
.
├── a.out
├── inc
│   ├── add.h
│   └── sub.h
├── libmymath.so
└── main.c

将生成的a.out拷贝到系统的任何目录下,你会发现,都可以正常运行。

《Linux三剑客》视频教程,从零开始快速掌握Linux开发常用的工具:Git、Makefile、vim、autotools、debug,免费赠送C语言视频教程,C语言项目实战:学生成绩管理系统。详情请点击淘宝链接:Linux三剑客