IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 深扒源程序到执行程序的过程 -> 正文阅读

[系统运维]深扒源程序到执行程序的过程

写代码时,我们通常会创建一个.c的C语言文件,然后经过编译器编译后可以生成一个可执行程序。而创建的.c我们称为源文件,.exe就是一个可以运行的可执行文件。那么编译器究竟对源程序做了哪些 不可描... 可以描述的事情,才让源程序成长为一个可执行程序呢。究竟是人性的扭...,咳咳,又扯远了。

翻译环境和执行环境

首先要知道,任何生成的可执行程序都会经历两个环境,一个是翻译环境,另一个叫执行环境。

翻译环境是将代码转换成可以被计算机执行的机器指令。

执行环境则用于执行实际代码。

翻译环境

我们将翻译阶段分为两个部分:编译和链接。

当一个工程中有多个源文件时,每个源文件都会单独经过编译器处理形成一个 .obj 不同操作系统后缀可能不同,在Linux操作系统下后缀为.o)的文件。.obj 的文件就是目标文件。然后这些文件会经过连接器来生成一个可执行文件。从 .c 文件到 .obj 文件的过程叫做编译,而.obj需要去链接器去将这些文件链接起来,从而形成一个可执行文件,这个过程叫做链接。当然这也只是一个大致的流程。

大致流程:

编译做了什么

编译有三个步骤:预编译、编译、汇编。

Linux可以很好的演示程序编译的每一个步骤,但是我没有装Linux所以只能尽量按照Windows来描述了。

预编译(预处理)干什么

一、头文件预处理

你有没有想过为什么要引头文件?引头文件其实就是为了声明函数。当程序进行预编译阶段时,会先将头文件包含的所有函数声明全部导入文件。假设你只有10行程序,当你引了头文件后,你的代码在预编译可能会有几百行,真正有效的还是你那10行程序。其实上面的代码就都是头文件里的函数声明。

编译器想的是:我只负责帮你把声明全部导入到你的程序,至于这些声明的函数用到了几个,那我管不着

小提一嘴:当使用自己的头文件时都是用双引号,原因是双引号会先在该工程目录下去查找这个头文件,如果找不到,编译器就会去默认的头文件的文件夹(库函数的头文件文件夹)里去找这个头文件,如果还是没有就报错。所以用双引号去找库函数会找两次。

如果是使用尖括号来找头文件,编译器就会直接去到库函数的文件夹里找,而直接忽略工程文件。想用尖括号来找自己在工程创建的头文件的话……。点开链接查询解决方法

二、对define定义的宏和常量的替换

除了声明,预处理会将所有使用define定义的符号、宏的地方都替换成define定义的内容,然后把define那段删掉。

比如说:

//常量
#define A 100
//宏
#define MAX(x,y) (((x)>(y))? (x):(y))
int main()
{
	printf("%d\n", A);
	printf("max = %d\n", MAX(10, 20));

	return 0;
}

//替换后
//替换并删掉宏
int main()
{
	printf("%d\n", 100);
	printf("max = %d\n", ((10)>(20))?(10):(20));

	return 0;
}

因为宏是完全替换的,所以并没有开辟栈帧,对空间和时间的开销都比函数消耗较少。但是宏因为是完全替换的,所以宏不能递归,并且非常需要注意优先级。如我的代码里一样要给足够括号。所以宏适合定义一些比较短小简单的程序,适当的使用可以降低程序的开销。该用宏时不要客气,但是该使用函数还是要使用函数。

三、删注释

鲁迅曾说过:“我最讨厌的两件事,一个是别人不写注释,另一个是别人让我写注释”,都知道注释是一个非常重要的事情,没注释的代码那就是一座屎山,一个没有注释的代码程序真的可以逼疯一个程序员。因为注释始终是给人看的,而电脑就没必要去执行。编译器就在预处理阶段先将注释给删掉。

预编译总结:在预编译阶段,编译器在做的都是些文本操作,像符号的替换,头文件声明的拷贝,和删除宏和注释(在Linux下程序预编译后会生成一个.i为后缀的文件)

编译阶段

编译器在编译阶段都在干啥。在预处理时编译器已经把所有的文本操作给做完了,所以在之后的编译和汇编阶段,编译器只需要把剩下的有效的代码转换计算机可以识别的语言,但不是直接转换成机器语言,而是先把代码转换成汇编指令,也就是熟知的汇编语言。(Linux会生成.s为后缀的文件)

要将源文件的代码转换成汇编指令,编译器在编译阶段要进行一些特殊处理。如语法分析、词法分析、语义分析、符合汇总。这些都是编译原理的内容了。

编译阶段会把所有的语法符号全部记录下,比如一个类型、函数名,变量名,大小括号的左括号、右括号等等都会被记录下来。

汇编阶段

编译阶段处理完成后,紧接着就是汇编阶段,汇编阶段就是把编译阶段生成的汇编代码转换成机器语言。然后由编译器生成一个.obj的文件,这个文件里就都是些看不懂二进制文件了。

在汇编阶段还会进行一个操作叫形成符号表,这个操作就与编译阶段的符号汇总相呼应了,在链接阶段起到了至关重要的作用。

那么符号表在干什么?假设我一个工程创建了两个源文件,其中add.c里放了一个加法函数的实现,main.c里使用了extern声明了add函数。那么符号表就会先帮我把这个函数给记录下来,并给这个函数的地址分配一个临时的地址,然后还会给add.c的源文件的函数分配一个地址。(下面地址为假设),当然符号表链接的不只是函数,变量的地址也在符号表中。

?链接库链接

链接阶段,编译器会将工程所有编译过后生成的.obj(Linux为.o)文件链接起来生成可执行程序(Windows为.exe后缀?Linux为.elf后缀)。

一、合并段表

合并段表可简单理解为,可执行文件将工程里所有的.obj文件都给分为了几个段,每个段的功能是相同的都有自己相同的意义,然后可执行文件再将这些.obj文件的每个相同的段链接在一起,最后只生成了一个可执行文件。类似于下面这个样子(有点像缝裤子怎么回事)。

二、符号表的合并重定位

形成符号表之后,编译器就要将这些函数的地址给链接起来。编译器会通过符号表对照,将函数名相同的函数地址链接起来,将原先声明给的临时填充地址覆盖成函数地址,这个覆盖的过程就叫做重定位

在正常情况下,当函数即声明了函数又定义了函数,这个函数是没有任何问题的,因为都链接起来了。

如果只声明了函数,没有定义函数,那么add.c里就没有地址,main.c里分配的地址也只是一个无效的地址,即使在main.c里声明了这个函数,在连接时依然找不到这个函数的地址,链接之后通过这个无效地址是找不到这个函数,编译器会报错。

只定义未声明时,当函数在执行时,在main.obj里没有找到函数的声明,也就没有分配函数的临时地址,在链接的时候编译器发现使用了该函数,但是没有找到这个函数的地址,编译器会先报一个警告,然后在add的符号表里发现了这个函数,然后符号表将add的函数地址链接到合并到符号表里。

结尾

最近打算也写写其他的内容了。一篇草稿鸽了这么久,老是只写这些干货感觉自己也没啥动力,准备分享一些刷题的题解和思路。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:35:42  更:2022-03-21 21:38:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:32:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码