linux下静态链接库和动态链接库的区别有哪些

77次阅读
没有评论

共计 3069 个字符,预计需要花费 8 分钟才能阅读完成。

这篇文章主要讲解了“linux 下静态链接库和动态链接库的区别有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“linux 下静态链接库和动态链接库的区别有哪些”吧!

区别:1、动态库的后缀为“.so”,静态库的后缀为“.a”。2、如果静态函数库改变了,那么程序必须重新编译;而动态函数库的改变并不影响程序。3、相对于静态库,动态库在编译的时候并没有被编译进目标代码中,用户的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。

一、库的基础概念:

在 windows 平台和 linux 平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于 windows 和 linux 的本质不同,因此二者库的二进制是不兼容的。通俗的说就是把这些常用函数的目标文件打包在一起,提供相应函数的接口,便于程序员使用。在使用函数时,只需要包对应的头文件即可。按照库的使用方式又可分为动态库和静态库,在不同平台下对应后缀也有所不同。

WINDOWS 下:.dll 后缀为动态库,.lib 后缀为静态库;

LINUX 下:.so 后缀为动态库,.a 后缀为静态库。

二、静态库与静态链接

1 静态库:

静态库可以简单的看成一组目标文件的集合,即很多目标文件经过压缩打包后形成的文件。比如在我们日常编程中,如果需要使用 printf 函数,就需要包 stdio.h 的库文件,使用 strlen 时,又需要包 string.h 的库文件,可是如果直接把对应函数源码编译后形成的.o 文件直接提供给我们,将会对我们的管理和使用上造成极大不便,于是可以使用“ar”压缩程序将这些目标文件压缩在一起,形成 libx.a 静态库文件。

注:静态库命名格式:lib + 库名称”+ .a(后缀) 例:libadd.a 就是一个叫 add 的静态库

2 静态链接:

对于静态库,程序在编译链接时,将库的代码链接到可执行文件中,程序运行时不再需要静态库。在使用过程中只需要将库和我们的程序编译后的文件链接在一起就可形成一个可执行文件。

通过一个例子来了解下如何将我们自己写的头文件和代码同时进行编译链接,最终生成可执行文件:

/main.c/
#include  stdio.h 
#include  add.h 
int main()
 int ret = add(3, 4);
 printf(3 + 4 = %d\n ,ret);
 return 0;
/add.c/
#include  add.h 
int add( int x, int y)
 return x + y;

main : main.c libadd.a gcc main.c -L . -ladd -o main //- L 为指定路径  . 为当前目录下  -l+ 库名字,编译器可在指定目录下自己寻找名为 add 的库文件 libadd.a :  gcc -c add.c -o add.o //ar -rc 将多个编译后的文件打包为一个静态库文件 ar -rc libadd.a add.o .PHONY:clean clean: rm main libadd.a

make 后输出截图:

3 缺点:

1、内存和磁盘空间浪费:静态链接方式对于计算机内存和磁盘的空间浪费十分严重。

假如一个 c 语言的静态库大小为 1MB,系统中有 100 个需要使用到该库文件,采用静态链接的话,就要浪费进 100M 的内存,若数量再大,那浪费的也就更多。例如下图:程序 1 和程序 2 都需要用到 Lib.o,采用静态链接的话,那么物理内存中就会存放两份对应此文件的拷贝。

2、更新麻烦:

比如一个程序 20 个模块,每个模块只有 1MB,那么每次更新任何一个模块,用户都得重新下载 20M 的程序。

三、动态库与动态链接

1 动态库:

程序在运行时才去链接动态库的代码,多个程序共享库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。

注:动态库命名格式:lib + 库名称”+ .so(后缀) 例:libadd.so 就是一个叫 add 的动态库

2 动态链接:

由于静态链接具有浪费内存和模块更新困难等问题,提出了动态链接。基本实现思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将他们链接在一起形成一个完整的程序,而不是像静态链接那样把所有的程序模块都链接成一个单独的可执行文件。所以动态链接是将链接过程推迟到了运行时才进行。

同样,假如有程序 1,程序 2,和 Lib.o 三个文件,程序 1 和程序 2 在执行时都需要用到 Lib.o 文件,当运行程序 1 时,系统首先加载程序 1,当发现需要 Lib.o 文件时,也同样加载到内存,再去加载程序 2 当发现也同样需要用到 Lib.o 文件时,则不需要重新加载 Lib.o,只需要将程序 2 和 Lib.o 文件链接起来即可,内存中始终只存在一份 Lib.o 文件。

动态库和动态链接的例子依然使用上面的代码,输出结果也相同,唯一需要改变的就是 Makefile 文件。

/Makefile/
main : main.c libadd.so
 gcc main.c -L . -ladd -o main
libadd.so : 
 gcc -fPIC -shared add.c -o libadd.so
 //-shared 表示输出结果是共享库类型的  -fPIC 表示使用地址无关代码奇数来生产输出文件
.PHONY:clean
clean:
 rm main libadd.so

当我们生成可执行文件后,可使用 ldd 命令查看该可执行文件所依靠的动态库。

前面提到 windows 和 Linux 下库文件的后缀不同,更根本的原因在于二者文件格式都不同。可以通过 file 一个动态库查看 Linux 下动态库的文件类型其实是 ELF 格式。ELF 动态链接文件被称为动态共享对象 (DSO,Dynamic Shared Objects),简称共享对象;在 windows 下,动态链接文件被称为动态链接库(Dynamic Linking Library),也就是.dll 文件后缀的全称。

3 优点:

①毋庸置疑的就是节省内存;

②减少物理页面的换入换出;

③在升级某个模块时,理论上只需要将对应旧的目标文件覆盖掉即可。新版本的目标文件会被自动装载到内存中并且链接起来;

④程序在运行时可以动态的选择加载各种程序模块,实现程序的扩展。

四、静态库和动态库的区别

1. 静态库

这类库的名字一般是 libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为 如果静态函数库改变了,那么你的程序必须重新编译。

2. 动态库

这类库的名字一般是 libxxx.so ; 相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。

感谢各位的阅读,以上就是“linux 下静态链接库和动态链接库的区别有哪些”的内容了,经过本文的学习后,相信大家对 linux 下静态链接库和动态链接库的区别有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-12发表,共计3069字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)