2025-07-12
【0】开发者笔记
00
请注意,本文编写于 83 天前,最后修改于 69 天前,其中某些信息可能已经过时。

目录

一.编译链接的过程
A:编译(源文件——>目标文件)
目标文件
B:链接(目标文件——>可执行文件)
二.程序内存布局与虚拟内存
虚拟内存技术
程序,进程,线程

经过了很长时间的学习,我们对计算机的各个模块都有了响应的了解,但是分散的知识是很难发挥作用的,需要一些东西它们串联起来。

今天,我们通过一个简单的问题,将之前接触到的部分知识点整合起来。

问题

程序/代码是如何运行起来的?

对我们程序员来说,需要写一些源代码,以CPP为例,会生成一些.cpp或.c后缀的源文件,例如以下这个文件:

C
main.c #include <stdio.h> int main() { printf("Hello,World\n"); return 0; }

在写完代码后需要进行编译链接,然后在命令行下执行

bash
# gcc main.c -o hello # ./hello Hello,World

一.编译链接的过程

A:编译(源文件——>目标文件)

编译器从宏观来说就是一个强大的“文本处理程序”,其就是将“CPP文件”处理为“目标文件”。而处理的过程分为多个步骤

  1. 词法分析。编译器会将文件中的内容分割为一个一个的类似于“class”的符号,这一步称为提取符号,词法分析。

    //

  2. 语法分析。在词法分析的基础上,编译器会对每个符号进行解析,例如:当编译器遇到了while,此时就会有( 接下来就会是一个布尔表达式,之后是 ),然后会是 { ,循环体,} 之后就结束。此时就形成了一个具有语法意义的语法树语法树

  3. 语义分析。已经生成了语法树,但不确定是否正确,因此需要进行检查。

  4. 生成汇编。根据语法树进行转换,生成汇编指令。

  5. 生成机器指令。

此时,生成的机器指令存于目标文件。

目标文件

对于目标文件,其内容以段的形式存储信息。目标文件

目标文件将所有使用的符号存于符号表,**整个符号表就做两件事:定义了那些符号;用了哪些外部符号。**同时对于不能确定的变量,单独分离出来,为将来链接器的决议指明。

B:链接(目标文件——>可执行文件)

链接器从宏观上来看也相当于一个强大的“文本处理程序”。其对目标文件以及库文件进行链接时,也分为多个步骤。

  1. 符号决议。符号就是变量,符号决议就是为所有外部的符号找到其所对应的定义。

  2. 生成可执行文件。当所有符号都有定义后,链接器会将所有代码区与数据区整合起来。//生成可执行文件

  3. 重定位。生成基本的可执行文件后,需要对之前.relo.text以及.relo.data中的地址进行重新定位,因为在编译时,无法确定的地址会赋予0,因此在整合之后需要将其改为正确的地址。

二.程序内存布局与虚拟内存

是否经常看到这样的分区:内存分区

此时有一个疑问,此分区的起始地址是0x400000,如果我们有两个程序AB,CPU在执行程序时,取0x400000时,取的是A的起始,还是B的起始?

答案是,CPU执行程序A时,取的是A的代码区,CPU执行程序B时,取的是B的代码区。原因是虚拟内存

虚拟内存技术

我们所看到的结构都是虚拟内存,其为虚拟的,抽象出来的结构。而物理内存就是一块空间,没有分区,没有种类。而它们之间的映射关系 依靠于页表

通过页表,不同进程在同一虚拟地址上所存的信息分布在不同的物理内存上。如图所示:虚拟内存

此时我们看到:

  1. 每个进程都有标准的虚拟内存,大小一样,排列顺序一致。
  2. 物理内存的大小与虚拟内存大小无关。
  3. 每个进程有独立页表。

虚拟内存技术,使得所有程序有了统一的格式成为可能。

程序,进程,线程

程序:运行于某种目标计算机体系结构上,用某种程序设计语言编写,具有信息处理能力或判断的指令的集合。

进程:进程是具有一定功能的程序动态执行的过程, 是操作系统进行资源分配和调度的一个独立单位。进程是抽象出来的。 进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。

线程: 线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。 一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。

1717647786553

本文作者:流浪的将军

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!