编译过程、静态库和动态库
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最终会有两份。
- 更新麻烦:
如果一个静态库更新,则所有有关的库都要重新链接
动态链接
- 所有的依赖不加载到可执行文件中,仅仅保留符号链接
- 用到符号链接时,再动态加载链接库,并计算有关地址,延迟绑定。
- 装载时定位,用到对应的组件,再装在动态库,此时定位符号地址;而静态库是初始化全部加载
编译过程、静态库和动态库相关推荐
- 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 / ...
- C程序编译过程及常见选项--静态库和动态库
C程序编译过程及常见选项--静态库和动态库 前言 一.gcc详讲 1.1 编译过程 1.2 预处理 1.3 编译(Compilation) 1.4 汇编(Assembly) 1.5 链接(Linkin ...
- Linux中gcc的编译、静态库和动态库的制作
欢迎大家关注笔者,你的关注是我持续更博的最大动力 Linux中gcc的编译.静态库.动态库 文章目录: 1 gcc的编译过程 1.1 gcc的编译过程 1.2 gcc的常用参数 2 gcc 静态库的制 ...
- g++ 编译mysql动态库_Linux下g++编译以及使用静态库和动态库的方法详解
下面小编就为大家带来一篇Linux下g++编译与使用静态库和动态库的方法.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 在windows环境下,我们通常在IDE如VS的 ...
- x64 编译 静态链接_C++静态库与动态库
这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书<程序员的自 ...
- gcc编译多文件项目(包含静态库和动态库)
gcc背景介绍 谈到 GCC,就不得不提 GNU 计划.GNU 全称 GNU's Not UNIX,又被称为"革奴计划",由理查德·斯托曼于 1983 年发起.GNU 计划的最终目 ...
- vs如何把c语言编译成静态库,VS中Debug和Realease、及静态库和动态库的区别整理(转)...
一.Debug和Realease区别产生的原因 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化,使得程序在代码 ...
- VS2015编译32位Opencv310(动态库+静态库,文末有下载链接)
VS2015编译32位Opencv310(动态库+静态库 编译过得,可以直接用的: http://download.csdn.net/download/longzaihuaxia/9802510 之前 ...
- NDK 编译和使用静态库、动态库
NDK 编译和使用静态库.动态库 情况一:编译静态库 情况二:编译动态库 情况三:编译动态库+静态库 情况四:已有第三方静态库(动态库),编译静态库(动态库) 默认所有代码和文件在$project/j ...
- Linux基础——gcc编译、静态库与动态库(共享库)
Linux基础--gcc编译.静态库与动态库(共享库) https://blog.csdn.net/daidaihema/article/details/80902012 Linux基础--gcc编译 ...
最新文章
- 最清楚的mmap()详解与源码分析
- 如何安装mysql5.7.9_安装mysql-5.7.9-winx64
- c语言 异或_C语言经典例题来袭!5大方法告诉你答案
- 视频编解码学习之二:编解码框架
- Purpose of cmove instruction in x86 assembly? | cmove 指令如何避免错误的分支预测带来的开销?
- 话里话外:从“种房子”谈流程与制度的差别
- maven排除依赖冲突问题
- mysql 临时索引_MYSQL临时表创建索引
- Go程序的一生是怎样的?
- 刚创建了蕝薱嚣张IT部落
- [Oracle]GoldenGate官方文档
- ams1117-3.3v电源稳压芯片低压差线性稳压器
- Windows2012开机启动项设置
- stm32中的“hello world”
- 城市轨道交通信号系统学习笔记(三)继电器
- luogu4182 [USACO18JAN] Lifeguards P (单调队列优化dp)
- 连接一个HTTPS网站的前300毫秒,都发生了什么? | ArcBlock 课堂预告
- 【Java基础】基础概念与常识
- 基于Python的超市零售数据分析
- 【电气专业知识问答】问:电网调度部门对各主要发电厂涉网部分电气设备的监控内容是什么?如何实现?
热门文章
- 最急救助(【CCF】NOI Online能力测试3 入门组)
- 定义一个圆形类Circle
- Python考试基础知识
- 像python一样运行js的__main__
- leetcode954. Array of Doubled Pairs
- openJDK之如何下载各个版本的openJDK源码
- extends 和super 泛型限定符-上界不存下界不取
- SecureCRT key登录linux ssh设置
- Django中views笔记
- Postgres 数据库字符集更改 ERROR: new encoding (UTF8) is incompatible