只是扩展:
ELF文件(Executable and Linkable Format):可执行和可连接格式文件。
ELF可重定位目标文件的格式:
ELF可执行文件的格式:
静态库:(.a)
所有的编译系统都提供一种机制,将所有相关的目标文件打包成为一个单独的文件,成为静态库,它可以用作连接器的输入。(一般由.o文件构成,即.o文件的打包)
程序在编译链接的时候把库的代码链接到可执行文件中,程序运行时将不再需要静态库。
如何打包?
ar -rc lib库名.a(库文件名) xxx.o ex: ar -rc libmymath.a add.o sub.o
静态库默认搜索路径:
1./lib /usr/lib
2.-L 指定库的路径 ex: gcc main.c -L . -lmymath
当静态库被调用时,用到哪个函数,调用哪个函数(.o文件)。
缺点: 静态库和所有软件一样需要定期的维护和更新。如果我们想要使用一个库的最新版本,,就必须以某种方式了解到该库的更新情况,然后显式的将我们
的程序与更新的库重新连接。
动态(共享)库:(.so)
(ELF文件, 即可执行程序)共享库是一个目标模块,在运行时,可以加载到任意的存储器地址,并和一个在存储器中的程序连接起来。
动态库在运行的时候才去链接动态库的代码,多少程序共享使用库的代码。
一个与动态库连接的可执行文件仅仅包含他们用到的函数入口地址一个表,而不是外部函数所在目标文件的整个机器码
在可执行文件开始运行之前,外部函数的机器码由操作系统从磁盘上的该动态库文件中复制到内存中。这个过程成为动态链接。
动态库可以在多个程序之间共享,所以动态链接是的可执行文件更小,节省了磁盘空间。
如何生成动态库?
gcc -fPIC -shared -o lib库名.so xxx.c ex:gcc -fPIC -shared -o libmymath.so add.c sub.c
动态库的链接:
gcc main.c -L . -lmymath
ldd查看静态库链接情况
ldd a.out
动态库的使用:
1.vim /etc/ld.so.conf.d/XX.conf -- 把动态库的路径加进去 vim /etc/ld.so.conf.d/mymath.conf .
2.ldconfig 链接动态库
利用文件打开动态库: 动态库的运行时加载: -ldl ex: gcc main.c -ldl
void *dlopen(const char *filename, int flag); //动态库名, 什么时候将动态库加载到内存(RTLD_LAZY(什么时候用,什么时候加载))
//返回值 代表动态库的句柄
void *dlsym(void *handle, //dlopen的返回值
const char *symbol); //函数的符号名(函数名) 返回函数的地址---函数指针来接收
int dlclose(void *handle); //关闭dlopen打开的文件
#include <stdio.h> #include <dlfcn.h> #include "add.h" #include "sub.h" typedef int FUNC(int ,int); int main() { void *dp = dlopen("libmath.so", RTLD_LAZY); FUNC *paf, *psf; paf = (FUNC*)dlsym(dp, "add"); psf = (FUNC*)dlsym(dp, "sub"); printf("10 + 20 = %d\n", paf(10,20)); printf("10 - 20 = %d\n", psf(10,20)); dlclose(dp); return 0; }