Linux下生成可执行程序的每一步过程以及链接库的初步认识

2023-09-12 22:46:43

程序的翻译

程序在形成可执行程序之前都经历过一系列十分复杂的过程,也就是我们程序的翻译,程序的翻译经过以下阶段:

  1.  预处理(进行宏替换)
  2.  编译(生成汇编)
  3.  汇编(生成机器可识别代码)
  4.  连接(生成可执行文件或库文件)

就以C语言代码为例,当我们写好了一份C语言代码,第一部要进行头文件的包含,然后在主函数下咔咔一顿写,再开始翻译,也就是形成可执行程序的过程.

我们要了解翻译过程,大致是要将我们写的代码转换成汇编,然后将汇编形成二进制码,也就是计算机可以识别的代码,最后将目标二进制文件和链接库通过链接器连接生成可执行程序。

 预处理阶段

预处理执行的就是:1.将文件的头文件展开 2.宏替换 3.条件编译 4.代码注释的删除

而头文件展开是干啥呢,这里就要大略的谈谈头文件和库文件了,头文件就是我们的stdio.h,而我们包含的这个头文件功能起到一些函数、变量类型定义的作用,而函数的具体实现是在库文件里的,例如我们的printf函数也是需要实现的,就是在stdio.h定义的,如果我们要使用函数的话,编译器就需要到特定的库文件中去寻找该函数的实现,而库文件的内容实质上都是一些二进制。所以回到问题,头文件展开的实质就是将stdio.h里面的内容拷贝一份放在咱们的代码里。

宏替换就比较简单,就是将#define定义的宏变量,宏函数等内容进行替换。

条件编译就是将#if #else #endif等内容的执行

代码注释删除就不解释了哈

linux下我们编译C语言代码时可以用gcc编译器,编写C++代码时可以用g++编译器,而且这些编译器还可以执行到具体某个过程终止:例如想让代码就执行完预处理过程就终止的话可以 gcc -E test.c -o test.i //其实-E是指预处理过程,而-o是预处理的文件存放在test.i的文件中

test.c代码

 预处理之后:

其实并不仅仅只有这些,还有头文件展开的内容,由于内容过于丰富所以就未截取。 

编译

在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。

  • 编译过程为 扫描程序-->语法分析-->语义分析-->源代码优化-->代码生成器-->目标代码优化;
  • 扫描程序进行词法分析,从左向右,从上往下扫描源程序字符,识别出各个单词,确定单词类型
  • 语法分析是根据语法规则,将输入的语句构建出分析树parse tree或者语法树syntax tree
  • 语义分析是根据上下文分析函数返回值类型是否对应这种语义检测,可以理解语法分析就是描述一个句子主宾谓是否符合规则,而语义用于检测句子的意思是否是正确的
  • 目标代码优化就是执行死代码删除、函数内联、for循环的循环控制变量调度到寄存器访问、强度削弱...(而死代码的删除并不是注释删除而是移除根本执行不到的代码,或者对程序运行结果没有影响的代码    内联函数,也叫编译时期展开函数, 指的是建议编译器将内联函数体插入并取代每一处调用函数的地方,从而节省函数调用带来的成本,使用方式类似于宏,但是与宏不同的是内联函数拥有参数类型的校验,以及调试信息,而宏只是文本替换而已    for循环的循环控制变量,通常被cpu访问频繁,因此如果调度到寄存器中进行访问则不用每次从内存中取出数据,可以提高访问效率     强度削弱是指执行时间较短的指令等价的替代执行时间较长的指令,比如 num % 128 与 num & 127 相较,则明显&127更加轻量)

上面这块内容为摘抄大佬文案,我也不太懂,看看猪肉就行了。

而这一过程的指令就是:gcc -S test.i -o test.s//这里其实-S后面跟test.c也行,只不过我们刚刚已经执行了预处理过程,紧接着就是编译,所以直接对test.i操作即可。

这其实就是编译的过程:形成汇编代码。

汇编

汇编就是将编译阶段形成的汇编代码转换成二进制文件,此时就可以被计算机识别。

而这一过程的指令就是:gcc -c test.s -o test.o//这里其实-c后面跟test.c也行,只不过我们刚刚已经执行了编译过程,紧接着就是汇编,所以直接对test.i操作即可。

这里是部分截图,而且需要查看该二进制码的指令是od,如果一般的查看方式的话是一堆乱码。

链接

链接就是将目标文件(test.o)与链接库通过链接器链接起来的过程。

而这里主要就是了解一下什么是链接库。链接库也划分成静态库和动态库两种。

链接库

在我们实现C语言程序的时候,一般是要在开头包含头文件的,而对于头文件的作用就是声明一些你用到的函数,就像printf函数,但是函数的定义(实现)在哪里呢,其实就是在库文件(libc.so.6
)中,而在使用的过程中系统会默认到该路径下去寻找,这样就有函数的定义的,也就可以正常使用了。

静态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”

就是静态库进入.o的二进制目标文件中,链接成可执行程序的时候,链接器会复制静态库内的函数和数据进入可执行程序中
 

动态库

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。

更多推荐

shared_ptr用法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、初步了解二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,

高精度PWM脉宽调制信号转模拟信号隔离变送器1Hz~10KHz转0-5V/0-10V/1-5V/0-10mA/0-20mA/4-20mA

主要特性:>>精度等级:0.1级。产品出厂前已检验校正,用户可以直接使用>>辅助电源:8-32V宽范围供电>>PWM脉宽调制信号输入:1Hz~10KHz>>输出标准信号:0-5V/0-10V/1-5V,0-10mA/0-20mA/4-20mA等,具有高负载能力>>全量程范围内极高的线性度(非线性度<0.2%)>>标准D

数据结构——图的应用

文章目录前言一、图的应用1.最小生成树普里姆(Prim)算法克鲁斯卡尔(Kruskal)算法2.最短路径Dijkstra算法求单源最短路径3.拓扑结构4.关键路径总结前言图的应用1.1最小生成树1.2最短路径1.3拓扑结构1.4关键路径一、图的应用1.最小生成树定义:从图中选取若干条边,将所有顶点连接起来,并且所选取的

LLM 09-新的模型架构

LLM09-新的模型架构回想一下第6章模型架构,神经语言模型的核心接口是一个将token序列映射到上下文嵌入的编码器:[the,mouse,ate,the,cheese]⇒ϕ[(10.1),(01),(11),(1−0.1),(0−1)].[\text{the},\text{mouse},\text{ate},\tex

51单片机光照强度检测自动路灯开关仿真( proteus仿真+程序+报告+讲解视频)

51单片机光照强度检测自动路灯开关仿真(proteus仿真+程序+报告+讲解视频)仿真图proteus7.8及以上程序编译器:keil4/keil5编程语言:C语言设计编号:S0052讲解视频基于51单片机的光照检测自动路灯控制仿真设计(proteus仿真+程序+报告+讲解视频)1.主要功能:基于51单片机的万年历时钟

web安全漏洞-SQL注入攻击实验

实验目的学习sql显注的漏洞判断原理掌握sqlmap工具的使用分析SQL注入漏洞的成因实验工具sqlmap是用python写的开源的测试框架,支持MySQL,Oracle,PostgreSQL,MicrosoftSQLServer,MicrosoftAccess,IBMDB2,SQLite,Firebird,Sybas

web系统安全设计原则

一、前言近日,针对西工大网络被攻击,国家计算机病毒应急处理中心和360公司对一款名为“二次约会”的间谍软件进行了技术分析。分析报告显示,该软件是美国国家安全局(NSA)开发的网络间谍武器。当下,我们发现对于我们发布到互联网的软件和系统的安全审查越来越严格。因为web系统天生的伴随着很多漏洞的产生,这是就给很多不法分子留

kubernetes核心概念 Service

kubernetes核心概念Service一、service作用使用kubernetes集群运行工作负载时,由于Pod经常处于用后即焚状态,Pod经常被重新生成,因此Pod对应的IP地址也会经常变化,导致无法直接访问Pod提供的服务,Kubernetes中使用了Service来解决这一问题,即在Pod前面使用Servi

B+树的定义以及查找

1.B+树的定义一棵m阶的B+树需满足下列条件:每个分支结点最多有m棵子树(孩子结点)。非叶根结点至少有两棵子树,其他每个分支结点至少有「m/2]棵子树。结点的子树个数与关键字个数相等。所有叶结点包含全部关键字及指向相应记录的指针,叶结点中将关键字按大小顺序排列,并且相邻叶结点按大小顺序相互链接起来(支持顺序查找)。所

【Linux成长史】Linux基本指令大全

🎬博客主页:博主链接🎥本文由Mmalloc原创,首发于CSDN🙉🎄学习专栏推荐:LeetCode刷题集数据库专栏初阶数据结构🏅欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📆未来很长,值得我们全力奔赴更美好的生活✨文章目录😇本章详情😇Linux指令⏳more指令⏳less指令(重要)⏳head指令⏳时间相

NumPy数值计算

1、Numpy概念1.1Numpy是什么?Numpy是(NumericalPython的缩写):一个开源的Python科学计算库使用NumPy可以方便的使数组、矩阵进行计算包含线性代数、傅里叶变换、随机数生成等大量函数1.2为什么使用Numpy对于同样的数值计算任务,使用NumPy比直接编写Python代码实现,优点:

热文推荐