【Linux】动态库和静态库

Linux 动态库和静态库

文章目录

  • Linux 动态库和静态库
    • 什么是动态库和静态库
    • 动态库和静态库有什么不同
      • 动态库
      • 静态库
    • 生成自己的静态库
    • 生成自己的动态库

什么是动态库和静态库

我们在写代码的时候,会调用很多的库函数,像printf scanf 等函数,但是我们的代码中并没有这些函数的实现,这些函数是语言提供的函数,这些函数就存放到对应的库中,而这些库就叫做动态库和静态库。

  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

动态库和静态库有什么不同

动态库

动态库在程序运行的时候,运行到了库函数的函数入口,而我们没有函数的实现,这时程序就会到对应的动态库里去链接动态库里这个函数的实现代码,把库中的代码拿到虚拟地址空间中的共享区,执行代码。

优点:不需要把库函数的代码编译进我们的可执行程序,可执行程序的体积小,多份代码可以共用一个库节省了空间。如果库函数更新,在进行升级的时候不需要重新编译程序,直接升级库即可。

缺点:对库的依赖性强,如果没有动态库,那么这个用了动态库的可执行程序将无法运行。


静态库

静态库是程序在编译链接阶段,就把程序所需的库函数代码,拷贝到程序中一起编译,这时的程序不再需要静态库就能运行。所需要的库中的代码是直接被拿到代码段执行的,和整个可执行程序是一体的。

优点:编译成功的可执行程序可以独立运行不再需要静态库,没有了库的依赖性。

缺点:生成的程序占用空间大,不能多个程序共用一个库,库升级的时候需要重新编译程序。


动态库和静态库的本质区别就是看库是否被编译到了程序内部


生成自己的静态库

首先,一个静态库,其实就是自己写了一些方法,我们把这些方法的源文件和已经编译汇编好的.o文件打包起来,打包好的文件就是库文件,别人只需要配合.h头文件和静态库文件进行编译生成可执行程序,就能使用我们写的方法。

  • 第一步是先实现自己的方法,源文件和头文件

【Linux】动态库和静态库_第1张图片

【Linux】动态库和静态库_第2张图片

  • 接着把源文件编译成.o文件

【Linux】动态库和静态库_第3张图片

  • 然后把这些.o文件生成静态库文件
ar -rc libmymath.a add.o sub.o
#   ar是gnu归档工具,rc表示(replace and create)

【Linux】动态库和静态库_第4张图片

查看静态库中的目录列表

ar -tv libmymath.a
# t:列出静态库中的文件
# v:verbose 详细信息

【Linux】动态库和静态库_第5张图片

一般我们在给别人提交一个库文件时,会将库文件和头文件放到一个目录结构中,如下

【Linux】动态库和静态库_第6张图片

include中放库所需的头文件,lib中放库文件。

而前面生成的.o文件和源文件就没有用了。

  • 下面就能用我们打包好的库进行编译程序了

在makefile中填写编译指令

gcc -o $@ $^ -I ./mylib/include -L ./mylib/lib -l mymath -static
# -I 表示头文件的存放路径(头文件搜索路径)
# -L 表示库文件的存放路径(库文件搜索路径)
# -l 表示库文件的具体名称(库文件名,静态库去掉lib前缀和.a后缀即为文件名)

在后面加上**-static**表示静态链接编译

编译执行,可以发现程序正常执行

【Linux】动态库和静态库_第7张图片

【Linux】动态库和静态库_第8张图片

生成自己的动态库

动态库的结构和静态库类似,都是需要.o文件和.h文件。

  • 实现自己的方法,源文件和头文件

【Linux】动态库和静态库_第9张图片

【Linux】动态库和静态库_第10张图片

  • 这次我们直接用makefile生成动态库以及动态库发布目录
libmymath.so:myadd.o mysub.o
        gcc -shared -o $@ $^
 		# -shared表示生成共享库格式

myadd.o:myadd.c
        gcc -fPIC -c $<
        # fPIC:产生位置无关码(position independent code)
mysub.o:mysub.c
        gcc -fPIC -c $<

.PHONY:clean
clean:

        rm *.o libmymath.so

.PHONY:output
output:
        mkdir -p mylib/include
        mkdir -p mylib/lib 
        cp *.h mylib/include
        cp *.so mylib/lib 
  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 库名规则:libxxx.so

运行makefile

【Linux】动态库和静态库_第11张图片

【Linux】动态库和静态库_第12张图片

至此,我们就把我们的程序和头文件打包成了一个动态库 并且把动态库放进了发布文件

  • 接下来我们写一个程序并且使用动态库编译

【Linux】动态库和静态库_第13张图片

  • 为这个程序编写makefile
mytestso:mytestso.c                                             
  gcc -o $@ $^ -I ./mylibso/mylib/include -L ./mylibso/mylib/lib     -l mymath
.PHONY:clean
clean:
  rm mytestso

和静态库的编译类似,需要设置头文件和库文件的搜索路径 但是末尾不用加static

  • 编译运行

【Linux】动态库和静态库_第14张图片

编译通过,但是运行时显示找不到我们的动态库

使用ldd命令查看可执行文件的依赖库,发现not found =

【Linux】动态库和静态库_第15张图片

这是因为我们编译时设置的搜索路径是把路径告诉了gcc编译器,但是动态库是在程序运行时才去找库,操作系统并不知道我们的库文件放在哪,这时就要设置环境变量来告诉操作系统我们的库位置

  • 设置库的搜索路径到系统默认寻找动态库的环境变量
export LD_LIBRARY_PATH=/home/xiaomage/workspace/Lib/mylibso/mylib/lib

这时再用ldd查看依赖库,发现已经找到库路径

【Linux】动态库和静态库_第16张图片

  • 运行mytestso
    【Linux】动态库和静态库_第17张图片

执行成功

你可能感兴趣的:(Linux,linux)