静态库与动态库记录

作者: | 更新日期:

几年前曾翻过《链接、装载与库》,现在有人问起静态库动态库的问题,这里就简单记录一下。

背景

《链接、装载与库》这本书还有一个不好的名字叫做《程序员的自我修养》。
当别人给我说起《程序员的自我修养》这本书的时候, 我就说没听过这本书。
因为这个名字完全没有透露出这本书是讲什么的。
但是, 还是推荐一下这本书, 确实是一本很好的书。

库的作用

编写程序, 应该遵守一个原则:不要重复造轮子。
于是有了下面的演化:

  1. copy
    实现方式: 需要某个功能代码时, 为了不重复造轮子, copy一份过来
    缺点: 功能改变时, 需要通知所有使用者重新copy新的代码
  2. 头文件
    实现方式: 需要的功能放在指定的头文件内, 需要时引入对应的头文件
    缺点: 每次编译生成中间文件耗时, 源码暴漏给使用者
  3. 静态库
    实现方式: 打包成一个二进制文件, 程序编译时使用
    缺点: 每个程序内存中单独拥有这份代码, 功能更新时需要重新编译
  4. 动态库
    实现方式: 打包成一个二进制, 程序运行时动态加载
    优点:所有运行的程序共享同一个动态库, 更新动态库只需要重启程序即可

静态库

静态库: 在链接阶段,链接器会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。

Linux静态库命名规范,必须是lib[your_library_name].alib为前缀,中间是静态库名,扩展名为.a

生成目标文件

参数-c 为生成目标文件.o

g++ -c lockapi.cpp

生成静态库文件

ar 命令可以把目标文件打包成.a静态库文件

ar -crv liblockapi.a lockapi.o

使用静态库

程序中正常引入头文件, 正常使用静态库的函数即可。
Linux下使用静态库,只需要在编译的时候,指定链接库的搜索路径(-L选项)、指定链接库名(不需要lib前缀和.a后缀,-l选项)。

g++ main.cpp -L../lib -llockapi

动态库

动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为.so

生成目标文件

-fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。

g++ -fPIC -c lockapi.cpp

生成动态库

-shared指定生成动态链接库。

g++ -shared -o liblockapi.so lockapi.o

使用动态库

和静态库类似。

g++ main.cpp -L../lib -llockapi

运行程序

动态库的链接由ld-linux.so完成, 查找动态库的位置有下面几个顺序:

动态库显示调用

之前写过一些动态库, 然后服务器就自动加载自己的动态库了, 是怎么做到的呢?

原来我们可以在程序中动态加载任意动态库。

#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
//Link with -ldl.
点击查看评论

关注公众号,接收最新消息

tiankonguse +
穿越