深入理解计算机系统===》hello.c程序的运行

  • 编译器和IDE提供的默认配置,编译和链接参数对于大部分应用程序开发而言已经足够使用了。但是很多基于底层的系统软件的运行机制被掩盖,其程序的莫名其妙的错误使得我们陷入瓶颈束手无策。所以进行深层次的了解软件背后,程序背后执行的机理有利于我们更加深入理解计算机以及解决相关问题。
  • 执行过程:以hello.c为例

  • 整体流程:《预编译--编译--汇编--链接》

 预编译阶段 :

在C/C++中 他的源代码文件的扩展名是.cpp/.c,所包含的头文件扩展名是.h

而进行预编译后的文件的扩展名为.i

  • 在Linux系统新建c_program文件夹,
  • 之后vim生成新的文件且编写hello.c,
  • ls命令查看存在hello.c,cat -n hello.c查看具体代码
  • 通过命令:gcc  -E  hello.c  -o  hello.i 将源代码hello.c进行预编译处理。
  • 查看预编译后的hello.i里面的内容:cat -n hello.i

预编译后的 `hello.i` 文件包含了原始C源代码经过预处理器(preprocessor)处理过的内容。预处理器主要执行以下操作:

1. 宏替换:所有的宏定义(`#define`)都被展开,也就是说,任何使用了已定义宏的地方都将被替换成对应的宏值。

2. 包含文件:`#include` 指令被处理,指定的头文件内容被插入到源代码对应的位置。例如,如果源代码中有 `#include <stdio.h>`,那么 `stdio.h` 文件的所有内容会被复制并添加到 `hello.i` 文件内。

3. 条件编译指令:`#ifdef`、`#ifndef`、`#else` 和 `#endif` 等条件编译指令及其控制的代码块根据宏定义的存在与否被相应地保留或剔除。

4. 注释移除:预编译器会移除所有的 `/* */` 格式的注释,但保留 `//` 类型的注释(C++中),因为C语言的标准预处理器并不处理这种注释。

因此,当你打开一个预编译后的 `hello.i` 文件时,你会看到的是一个没有未展开宏、已经包含了所需头文件内容的纯C源代码文件。对于简单的`Hello World`程序,你可能会看到标准输入输出库(如stdio.h)的相关声明、宏定义的展开以及你的主函数(main)的代码,以及其他任何在源代码中通过预处理器指令引入的内容。由于头文件的展开,这个文件通常比原始的`.c`源文件要长很多行。

  • 预编译的过程就是去处理那些源代码中以“#”开头的预编译指令,比如在hello.i中程序hello.c运行所需要输出的函数printf(,就源自于头文件#include <stdio.h>
  • 主要处理规则如下:
  1. 将所有的#define删除,并且展开所有的宏定义
  2. 处理所有条件编译指令
  3. 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置,注意这个过程是递归进行的,也就是被包含的文件可能包含其他的文件
  4. 删除所有的注释:“//”,“/**/”
  5. 添加行号和文件名,便于编译器产生调试用的行号信息
  6. 保留所有的#pragma编译器指令,因为要使用,
  7. 经过预编译后的.i文件不包含任何宏定义,所有的宏已经被展开,并且包含的文件也被插入到.i中

编译阶段:

  • 就是将预处理完后的文件进行一系列的词法分析,语法分析,语义分析以及优化,之后产生相应的汇编代码,此过程是核心也是较为难以理解需要深入的复杂部分。
  • 使用命令:gcc -S hello.c -o hello.s

汇编阶段:

  • 汇编器将汇编代码转变为机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令,进而汇编阶段对于汇编器来讲是简单的没有发杂语法,只需要转化翻译就行。
  • 通过命令:gcc -c hello.s -o hello.o
  • 当然已经被翻译成机器指令不能被查看:出现乱码

链接阶段:

  • 链接
  • 链接通常是令人费解的问题:
     
    gcc -o hello hello.o

    这条命令会链接 hello.o 目标文件,生成名为 hello 的可执行文件。如果您在项目中有其他的依赖对象文件或需要链接库文件,可以像之前解释的一样,在命令行中加入它们。一旦完成链接,就可以通过 ./hello 命令在终端运行生成的可执行文件

  • 在现代软件开发过程中,软件的规模往往是相当大的,动辄几百万行代码,进而将其模块化,各个模块之间相互依赖又彼此独立,按照层次化的模块存储和组织源代码增强了可读性,可操作性,简单来说:链接 就是将所需要的各个模块根据某种特定的规则进行拼接形成可执行目标文件,用户才能./hello 执行。
  • 专业来说:链接就是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载到内存并执行。

操作系统内存布局:

再回头理解visual studio 2022下的程序的执行:

链接过程较为复杂:所包含的地址和空间分配,符号决议,重定位等问题有待深入~~~

参阅教材:《深入理解计算机系统》  《程序员的 自我修养》

  • 37
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值