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. adb: createprocessw failed: 系统找不到指定的路径_gcc编译过程、gcc命令参数、静态库和动态库搜索路径...

    一.gcc编译过程 gcc -E hello.c -o hello.s //预处理 gcc -S hello.s -o hello.i //编译 gcc -c hello.i -o hello.o / ...

  2. C程序编译过程及常见选项--静态库和动态库

    C程序编译过程及常见选项--静态库和动态库 前言 一.gcc详讲 1.1 编译过程 1.2 预处理 1.3 编译(Compilation) 1.4 汇编(Assembly) 1.5 链接(Linkin ...

  3. Linux中gcc的编译、静态库和动态库的制作

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 Linux中gcc的编译.静态库.动态库 文章目录: 1 gcc的编译过程 1.1 gcc的编译过程 1.2 gcc的常用参数 2 gcc 静态库的制 ...

  4. g++ 编译mysql动态库_Linux下g++编译以及使用静态库和动态库的方法详解

    下面小编就为大家带来一篇Linux下g++编译与使用静态库和动态库的方法.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 在windows环境下,我们通常在IDE如VS的 ...

  5. x64 编译 静态链接_C++静态库与动态库

    这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书<程序员的自 ...

  6. gcc编译多文件项目(包含静态库和动态库)

    gcc背景介绍 谈到 GCC,就不得不提 GNU 计划.GNU 全称 GNU's Not UNIX,又被称为"革奴计划",由理查德·斯托曼于 1983 年发起.GNU 计划的最终目 ...

  7. vs如何把c语言编译成静态库,VS中Debug和Realease、及静态库和动态库的区别整理(转)...

    一.Debug和Realease区别产生的原因 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化,使得程序在代码 ...

  8. VS2015编译32位Opencv310(动态库+静态库,文末有下载链接)

    VS2015编译32位Opencv310(动态库+静态库 编译过得,可以直接用的: http://download.csdn.net/download/longzaihuaxia/9802510 之前 ...

  9. NDK 编译和使用静态库、动态库

    NDK 编译和使用静态库.动态库 情况一:编译静态库 情况二:编译动态库 情况三:编译动态库+静态库 情况四:已有第三方静态库(动态库),编译静态库(动态库) 默认所有代码和文件在$project/j ...

  10. Linux基础——gcc编译、静态库与动态库(共享库)

    Linux基础--gcc编译.静态库与动态库(共享库) https://blog.csdn.net/daidaihema/article/details/80902012 Linux基础--gcc编译 ...

最新文章

  1. 最清楚的mmap()详解与源码分析
  2. 如何安装mysql5.7.9_安装mysql-5.7.9-winx64
  3. c语言 异或_C语言经典例题来袭!5大方法告诉你答案
  4. 视频编解码学习之二:编解码框架
  5. Purpose of cmove instruction in x86 assembly? | cmove 指令如何避免错误的分支预测带来的开销?
  6. 话里话外:从“种房子”谈流程与制度的差别
  7. maven排除依赖冲突问题
  8. mysql 临时索引_MYSQL临时表创建索引
  9. Go程序的一生是怎样的?
  10. 刚创建了蕝薱嚣张IT部落
  11. [Oracle]GoldenGate官方文档
  12. ams1117-3.3v电源稳压芯片低压差线性稳压器
  13. Windows2012开机启动项设置
  14. stm32中的“hello world”
  15. 城市轨道交通信号系统学习笔记(三)继电器
  16. luogu4182 [USACO18JAN] Lifeguards P (单调队列优化dp)
  17. 连接一个HTTPS网站的前300毫秒,都发生了什么? | ArcBlock 课堂预告
  18. 【Java基础】基础概念与常识
  19. 基于Python的超市零售数据分析
  20. 【电气专业知识问答】问:电网调度部门对各主要发电厂涉网部分电气设备的监控内容是什么?如何实现?

热门文章

  1. 最急救助(【CCF】NOI Online能力测试3 入门组)
  2. 定义一个圆形类Circle
  3. Python考试基础知识
  4. 像python一样运行js的__main__
  5. leetcode954. Array of Doubled Pairs
  6. openJDK之如何下载各个版本的openJDK源码
  7. extends 和super 泛型限定符-上界不存下界不取
  8. SecureCRT key登录linux ssh设置
  9. Django中views笔记
  10. Postgres 数据库字符集更改 ERROR: new encoding (UTF8) is incompatible