请教关于linux中静态库与动态库的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教关于linux中静态库与动态库的问题相关的知识,希望对你有一定的参考价值。

我的理解是这样的:编译程序时,如果有用到静态库,则编译器会把静态库中你所需要的函数直接加入到你的源程序中再进行编译。 如果是用到了动态库,则编译器在编译时,只是确定一下是否能在相关路径下找到你所需的库,然后当程序运行时再去找相关的库,调用库中的函数。

请问下我的理解是不是正确的?

哈哈,简单的来说可以按你这么理解,静态库就是在打包在程序里面的,而动态库是和程序分离开的,是程序需要的时候动态装配进内存的。

说一下我自己的理解和经验吧:动态库之所以会用到,是因为有些库会被多个程序用到,拿windows的例子来说吧,比方说你开两个游戏,一个魔兽,一个极品飞车,这两个都要用到activex 这个库,如果做为动态库,两个程序共用一个,但是静态库就要分别为两个游戏都生成库,如果更多的话,这样就浪费了内存很多空间。

静态库是和程序一起装入内存的(其实静态库已经成为程序的一部分),而动态库是动态装入内存的,如果内存不大,又使用静态库,必然会发生很多的缺页中断,这样效率会很低哦,你有兴趣可以多多研究一下内存的一些算法,linux kernel有现成的分页算法,会对你很有帮助的。

如果缺页中断不太明白的话可以看看操作系统的书,或者追问我,大家一起切磋交流~
参考技术A 可以这样理解.

当和静态库一起编译后,可执行程序将会比较大,且用ldd查看的时候,结果为“not a dynamic executable ”.
当和动态库一起编译后, 可执行程序比较小, 用ldd查看的时候, 显示可执行程序依赖很多库, 比如
$ ldd a.out
linux-vdso.so.1 => (0x00007fff964bf000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f87f0695000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f87f0478000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f87f0274000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f87efeed000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f87efcd6000)
/lib64/ld-linux-x86-64.so.2 (0x00007f87f0936000)

[Linux 高并发服务器]制作静态库与动态库

[Linux 高并发服务器]制作静态库与动态库

什么是库

  • 库文件是计算机类的一类文件,可以当作代码仓库,提供给使用者一些可以直接拿来用的变量
    函数和类
  • 库不能单独运行
  • 库文件用两种:静态库和动态库(共享库),区别是静态库在程序链接阶段被复制到了程序中,动态库在链接阶段没被复制到程序当中,而是在运行时由系统动态添加到内存中使用
  • 库的好处:代码保密,方便部署和分发

静态库的制作和使用

命名规则

LINUX系统libxxx.a,前缀lib和后缀.a固定,xxx为库名
Windows系统:libxx.lib

静态库的制作

gcc获得.o文件
将.o文件大宝,使用ar工具

ar rcs libxxx.a xxx.o xxx.o

r-将文件插入备存文件
c-创建备存文件
s-创建索引

静态库的使用

创建如下文件目录格式

使用打包好的libcalc.a静态库需要静态库文件本身以及head.h文件
main.c文件为需要使用静态库的测试文件
使用如下命令把静态库编译链接到main.c

gcc main.c -o app -I ./include -l calc -L lib

-I在哪里找头文件
-l指定库的名称,主要不要写成libcalc.acalc才是库名
-L到哪里找库

动态库的制作和使用

命名规则

Linux:libxxx.so,在Linux下是一个可执行文件
Windows:libxxx.dll

动态库的制作

  • gcc 得到 .o文件,得到和位置无关的代码
gcc -c -fpic/-fPIC a.c b.c

-fpic参数主要发生在编译->汇编的过程中

  • gcc 得到动态库
gcc -shared a.o b.o -o libcalc.so

.so文件在LINUX下为可执行文件

使用动态库

参照静态库的使用方法输入

gcc main.c -o main -I ./include -L lib/ -l calc

但是在使用main的时候报错了

/main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory

原因是对于动态库而言,GCC进行链接是,动态库代码不会被打包到可执行文件当中
程序启动之后,动态库会被动态加载到内存中

我们可以通过ldd命令来检查动态库依赖关系
当系统加载可执行带代码的时候,能够知道依赖库的名字,但还是需要知道绝对路径。此时就需要系统的动态载入器来获取该绝对路径。对于elf格式的可执行程序,是由ld-linux.so来完成的(也就是图片中最后一行的玩意)

流程如下:

  1. DT_RPATH段
  2. 环境变量LD_LIBRARY_PATH
  3. /etc/ld.so.cache文件列表
  4. /lib/,/user/lib

所以就是动态库没被加载到吗,我们一个个流程去找就行了
对于DT_RPATH段,我们一般不用检查。

我们检查一下环境变量,使用env命令即可查看我们的环境变量,发现貌似没有配置LD_LIBRARY_PATH,我们添加一下

方法一:直接在终端使用export配置
这种方法是临时的配置,关掉或者换个终端就没有了

export LD_LIBRARY_PASH=$LD_LIBRARY_PASH:这里进入到动态库文件目录然后pwd获取位置粘贴到这

tip:如果要查询某个环境变量的值可以用echo

echo $LD_LIBRARY_PATH

方法二:在目录下的.bashrc文件中添加

export LD_LIBRARY_PASH=$LD_LIBRARY_PASH:这里进入到动态库文件目录然后pwd获取位置粘贴到这

然后使用

source .bashrc

保存应用设置
注意:如果你的shell不是bash改成了zsh之类的要去相应的配置文件修改例如.zshrc
这种方式是用户级别的

方法三:在/etc/profile中按照方法二添加并保存

这种方式是系统级别,如果用户级别已经设置了可能会失效
我们使用unset来删除已有的环境变量

方法四:把生成的动态库放到/lib/或者/usr/lib目录

不推荐这种方法,因为本身里面就有很多库

添加后重新使用ldd查询依赖,发现找到了,可以正常使用

静态库和动态库优缺点

静态库优点

  • 静态库被打包到应用程序中加载速度快
  • 发布程序无需提供静态库,移植方便

静态库缺点

  • 消耗系统资源,浪费内存(可能好几个程序用相同的静态库,都被打包进去了)
  • 更新部署发布麻烦

动态库优点

  • 可以实现进程之间资源共享(共享库)
  • 更新部署发布简单
  • 可以控制何时加载动态库

动态库缺点

  • 加载速度比静态库慢
  • 发布程序时需要提供依赖的动态库

一般使用场景

库很小的话使用静态库
库比较大的花使用动态库

以上是关于请教关于linux中静态库与动态库的问题的主要内容,如果未能解决你的问题,请参考以下文章

深入探讨Linux静态库与动态库的详解(转)

技巧:Linux 动态库与静态库制作及使用详解

Linux_动态库与静态库(制作与安装)

Linux分文件编程:静态库与动态库的生成和使用

Linux静态函数库与动态函数库

关于Linux静态库和动态库的分析