深入理解计算机系统大作业

摘要

本论文从一个程序文件hello.c出发,通过讲述该文件实现P2P,O2O的过程,简单地展现了计算机系统的工作原理,并且回顾了许多实用的工具。
关键词:P2P,O2O,计算机系统,程序;

第1章 概述

1.1 Hello简介

P2P

1.编译过程
图1-1 编译过程
2. 创建并运行进程 通过给予上下文形成进程,并放在系统中运行 。

O2O

shell执行hello进程,为其映射出虚拟内存,然后在开始运行进程的时候分配并载入物理内存,开始执行hello的程序,将其output的东西显示到屏幕,然后hello进程结束,shell回收内存空间。

1.2 环境与工具

硬件环境: X64CPU; 8GHz; 8GRAM; 1TB HD;
软件环境: Windows10 64位;VMware14.12; Ubuntu 16.04 LTS 64位;
工具:gcc,gdb,cpp,ccl,as,ld,readelf等。

1.3 中间结果

hello.i
hello.c文件通过预处理后得到的新的程序文本文件,对于包含文件,宏定义以及条件编译进行了处理;
hello.s
hello.i文件通过编译后得到的由汇编语言编写的文本文件,将高级语言转换成了对应的汇编语言;
hello.o
hello.s文佳汇编后得到的二进制文件,可用于与其他可重定位目标文件链接形成可执行文件;
hello
可执行目标文件,在主机端输入./hello后可执行程序,完成程序的预期任务。

1.4 本章小结

关于hello.c P2P,O2O的粗略介绍。

第2章 预处理

2.1 预处理的概念与作用

预处理器(cpp)根据义字符#开头的命令,修改开始的c程序。比如hello.c中第一行的#include<stdio.h>命令告诉预处理器读取系统头文件stdio.h的内容,并插入到程序文本中;又比如,用define设置了一个宏,预处理器会将程序中所有的该宏替换掉(除此之外,当然还有条件编译)。结果得到另一个程序,hello.i。

2.2在Ubuntu下预处理的命令

cpp hello.c > hello.i
图2-1输入命令前,一个.c文件

图2-2输入命令
图2-3输入命令后,多了一个hello.i的程序文件

2.3 Hello的预处理结果解析

hello.i可作为文本文件打开,该文本的最后末端的内容即是hello.c的主体内容,而hello.i前面还有大量的文本,包括各种各样的定义,系统内的文件引用,可见是将hello.c内预处理部分(主要是三个头文件)经过了预处理,将内容插入到了程序中,成为了一个新的程序。

2.4 本章小结

预处理的主要三个功能就是处理宏定义,插入包含文件的内容,以及依据条件编译。

扫描二维码关注公众号,回复: 4735268 查看本文章

第3章 编译

3.1 编译的概念与作用

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

3.2 在Ubuntu下编译的命令

gcc -S hello.c -o hello.s

图3-1输入命令
图3-2生成一个新的文本文件hello.s

3.3 Hello的编译结果解析

hello编译结果
3.3.1数据传送指令mov、movw,movsbw
一般用于赋初值,数据更换寄存器(具体目的包括输入、输出等)等
赋初值
赋初值,利用了栈空间,l(movl)表示按4字节传送

3.3.2压入和弹出栈数据push、pop
压入栈
利用栈空间 将寄存器%rbp中的数据压入栈中(一般是(%rsp-8)所示内存地址)

3.3.3算数和逻辑运算leaq、add、not、and、sal、shr等
包括加载有效地址、加减乘除运算、逻辑运算、移位运算

leaq
leaq加载有效地址,类似于mov指令

减法
sub减法

加法
add加法

此外还有mul,imul乘法操作;div,idiv除法操作;and,or,xor,not逻辑运算;sal,shl,sar,shr移位运算 。

3.3.4控制操作cmp、test、set、jmp
比较(设置条件码)、跳转、由此可做到条件语句、循环语句
循环
判断栈中数据与9的大小,决定是否跳转其中.L3 .L4(按顺序,L4在L3前)形成了循环语句,对应于hello.c中的for语句;
if
这是一个条件跳转语句,对应于hello.c中的if语句

3.3.5函数调用call、ret
也可由此实现递归

call
调用函数,屏幕显示

ret
ret函数返回,类似于return 0;

3.3.6全局变量
常量
对应于hello.c中的int sleepsecs =2.5,由于int定义为整形数,所以此处给的空间为4个字节

3.4 本章小结

汇编语言相较于一般的高级语言,更加展现了机器实现操作的步骤和思路,也给出了许多高级语言无法给出的信息(寄存器中的数据,栈的空间使用情况),而且可读性很高。

第4章 汇编

4.1 汇编的概念与作用

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

4.2 在Ubuntu下汇编的命令

as hello.s -o hello.o
图4-1 输入命令
图4-2 出现了一个新的二进制文件hello.o

4.3 可重定位目标elf格式

4-2-1
4-2-2
可见其包含elf头表,节头表,重定位节和一个符号表重定位项目中给出了偏移量、信息、类型、符号值、符号名称等基本信息,如.rela.text中:

  1. 偏移量表示他目前的相对地址(未链接前)
  2. 信息表示他的值
  3. 类型比如R_X86_64_PC32表示重定位一个使用32位PC相对地址的引用
  4. 符号值和符号名称表示引用的符号。 分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。

4.4 Hello.o的结果解析

4-4
机器语言的一条指令一般是由若干个字节组成,包括指令、常数。
如b8 00 00 00 00前一个b8表示mov到%eax的指令,后面的八个零表示常数0x0(4字节,小端表示)
b8 00 00 00 00 mov 0x0 , %eax

在跳转时,反汇编文件跳转命令后直接接表示偏移量的数字
如:jmp 6fje 2bcallq 21<main+0x21>
而机器语句中则是依据当前语句与要跳转到的语句偏移量的差,
如:26:e8 00 00 00 00 call 2b
由于0x26(当前PC相对偏移量)+0x5(5个字节) = 0x2b,所以按顺序结构中间相差0个字节,即00 00 00 00

4.5 本章小结

汇编主要表现了机器语句的构造(章4 Y86-64),通过汇编,得到.o文件(二进制),机器才可以处理该文件。通过反汇编与.s文件的比较可以发现真正的机器指令思路上大体与汇编相同,但数的处理上会稍有不同。

第5章 链接

5.1 链接的概念与作用

hello程序调用了printf函数,printf函数存在于一个名为printf.o的单独地预编译好了的目标文件中,链接器(ld)就负责处理这种合并,结果就得到hello文件,一个可执行目标文件。

5.2 在Ubuntu下链接的命令

ld hello.o -lc -o hello.out 或gcc hello.o -o hello.out
最简单的生成可执行文件的方法: gcc -o hello hello.c
图-5-1
简单运行hello
hello

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

1
23456可见包含一个elf头表,29个节头,1个程序头,2个重定位节,2个符号表等,相比之前多了很多内容。图中含有地址,大小等信息

5.4 hello的虚拟地址空间

5-4
虚拟地址从0x00400000开始,到0x004001000
与5.3对照
程序头
可见若干程序头,包括:PHDR INTER PLOAD NOTEGNU_EH_FRAME GNU_STACK GNU_RELRO

5.5 链接的重定位过程分析

1.hello的内容较多,多出来很多函数puts,printf,sleep等,还有节.init .plt等
2.对函数引用的差别比较明显

hello
hello

hello.o
hello.o
可见hello主要是跳转向<mian+偏移量>,而hello则是直接跳向内存地址<函数名>,说明在连接的过程中,重定位已经完成,虚拟地址空间分配。
3. 从节头数量看,hello也会比较多 hello.o的节头有13个,和hello的节头有29个
hello.o
hello.o

hello
hello

5.6 hello的执行流程

载入:_dl_start _dl_init
开始执行:_start _libc_start_main _init
执行main:_main _printf _exit _sleep _getchar _dl_runtime_resolve_xsave _dl_fixup _dl_lookup_symbol_x
退出:exit

5.7 Hello的动态链接分析

在edb调试之后,原先0x00600a10开始的global_offset表全部成0,在执行_dl_init之后被赋上了相应的偏移量。说明_dl_init操作是给程序赋上当前执行的内存地址偏移量。

5.8 本章小结

通过与外部函数的链接,形成一个可以在机器上执行的文件,在链接的过程中,主要处理了符号解析和重定位的问题,最终使得我们编写成的简单的程序文件成为一个可以在机器环境中调用空间资源并处理问题的有效代码。

第6章 hello进程管理

6.1 进程的概念与作用

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

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

shell是一个应用程序,操作系统中提供了一个用户与系统内核进行交互的界面。
处理流程:1.读取用户的输入 ;2.分析输入内容,获得输入参数; 3.如果是内核命令则直接执行,否则调用相应的程序执行命令; 4.在程序运行期间,shell需要监视键盘的输入内容,并且做出相应的反应.

6.3 Hello的fork进程创建过程

fork
fork

6.4 Hello的execve过程

execve运行时,先是从可执行文件中加载的内容,然后是运行时的堆栈和共享库的存储器映射区域。
新的程序典型的栈帧:
execve

6.5 Hello的进程执行

上下文切换

6.6 hello的异常与信号处理

C
输入Ctrl+C,进程直接结束,该操作是向进程传输sigint信号,终止前台作业
Z
输入Ctrl+Z, 进程停止 ,该操作是传输sigtstp信号,停止前台作业,不结束进程,输入ps后可见hello仍在。
E
乱按回车,除了换行,不受影响

fg
Ctrl-z后可以运行fg命令,停止的进程继续运行完成

jobs
Ctrl-z后可以运行jobs命令,可返回上一条指令结果的内容

pstree
Ctrl-z后可以运行pstree命令,可显示进程树
killkill命令可想制定进程传送制定信号,向PID为2789的进程hello传送序号为2的信号(sigint,等同于Ctrl+C),发现进程终止。

6.7本章小结

进程在shell的环境下用fork,wait创建并回收子程序,用execve加载新的程序,用键盘、函数反复地发送、捕获、接收、处理/放弃信号,一会运行程序一会处理信号。

第7章 hello的存储管理

7.1 hello的存储器地址空间

逻辑地址:其实指的是偏移量,如21<main+0x21>
线性地址(虚拟地址):虚拟地址空间中的地址,可以保证每个进程拥有相同的地址空间,而且简化了内存管理。0x00400000,几乎所有的进程的用户空间都由此开始。
物理地址:内存地址,是真实且与内存空间一一对应的地址

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

先将逻辑地址分成段选择符+段描述符的判别符(TI)+地址偏移量的形式,然后先判断TI字段,看看这个段描述符究竟是局部段描述符(ldt)还是全局段描述符(gdt),然后再将其组合成段描述符+地址偏移量的形式,这样就转换成线性地址了

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

先将虚拟地址分为虚拟页号(VPN),虚拟页偏移量(VPO),依据VPN(TLBT+TLBI)先在TLB中寻找,若找不到,则在高速缓存/内存中寻找,若找到对应的物理页号(PPN),再将PPN与VPO组合成物理地址,若还是查找不到,则需要缺页处理,在磁盘中查找,并将新的页更新入内存中。

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

36位的VPN被分成4个9位的片,每个片被用做到一个页表的偏移量。CR3寄存器包含L1页表的物理地址。VPN1提供一个L1 PET的偏移量,这个PTE包含L2页表的基地址,VPN2再提供一个偏移量,以此类推。
多级页表 多级页表的地址翻译(这里借用一下老师的图)

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

物理地址拆分为CT(标记),CI(组索引),CO(块偏移),依据组索引,找到对应的组,在依据标记查找是否存在且是否可访问,最后根据块偏移找到块,若没有找到则向下一级高速缓存中查找

7.6 hello进程fork时的内存映射

创建当前进程的mm_struct,vm_area_struct和页表的原样副本
两个进程的每个页面都标记为只读页面
两个进程的每个vm_area_struct都标记为私有,这样就只能在写入时复制

7.7 hello进程execve时的内存映射

删除已存在的用户区域
创建新的私有区域(.malloc,.data,.bss,.text)
创建新的共享区域(libc.so.data,libc.so.text)
设置PC,指向代码的入口点

7.8 缺页故障与缺页中断处理

1.第一种情况:缺失发生时,相关的页已经被加载进内存,但是没有向MMU注册的情况。操作系统只需要在MMU中注册相关页对应的物理地址即可。
2.第二种情况:指相关的页在页缺失发生时未被加载进内存的情况。这时操作系统需要:寻找到一个空闲的页。或者把另外一个使用中的页写到磁盘上(如果其在最后一次写入后发生了变化的话),并注销在MMU内的记录;将数据读入被选定的页;向MMU注册该页。

7.9动态存储分配管理

动态内存分配器维护这一个进程虚拟内存区域,称为堆
堆
(感谢老师)
显示分配器主要方法有隐式空闲链表,显示空闲链表
链表
(再次感谢老师)
由于显示空闲链表可利用空闲块记录数据结构,所以更加通用

7.10本章小结

主要表述了一个地址的产生,经过各种翻译,最后返回需要的数据,包括从虚拟地址到物理地址,再从物理地址找到数据,以及翻译查找过程出现缺页的处理办法,和维护进程虚拟空间的办法

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:文件
文件的类型:
普通文件(regular file):包含任意数据的文件。
目录(directory):包含一组链接的文件,每个链接都将一个文件名映射到一个文件(他还有另一个名字叫做“文件夹”)。
套接字(socket):用来与另一个进程进行跨网络通信的文件
命名通道
符号链接
字符和块设备

设备管理:unix io接口

打开和关闭文件
读取和写入文件
改变当前文件的位置

8.2 简述Unix IO接口及其函数

打开文件:open函数,打开一个已存在的文件或者创建一个新文件
int open(char *filename,int flags,mode_t mode);
关闭文件:close函数,关闭一个已打开的文件
int close(int fd);
读:read函数,执行输入
写:write函数,执行输出
ssize_t read(inf fd,void *buf,size_t n );
ssize_t write(inf fd,const void *buf,size_t n );

8.3 printf的实现分析

printf
其中调用的vsprintf函数的作用是格式化。它接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化,产生格式化输出。Write则将vsprintf的输出逐个的写到终端。
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall。
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析

getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdin流中每次读入一个字符.getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键。
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。

8.5 本章小结

表述了Unix IO接口及其4个函数,简单了解了一下printf,getchar的实现

结论

hello.c一开始说白了就是一堆文本文字,直至经过了预处理、编译、汇编、与若干其他文件的链接后终于成为了一个可执行目标文件hello,此时他已经可以走向linux,在系统中正式开始自己的程序生涯,他被给予上下文成为了进程,在系统中运行并处理信号,一些有它产生或者他需要的信息、空间则通过与存储结构合作,调用空间,存储信息。而且还会通过I/O设备与其他程序在进行交互与通信。
在完成大作业的过程中,回顾了这一学期以来csapp课程许多重要的概念、理解和操作,发现相比于半年前刚刚接触到深入C程序时对于C有了很多理解,一边是敬佩和感叹前人对于计算机系统设计的精妙与复杂,一遍又深觉自己的不足,虽然所谓的深入理解依旧是比较浅的,但是对于编写程序而言,提供的帮助是显而易见的。

附件

hello.i hello.c文件通过预处理后得到的新的程序文本文件,对于包含文件,宏定义以及条件编译进行了处理;
hello.s hello.i文件通过编译后得到的由汇编语言编写的文本文件,将高级语言转换成了对应的汇编语言;
hello.o hello.s文佳汇编后得到的二进制文件,可用于与其他可重定位目标文件链接形成可执行文件;
hello 可执行目标文件,在主机端输入./hello后可执行程序,完成程序的预期任务;

参考文献

[1] 林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.
[2] 辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.
[3] 赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
[4] 谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.
[5] KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.
[6] CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.
[7] https://blog.csdn.net/dxyinme/article/details/85322271
[8]https://www.cnblogs.com/pianist/p/3315801.html
[9]深入理解计算机系统原书第三版. 机械工业出版社

猜你喜欢

转载自blog.csdn.net/weixin_43660028/article/details/85506433
今日推荐