4.5 静态库链接

4.5 静态库链接

  • 一种语言的开发环境往往会附带语言库(language library), 这些库通常是对操作系统API的包装。例如C语言标准库的函数strlen()并没有调用任何操作系统的API,但是很大一部分库函数都要调用操作系统API,例如print()
  • 静态库可以简单地看做一组目标文件的集合,即很多目标文件经过压缩打包后形成的一个文件。例如C语言静态库libc.a,该库是glibc项目的一部分。glibc的介绍
  • 接下来将介绍一个程序的目标文件如何与c语言运行库链接形成一个可执行文件。
    • C语言的运行库,包含了很多跟操作系统功能相关的代码,比如输入输出,文件操作,日期,内存管理等。glibc本身就是C语言开发的,它由成千上百个C语言源代码文件组成,也就是说,编译后有相同数量的目标文件,比如输入输出的scanf.o,printf.o;文件操作有fread.o,fwrite.o;时间日期有date.o,time.o; 内存管理有malloc.o等。把这些零散的目标文件直接提供给库的使用者,很大程度上会造成文件传输,管理和组织方面的不便,于是人们通常用“ar”压缩程序将这些目标文件压缩到一起,并且对其进行编号和索引,以便查找和检索,就形成了libc.a这个静态库文件。我们可以使用ar -t libc.a命令查看该库文件包含哪些目标文件.
    • 如何在这么多目标文件中找到print函数所在的目标文件? 可以通过objdump 或者 readelf加上文本查找工具如"grep"grep
    • 直接链接hello.o和print.o会出错。原因:print.o依赖于其他的目标文件,同时这些目标文件可能依赖于其他目标文件。链接器会处理这些繁琐的操作,自动寻找所有需要的符号以及它们所在的目标文件,将这些目标文件从libc.a中解压出来,最终将它们链接在一起形成一个可执行文件。
    • 实际上linux系统上的库比我们想象的要复杂,当我们编译和链接一个普通C程序时,不仅用到C语言库libc.a,而且会用到其他一些辅助的目标文件和库。我们可以通过-verbose将整个编译链接过程的中间过程打印出来。gcc -static --verbose -fno-builtin hello.c,-static 指的静态链接; --verbose将整个编译链接过程的中间步骤打印出来(显示程序详细编译过程)。verbose:冗余的,啰嗦的;-fno-builtin关闭内置函数优化选项;从结果上,有三个关键步骤:
    • 调用ccl程序,这个程序是GCC的C语言编辑器,将hello.c编译成一个临时的汇编文件.s
    • 调用as程序,这个程序是GNU的汇编器,将汇编文件.s汇编成临时目标文件.o
    • 调用collect2程序完成链接,该程序是对ld链接器的一个包装,会调用ld链接器来完成对目标文件的链接,然后再对链接结果进行一些处理,主要是收集所有与程序初始化相关信息并且构造初始化的结构。
  • Q: 为什么** 静态运行库里面一个目标文件只包含一个函数**?例如libc.a的printf.o只包含printf函数。
  • A:如果很多函数都放在一个目标文件中,很可能很多没有用的函数都被一起链接进输出结果中。运行库有成百上千个函数,每个函数独立地放在一个目标文件中可以减少空间浪费。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值