静态链接与动态链接的区别

静态库与动态库详解

https://blog.youkuaiyun.com/LU_ZHAO/article/details/104251151

 

什么是库?
库是已经写好的,成熟的,可以复用的代码。程序员编程的时候都要依赖很多基础的底层库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。

回顾将源程序到可执行程序的过程:

预处理
编译
汇编
链接
.c
.i
.s
.o
a.out
链接
链接主要完成两个任务:

合并目标文件。
符号解析与重定位。
静态链接
在链接阶段,将汇编生成的.o文件和所需要的库一起链接打包到可执行文件中去。因此称为静态链接。
一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。它有以下特点:

静态库对函数的链接是在编译时完成的。
移植性好。
浪费空间和资源,因为和所需要函数相关的所有的库都被打包进可执行文件了。
Linux静态库命名规范:必须是"lib[your_library_name].a"。

创建静态库的步骤:

首先编译成目标文件.o:
g++ -c statictest.cpp
1
再使用ar工具将目标文件打包成.a静态库文件(Linux下使用ar工具、Windows下vs使用lib.exe):
ar -crv libstatictest.a statictest.o
1
可以使用makefile文件(CMake等等工程管理工具)来生成静态库,更方便快速。

使用静态库:
g++
-L:库所在目录
-l:链接时需要的库,编译器查找时会在指定的名称前加lib,后面加上.a(静态链接)或.so(动态链接)来确定库的名称。
g++ main.cpp -L../directoryOfLib -lstatictest
1
动态链接
静态库有什么问题?

浪费空间。
库更新以后需要重新编译:库是被复制到可执行文件中去了,如果某个库更新了,则与它相关的所有可执行文件都需要重新编译。
为了解决以上问题,可以使用动态库:

解决浪费空间:动态库在编译时不会被载入,而是在程序运行时才载入。此时如果不同的应用程序调用相同的库,那么在内存中只需要一份该库的实例。
解决全量更新问题:动态库修改后不用修改重新编译生成可执行文件,增量更新。
动态库的特点:

动态库只有一份,可以实现进程之间的资源共享。(因此动态库也称为共享库)
对库函数的链接推迟到程序运行时。
程序升级变得简单。
可以在链接载入时完全由程序员在程序代码中控制。
Linux动态库命名规范:必须是"lib[your_library_name].so"。

每个共享库都有个特殊的名字"soname"。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。
在文件系统中,"soname"是一个链接。对于每个动态库来说,对于编译器来说,有一个指向实际库镜像文件 - “lib[soname].so”。

创建动态库的步骤:

首先编译成目标文件.o,此时要加编译器选项-fPIC(position independent code):

g++ -fPIC -c dynamictest.cpp
1
-fPIC ,产生与位置无关代码(Position-IndependentCode),作用于编译阶段,使产生的代码中只有相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

生成动态库,-shared:

g++ -shared -o libdynamictest.so dynamictest.o
1
使用动态库(同静态库):

g++ main.cpp -L../directoryOfLib -ldynamictest
1
如何告诉系统我创建了一个动态库?或者说动态库是如何定位库的?

系统加载程序的时候,知道了所需依赖库的名称。那么它如何寻找呢?此时就需要系统动态载入器了"dynamiclinker/loader"。

对于elf格式的可执行文件,是由ld-linux.so*来完成的。它先后搜索elf文件的DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。

所以,如何让系统找到库?

放在安装在/lib或者/usr/lib下。
将目录添加到/etc/ld.so.cache文件中:
- 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径。
- 运行ldconfig ,该命令会重建/etc/ld.so.cache文件。
————————————————
 

========================================================================

1.静态链接与动链接的区别

        在C语言中,我们知道要生成可执行文件,必须经历两个阶段,即编译、链接。

        在编译过程中,只有编译,不会涉及到链接。

           在链接过程中,静态链接和动态链接就出现了区别。静态链接的过程就已经把要链接的内容已经链接到了生成的可执行文件中,就算你在去把静态库删除也不会影响可执行程序的执行;而动态链接这个过程却没有把内容链接进去,而是在执行的过程中,再去找要链接的内容,生成的可执行文件中并没有要链接的内容,所以当你删除动态库时,可执行程序就不能运行。

           所以总的来说,动态链接生成的可执行文件要比静态链接生成的文件要小一些。

2.动态库与静态库的区别

        2.1就不设置环境变量的情况下来说

        动态库一般都会存在/usr/lib/ 目录下;而静态库可以在任何目录下,只要你第一次链接的时候,用绝对路径去链接就行了,之后再删除,是不会影响你的生成的执行文件的。

            2.2如若可以设置环境变量的话

            动态库和静态库可以放置到你想放的任何地方,只是动态库需要设置环境变量,而静态库链接的时候需要绝对路径。

            但一般来说,动态库都会放在放在/usr/lib,应该大家都习惯了,这样也方便寻找,而当链接动态库的时候默认的路径就是/usr/lib。

各自的优缺点:

1、静态链接库执行速度比动态链接库快。(执行过程不需要找链接的内容)

2、动态链接库更节省内存。(未写入要链接的内容)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值