静态库和动态库——本质探究、使用方法

动态库的本质探究:

  所有使用某个库的程序可以只共享一份副本(节约空间)。

  动态链接,链接器在程序运行前不会将库中段和符号绑定到确切的地址上。

  实际查看动态库,发现动态库是将所有目标文件整理到一套链接地址上,进而可以知道动态库如果加载进内存,是以一个库作为整体加载的。

 

  再查看调用动态库的可执行程序中导入的符号:

  可以看出,并没有给符号绑定地址,只是进行了标记。

 

动态库的使用:

  动态库的制作

  (1)生成地址无关码:

      gcc -fPIC -c *.c

  (2)生成动态链接库

      gcc -shared *.o -o libxxx.so

  动态库的使用

    首先理解动态库的运行方式:

      动态库在被运行前由动态链接器加载到内存,并完成地址绑定。

      所以首先需要保证动态链接器能够找到动态库。

      使用 ldd 命令查看:

      红线部分为动态链接器,

      其中 libsort.so 没有找到。

      动态链接器会根据环境变量PATH和环境变量LD_LIBRARY_PATH指定的目录查找,所以添加libsort.so的目录。

 

静态库的本质探究:

  每个库在创建时会被绑定到特定的地址,链接器在链接时将程序中引用的库例程绑定到这些特定的地址。

  查看库文件符号:

  可以看出,静态库的函数被重定位到独立的地址空间。

  再查看调用静态的可执行文件的符号:

  可以看出被引用的符号,是被重定位到了可执行文件中。

   

静态库的使用:

  静态库的制作:

    (1)生成.o文件

    (2)生成静态库

      ar rcs libxxx.a *.o

      静态库的使用

      gcc main.c -L ./ -l xxx -o a.out

        其中 -L 指定静态库目录,-l 指定该目录中静态库的名字

 

对于使用静态库和直接编译链接的区别

  使用静态库:

    链接时,链接器会查询库的符号表和.o文件的符号表,找到需要导入的符号,将其实现和.o文件进行合并,分段。生成可执行文件。

      .o文件导入了什么符号,链接后就会添加对应的实现。

  直接编译链接:

    链接时,链接器会扫描所有.o文件的符号表和段表,整理导入符号和导出符号,合并所有段信息,整理出包含所有.o文件信息的段表,并进行重定位。对于匹配了的导入符号位置会进行代码修改。

      .o文件的所有信息都会被重定位到可执行文件中,无论可执行文件是否会运行该二进制处。

 

代码修改:

      eg: a 为本地符号,b为声明符号(需要导入的符号)

    mov a, %eax

    mov %eax, b

    编译后,二进制为:

    A1 34 12 00 00 mov a, %eax

    A3 00 00 00 00 mov %eax, b

    a的地址为0x1234,由于b为外部导入符号,编译时无法确定,所以b的四字节地址用0表示

    链接后,二进制位:

    A1 34 12 01 00 mov a, %eax

    A3 12 9A 00 00 mov %eax, b

    链接时进行了重定位,a地址偏移了0x100000,b地址进行了补充,并且对a,b地址相关的指针也进行了修改。

    现代计算机中,对该功能的支持高度依赖于硬件性质,意思就是链接器与具体硬件高度相关。

转载于:https://www.cnblogs.com/yangxinrui/p/10285881.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值