你好,我是大白。前两篇文章讲解了[计算机是怎样工作的] 以及[操作系统具体做了什么] 。接下来的文章就要开始详细讲操作系统了。接下来会有多篇文章详细讲进程,进程是操作系统中十分重要的一个虚拟化产物,我们一起来详细学习下吧!之前从[系统调用的角度讲过怎样创建进程] ,今天我们来看看怎样把源代码转化成一个进程!
一个阳光明媚的中午,大白在领导办公室
大白:领导我......
领导:行行行,你哪疼快去看哪吧!
--------------------当日下午,腾讯大楼,面试开始--------------------
面试官:这是第三轮面试了,前几轮问的差不多了,今天我想考查下你的基本功,我就想咱们详细的分析下从代码到进程要经过哪些步骤!你能先讲下我们为什么需要进程这个东西吗?
大白:好的,我在我上一篇写的系列文章中也提到过,大家都希望能同时在电脑上运行多个程序。比如看直播的同时也能开着微信聊天,还能同时看看邮件等等。但是我们知道,一个 CPU 在一瞬间只能同时处理一个运行着的程序,所以我们就需要通过虚拟化的技术来让操作系统用一个 CPU 营造出无数个 CPU 可用的假象。为了达到这个目的,我们首先要把运行着的程序进行抽象,把正在运行的程序抽象成所谓的进程。有利于后面的一系列操作。
面试官:不错,那你再讲下把源代码转化成一个进程一共需要哪几步吧?
大白:好的,程序转换为进程需要五个阶段,分别是预处理、编译、汇编、链接、装载。我下面画个图,看的更直观一些。这个流程都是以 Linux 系统和 C 语言为例的。
面试官:不错不错,那再讲下每个阶段分别再做什么吧!
大白:没问题,咱们一个个的看。
#include
、#define
等,再具体一点就比如说将头文件嵌入正文中,将定义的宏展开、把注释删去等。C 语言文件经过这一步生成 .i
文件,C++ 经过这一步生成 .ii
文件。 面试官:打断一下,预处理和编译处理后的结果大家应该比较容易理解。第一步是一些代码的预处理,编译就是把 C 转化为汇编的代码。但是经过第三步处理后生成的 .o
目标文件是什么样我就不太清楚了。这里详细讲一下吧!
大白:好的!其实目标文件在不同的平台上是不一样的,比如在 Windows 上的目标文件为 .obj
文件,而在 Linux 上目标文件为 .o
文件,格式被称为 ELF(Executable and Linkable Format, 可执行与可链接格式)。
大家有兴趣可以按照我下面给出的命令看下。首先写一段 C 语言代码,可以命名成 dabai.c
。然后用 “gcc -c dabai.c
” 编译下文件会生成一个同名的 .o
文件,然后用命令 “readelf -a dabai.o
” 输出就可以看啦。
我把重要的部分在下面单拿出来讲下,.o
文件的结构长下面这样。
图仿极客时间《趣谈 Linux 操作系统》 https://time.geekbang.org/column/article/90855
具体各部分的表示为
.text:放编译好的二进制可执行文件
.data:已经初始化好的全局变量
.rodata:只读数据,例如字符串常量、const 的变量
.bass:未初始化全局变量,运行时会置为0
.symtab:符号表,记录的则是函数和变量
.strtab:字符串表、字符串常量和变量名
.rel.text:代码段重定位表,描述代码段中出现的函数、变量的引用地址信息等
.rel.data:数据段重定位表
面试官:好的,你接着说下链接是做什么的!
大白:好的,链接 需要把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确衔接。比如代码文件 A.c
引用了代码文件 B.c
中的函数,在编译时对应生成的是 A.o
和 B.o
。那么 A.o
中的 .rel.text
和 rel.data
就应该记录了引用信息。通过链接把多个人 .o
文件就合并成了.out 文件。这个 .out
文件和 .o
文件相似,也是采用 ELF 格式的,只不过是 ELF 文件的另一种格式。具体长下面这样。转化成下面这样后就可以往内存中加载了。
此图仿极客时间《趣谈 Linux 操作系统》 https://time.geekbang.org/column/article/90855
面试官:你刚才说的是静态链接的方法吧?他有什么优缺点呢?
大白:是的,上面采用的是静态链接的方法,静态链接库一旦链接进去就合并了,以后程序运行就不会依赖链接库了。但这样的缺点就是一段代码如果被多个程序使用,那么内存里面就会存在多份。所以就又出现了一种动态链接,具体做法是将一个动态链接库链接到一个程序文件中时,最后的程序文件并不包括动态链接库中代码,而仅仅包括对动态链接库的引用。动态链接我就不特别详细的展开讲了,细节有点不太熟。
面试官:好的,那你说下装载是在做什么吧!
大白:经过上面的一系列操作已经把代码转化为可执行文件了,把可执行文件 装载 到内存中就可以执行了。装载可执行文件并且执行需要做以下三件事:
面试官:我是第一次遇见有人想主动加面的!
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8