CS:APP 计算机系统 课程大作业

学号:120L022004

目  录

第1章 概述... - 4 -

1.1 Hello简介... - 4 -

1.2 环境与工具... - 4 -

1.3 中间结果... - 5 -

1.4 本章小结... - 5 -

第2章 预处理... - 6 -

2.1 预处理的概念与作用... - 6 -

2.2在Ubuntu下预处理的命令... - 6 -

2.3 Hello的预处理结果解析... - 6 -

2.4 本章小结... - 7 -

第3章 编译... - 8 -

3.1 编译的概念与作用... - 8 -

3.2 在Ubuntu下编译的命令... - 8 -

3.3       Hello的编译结果解析... - 8 -

3.4 本章小结... - 13 -

第4章 汇编... - 14 -

4.1 汇编的概念与作用... - 14 -

4.2 在Ubuntu下汇编的命令... - 14 -

4.3 可重定位目标elf格式... - 14 -

4.4 Hello.o的结果解析... - 16 -

4.5 本章小结... - 18 -

第5章 链接... - 19 -

5.1 链接的概念与作用... - 19 -

5.2 在Ubuntu下链接的命令... - 19 -

5.3 可执行目标文件hello的格式... - 19 -

5.4 hello的虚拟地址空间... - 22 -

5.5 链接的重定位过程分析... - 24 -

5.6 hello的执行流程... - 26 -

5.7 Hello的动态链接分析... - 26 -

5.8 本章小结... - 27 -

第6章 hello进程管理... - 28 -

6.1 进程的概念与作用... - 28 -

6.2 简述壳Shell-bash的作用与处理流程... - 28 -

6.3 Hello的fork进程创建过程... - 29 -

6.4 Hello的execve过程... - 29 -

6.5 Hello的进程执行... - 29 -

6.6 hello的异常与信号处理... - 30 -

6.7本章小结... - 32 -

第7章 hello的存储管理... - 33 -

7.1 hello的存储器地址空间... - 33 -

7.2 Intel逻辑地址到线性地址的变换-段式管理... - 33 -

7.3 Hello的线性地址到物理地址的变换-页式管理... - 34 -

7.4 TLB与四级页表支持下的VA到PA的变换... - 35 -

7.5 三级Cache支持下的物理内存访问... - 36 -

7.6 hello进程fork时的内存映射... - 37 -

7.7 hello进程execve时的内存映射... - 37 -

7.8 缺页故障与缺页中断处理... - 38 -

7.9动态存储分配管理... - 39 -

7.10本章小结... - 41 -

第8章 hello的IO管理... - 42 -

8.1 Linux的IO设备管理方法... - 42 -

8.2 简述Unix IO接口及其函数... - 42 -

8.3 printf的实现分析... - 43 -

8.4 getchar的实现分析... - 46 -

8.5本章小结... - 46 -

结论... - 47 -

附件... - 48 -

参考文献... - 49 -

第1章 概述

1.1 Hello简介

P2P(From Program to Process):GCC编译器驱动程序读取源代码文件hello.c,并且把它翻译成一个可执行文件hello。这个翻译过程可以划分为四个阶段:

预处理阶段:预处理器(cpp)根据以字符 # 开头的命令,修改原始的C程序,将 #include命令包含的头文件/源代码读取并把它直接插入程序文本中。结果就得到了另一个C程序hello.i;

编译阶段:编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序;

汇编阶段:接下来,汇编器(as)将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件hello.o中。它是一个二进制文件;

链接阶段:最后,链接器(ld)将程序与函数库中需要使用的二进制文件进行链接,形成可执行目标程序二进制文件。

之后执行该文件会将该文件加载在内存中,由系统执行。操作系统会使用fork函数形成一个子进程,分配相应的内存资源,使用execve函数加载进程(Process),完成P2P(From Program to Process)过程。

020:hello运行时系统会为其分配对应的虚拟内存空间。Hello读取数据时通过层层存储结构,下一级作为上一级的缓存,使数据可以到达CPU进行处理。系统会删除当前虚拟地址的用户部分已存在的数据结构,为hello创建新的区域结构。程序运行完成后系统会回收hello进程并且删除内存中对应的数据,完成020(From Zero-0 to Zero-0)过程。

1.2 环境与工具

1.2.1 硬件环境

CPU: AMD Ryzen7 4800H AMD64 Architecture @2.90GHz

MEM: 16.0GB DDR4 3200MHz (SODIMM)

Disk: Adata IM2P33F8-512GD 512GiB SSD & Samsung SSD 980 1TiB SSD

1.2.2 软件环境

Microsoft Windows 10 64位

Ubuntu 20.04 LTS 64位

Oracle VM VirtualBox 6.0.12

1.2.3 开发工具

GNU GCC 9.2.0

GNU Make 4.2.1

Visual Studio Code x64

EDB Debugger

GNU GDB

1.3 中间结果

文件名

作用

hello.c

源代码

hello.i

hello.c预处理生成的文本文件

hello.s

hello.i编译后得到的汇编语言文本文件

hello.o

hello.s汇编后得到的可重定位目标文件

hello

hello.o链接后得到的汇编语言文本文件

hello.elfinfo

hello的readelf解析输出

hello.asm

hello的objdump反汇编输出

hello.o.asm

hello.o的objdump反汇编输出

hello.o.elfinfo

hello.o的readelf解析输出

1.4 本章小结

本章简述了hello的P2P,O2O过程,介绍了编写本文时的工作环境。

第2章 预处理

2.1 预处理的概念与作用

概念:预处理阶段,预处理器(cpp, C Pre-Processer)根据以 # 字符开头的命令,修改原始的C程序。以hello.c为例,第6-8行的 #include类命令告诉cpp预处理器读取系统头文件stdio.h, unistd.h, stdlib.h并把它直接插入到程序文本中。对所有 # 开头的命令处理之后,就得到了另一个C程序,以 .i作为扩展名。

作用:在C语言编译到汇编的阶段之前,预扫描源代码,完成头文件的包含、宏的扩展、条件编译、行控制等对代码结构进行的操作,确定要进行编译的全部代码,丢弃不需编译的代码、注释等,便于编译器后续的编译。

2.2在Ubuntu下预处理的命令

Ubuntu下可以使用gcc并附加参数 -E进行预处理,也可以直接调用cpp预处理器程序进行预处理。如下图:

 

图 2.1 预处理指令

2.3 Hello的预处理结果解析

图2.2 hello.c(源代码)

图2.3 hello.i(预处理输出)

观察对比源代码与预处理后的代码,我们可以得到以下结果:

  1. 代码行数增加,由23行增加到3060行,这是由于 #include 指令被递归地替换成了相应头文件内的代码。
  2. 插入了对应的stdio.h, unistd.h, stdlib.h头文件代码,可以发现在默认
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值