Linux 动静态库

目录

静态库和动态库的概念和本质。

结合虚拟地址空间 理解静态库和动态库的使用

gcc规则使用动静态库的规则:

制作静态库

使用静态库

方法1.

方法2.

制作动态库

使用动态库

方法1:

方法2:

方法3:

方法4:


静态库和动态库的概念和本质。

1. 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库,生成的可执行程序中自己的代码和静态库的代码是一体的,进程运行起来之后,全部都在地址空间的代码区。

2. 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序可以共享使用库的代码。

所以,在编译链接时,静态库就会和自己的源文件编译汇编形成的.o文件合并,生成一个可执行程序,之后再执行此可执行程序时,不再需要静态库,因为已经在可执行程序内部了。而使用动态库时,动态库并不在可执行程序内部,每次运行过程中,才会去加载链接动态库。


结合虚拟地址空间 理解静态库和动态库的使用

静态库在你的源文件编译汇编,最后链接时,已经进入可执行程序内部了,生成可执行程序之后,后期执行此可执行程序,不再需要静态库文件。可以独立运行,所有代码都存在于进程地址空间的代码段中。

动态库和可执行程序可以分批加载,先运行可执行,若需要执行动态库中的函数代码时,加载动态库代码到内存中,建立进程地址空间中共享区(栈堆之间的那部分区域),页表,内存中的动态库代码的映射关系。执行动态库代码时,从地址空间中的代码段跳转到共享区,然后通过页表映射执行内存中的动态库代码即可。

这也是为什么动态库的.o文件编译时,要加-fPIC选项,fPIC表示生成的.o文件中的地址,是一种与位置无关的地址,相对地址。编动态库代码的地址时,都是从0开始编址。

因为动态库的使用机制。动态库是一种共享库,动态库可以被多个进程共享,同时使用。所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。    即,如果多个进程需要用到内存中的一个共享库,则利用虚拟地址空间机制,建立映射关系即可。    而静态库则不是,若有十个进程使用同一个静态库,同时运行,则内存中将会有10份一样的静态库代码。这无疑是一种内存资源浪费。

结合动态库是一种共享库,以及用gcc -c 汇编动态库源文件时要加-fPIC选项,这个选项表示动态库编址是一种相对地址。如何理解呢?

多个进程使用同一个动态库时,每一次动态库被加载到内存,映射到进程的地址空间的共享区后,映射的位置可能是不一样的。
但是,因为动态库内使用的是相对地址,所以,函数定位可以采用 库在地址空间中的起始虚拟地址 + 函数偏移量的方式,确定函数的虚拟地址。也就是动态库的编址为一种相对地址。

而静态库和自己的.o文件链接合并,使用的虚拟地址是一种绝对地址。


 重在理解。

gcc规则使用动静态库的规则:

1. gcc默认使用动态库,若只有静态库,gcc只能对该库进行静态链接。

2. 若动静态库同时存在,则gcc默认使用动态库

3. 若动静态库同时存在,-static 即可指定使用静态库,进行静态链接。

制作静态库

如上,两个.c 两个.h    .h头文件包含库里面的函数声明 .c文件包含函数定义。

1. 将源文件,预处理,编译,汇编为.o可重定向二进制目标文件。

gcc -c mymath.c -o mymath.o   gcc -c myprint.c -o myprint.o

2. 将所有.o文件归档为静态库(静态库文件)至此,静态库就生成好了

ar -rc *.o -o libplus.a    (静态库文件的格式:  libxxx.a) 

3. 创建一个文件夹(目录),比如名为plus,将所有的头文件放在文件夹的include子目录下,将所有归档打包好的静态库放在plus的lib子目录下。   至此,这个plus文件就可以用来发布或者发给别人使用了。

使用静态库

方法1.

1. 将我们的第三方头文件和静态库放在系统存放头文件和库文件的默认搜索路径下。

(或者头文件放在当前路径下也行,因为#include <>会先去系统默认路径下找,然后去当前路径下找,但是,你使用的头文件一般不会在当前路径下)

因为gcc在编译链接时,会去系统默认路径下去查找所需要的头文件和库文件。同时gcc也能自动链接C标准库。但是没法自动链接我们的第三方库.

Linux下,头文件gcc默认搜索路径:/usr/include  库文件默认搜索路径: /lib64 or  /usr/lib64

2. gcc test.c -lplus -o test.exe

-lplus表示你要使用libplus.a这个静态库,而头文件不需要你在gcc编译时指定,因为你的test.c内部就已经说明了需要哪些头文件。      以上是在将头文件和静态库文件放在系统默认路径之后的操作。

方法2.

不将头文件和库文件放在系统默认路径下,则

gcc test.c -I ./plus/include -L ./plus/lib -lplus  -o test.exe

通过gcc时添加指令的方式,说明头文件的位置,库文件的位置,你要链接哪个静态库文件。即可生成可执行程序。


相比之下,第二种方法更好点。因为不会污染系统默认路径下的环境。

我们将库拷贝到系统默认路径下,就叫做库的安装。

制作动态库

还是基于 myprint.h myprint.c mymath.h mymath.c

1. gcc -fPIC -c myprint.c -o myprint_d.o

gcc -fPIC -c mymath.c -o mymath_d.o

编译.c文件生成.o可重定向二进制目标文件时,加-fPIC指令,表示与位置无关地生成.o文件(这块和动态库使用的本质有关)    

2. gcc -shared mymath_d.o myprint_d.o -o libplus.so

不用ar,用gcc -shared即可。将.o文件合并归档打包生成libxxx.so动态库  (这里若不加-shared,就等于生成可执行程序了)

3. 可以将.h放在plus/include/下 将.so放在plus/lib/下,这样plus文件就可以用来发布或者传给使用库的人了。

使用动态库

若我们还是gcc test.c -I ./plus/include -L ./plus/lib -lplus  -o test.exe 生成test.exe文件(这里的/plus/lib下存储的是动态库),然后运行./test.exe  会直接报错。

./haha_dong: error while loading shared libraries: libplus.so: cannot open shared object file: No such file or directory
显示无法找到动态库,这里和动态库和静态库的本质区别有关,因为动态库不是编译链接生成可执行之后就可以随意运行了。在程序运行过程中,会跳转到动态库。而上方报错就是因为查找不到libplus.so

方法1:

拷贝.so文件到系统共享库路径下

Linux下,头文件gcc默认搜索路径:/usr/include  库文件默认搜索路径: /lib64 or  /usr/lib64
因为程序运行过程中,需要动态库时,会自动去系统默认路径下查找动态库。这里不需要头文件,因为生成可执行的时候,头文件已经在你的源文件内部展开的。

方法2:

配置Linux系统环境变量:LD_LIBRARY_PATH

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yzl/aandso/plus2/lib

相当于,搜索动态库的时候,除了去系统默认路径下找,如果这个环境变量被配置了,还会在这个环境变量指定的路径下去找动态库。这里需要绝对路径。

缺点:这个环境变量在再次登录时,就没有了,因为环境变量的初值是通过系统的配置文件获取的。

方法3:

添加系统配置文件

/etc/ld.so.conf.d/ 路径下添加一个xxx.conf配置文件,将其内容设置为动态库的所在目录路径。

再sudo ldconfig  一下,表示更新配置文件,使其生效。

即可,这个是最安全最有效的了。退出重新登录也还在。

方法4:

在系统默认搜索库的路径下添加一个软链接

sudo ln -s /home/yzl/aandso/plus2/lib/libplus.so /lib64/libplus.so

不太推荐,类似方法1

综上,其实所有方法的目的都是为了在程序运行过程中能够找到动态库,而使用静态库的程序只要链接好之后,就不用再找静态库了,因为静态库已经在可执行程序内部了,目标文件生成后,静态库删掉,程序照样可以运行。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值