Linux下库、静态库、共享库


五、库

库就是目标文件的集合,我们把不需要升级更新维护的代码打包合并在一起方便使用,也可以对源文件进行保密。

静态库在使用时是把被调用的代码复制到调用模块中,然后再执行程序时,静态库就不需要了。

静态库的执行速度快,但占用空间大,当库中的内容发生变化时,需要重新编译出新的程序,因此不能轻易修改库中的内容,

而共享库只是在调用模块中嵌入调用代码的在库的相对位置的地址,当执行程序时,共享库会把程序一起加载到内存中,

当执行到调用共享库中代码的指令时跳转到共享中执行,执行完毕后再跳转回来。

占用空间小,方便更新(共享库发生变化后,程序不需要再次编译),相对于静态库执行效率略低。

静态库的扩展名为.a,共享库(动态库)的扩展名为.so

当静态库和动态库同时存在,优先调用动态库,调用静态库需要在编译时加-static

六、静态库:

1、创建静态库

编写源代码:vi .c/.h

编译源代码:gcc -c xxx.c -> xxx.o

打开生成静态库:ar -r libxxx.a x1.o x2.o ...

ar命令的一些参数:

-r 把目标文件添加到静态库中,已经存在的更新

-q 将目标文件追加到静态库的末尾

-d 从静态库中删除目标文件

-t 显示静态库中有哪些目标文件

-x 把静态库拆分成目标文件

2、调用静态库

直接调用:调用者要和库在同一路径下

gcc main.c libxxx.a

设置环境:设置方法与C_INCLUDE_PATH类似

1、打开vim ~/.bashrc 文件

2、在文件末尾,添加一行

export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径

3、重新加载配置文件 source ~/.bashrc

4、编译时要指定库名

gcc main.c -lmath

设置编译参数:-L路径

gcc main.c -L路径 -lmath

3、运行

在编译时已经把被调函数的二进制复制到可执行文件中了,在执行时不在需要静态库文件。

七、共享库

1、创建共享库

编写源代码: vi .c/.h

编译出位置无关目标文件:

gcc -c -fpic xxx.c -> xxx.o

链接生成共享库:

gcc -shared x1.o x2.o ... -o libxxx.so

2、调用共享库

直接调用:调用者要和库在同一路径下

gcc main.c libxxx.so

设置环境:设置方法与C_INCLUDE_PATH类似

1、打开vim ~/.bashrc 文件

2、在文件末尾,添加一行

export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径

3、重新加载配置文件 source ~/.bashrc

4、编译时要指定库名

gcc main.c -lmath

设置编译参数:-L路径

gcc main.c -L路径 -lmath

3、运行

在使用共享库时,调用者只是记录了被调代码在库的位置,因此在执行时需要共享库同时被加载。

操作系统会根据LD_LIBRARY_PATH环境变量的设置来加载共享库

八、动态加载共享库

#include <dlfcn.h>

1、加载共享库

void *dlopen(const char *filename, int flag);

filename:共享库的库名,或路径

flag:

    RTLD_LAZY 使用时才加载

    RTLD_NOW 立即加载

返回值:共享库的句柄(类似文件指针)

2、获取标识符地址并使用

void *dlsym(void *handle, const char *symbol);

handle:共享库的句柄

symbol:标识符的名字

返回值:标识符在共享库中的位置(地址,可以解引用,或跳转过去)。

3、卸载共享库

int dlclose(void *handle);

handle:共享库的句柄

返回值:成功返回0,失败返回-1

4、获取错误信息

char *dlerror(void);

返回值:会把在使用共享库的过程中出现的错误,以字符串形式返回

九、辅助工具

nm:查看目标文件、可执行文件、静态库、共享库的中的符号列表

ldd:查看可执行程序所依赖的共享库有哪些

strip:减肥,去除掉目标文件、可执行文件、静态库和共享库中的符号列表、调试信息。

objdump 显示二进制模块的反汇编信息

Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Love丶伊卡洛斯 !
评论
 Previous
Linux下系统调用和文件操作 Linux下系统调用和文件操作
一、系统调用 UNIX/Linux系统绝大部分功能都是通过系统调用实现,比如:open/close... UNIX/Linux把系统调用都封装成了C函数的形式,但他们不是标准C的一部分。 标准库中的函数绝大部分时间都工作在用户态,但部分
2019-09-09
Next 
Linux下GNU编译器 Linux下GNU编译器
GNU编译器 1、支持众多编程语言、平台 2、构建过程(C代码是如何变成可执行文件的)。 第一步,预处理. 这一步处理 头文件、条件编译指令和宏定义。 第二步,编译. 将第一步产生的文件连同其他源文件一起编译成汇编代码。
2019-09-09
  TOC