编译过程、静态库和动态库

C/C++代码到可执行文件

从代码到最终的程序,分为4个步骤,分别是:

  • 预编译:编译预处理,比如#define#ifndef之类的,C++的inline也是在这期间处理的
  • 编译:把代码转换成汇编,包括词法分析、语法分析和语义分析等
  • 汇编:把汇编语言转换成机器码,输出的是目标文件。比如*.o的文件
  • 链接:把目标文件聚合成可执行文件

链接:链接本质上是把多个ELF文件,按照符号符号等拼接成执行文件的过程,这个过程会给出各个符号最终的地址,供程序寻址。

链接和链接器

  • 重定位:以单个执行文件为例,程序中某个代码片段有删减的时候,变化的代码片段之后的代码段的地址都发生了变化,重定位就是重新计算变化后的代码的地址。
  • 符号:汇编语言中的概念,表示一段代码或一个变量的地址

程序模块化开发时,代码分成多文件多模块,此时每个模块进行对应的开发、测试等。

模块化之后,每个对应的模块都有自己的*.o目标文件,多模块拼接时,需要解决不同模块之间的符号链接问题。不同模块之间的符号引用,最终都要使程序找到对应的地址。

链接的文件是目标文件,目标文件存储的是机器码

链接符号:

  • 本目标文件的全局符号可以被其它目标文件引用
  • 目标文件引用符号,在本文件中无定义,去其他文件中找,称为全局符号

目标文件的结构

ELF:Executable Linked Format

ELF文件说明格式
可重定位文件包含代码和数据,链接成可执行文件或者共享目标文件.o .obj
可执行文件可以被操作系统执行.exe
共享目标文件链接器使用共享目标文件,与可重定位文件或者共享目标文件链接,称为新的目标文件.so .dill
核心转储文件进程意外终止时,OS把该进程地址空间的内容和一些其它信息,转储到核心文件中Linux下core dump

ELF文件结构:

几个核心的片段:

  • ELF Header:一些核心的信息,比如操作系统的平台,段表:描数文件各个段信息的数据。
  • .text:代码片段,指的是机器码
  • .data:数据段,初始化的全局变量,一些资源之类的
  • .bss:未初始化的片段,这个不占存储空间

data和text片段分离的优势:

  • 多进程下,text共享,进程只需要有自己的data即可
  • 不同访问情况有不同的权限,text只读,data读写,这样方便处理权限

可执行文件的装载和进程

进程置于内存中,以页的形式管理,如果要找的进程中地址不存在,则缺页中断,进行置换,置换到有关的内存页之后,重新加载对应的数据。

ELF的各个段大小不一样,我们称为section;而进程是分段管理的,我们称为segment。为了更高效的利用内存空间,我们把权限小姑娘同的的各个section的内容,有选择地放在一起加载,如下图:

调用ELF的过程:
bash->fork子进程A->A执行execute对应的ELF->A返回执行结果->bash等用户输入

静态链接

不同模块编译出不同的目标文件,比如Linux下的.a文件,最终把多个模块的目标文件组合成一个可执行文件。不同模块会加入到可执行文件的不同位置中,这样对应的符号就可以找到对应的地址的了,如下图:。

为了高效利用空间,都会像上图所示,把相同段的内容合并到一起。

优势:
没有外部依赖,运行速度快

缺陷:

  • 文件膨胀,如果有模块ProgramA和ProgramB都依赖lib.o,且有程序依赖PA和PB,则lib.o最终会有两份。
  • 更新麻烦:
    如果一个静态库更新,则所有有关的库都要重新链接

动态链接

  • 所有的依赖不加载到可执行文件中,仅仅保留符号链接
  • 用到符号链接时,再动态加载链接库,并计算有关地址,延迟绑定。
  • 装载时定位,用到对应的组件,再装在动态库,此时定位符号地址;而静态库是初始化全部加载

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值