计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 英才学院
学 号 7203610606
班 级 2036014
学 生 xxx
指 导 教 师 刘宏伟
计算机科学与技术学院
2021年5月
通过对《深入了解计算机系统》这本书的学习,本文将从“hello”的一生入手,从预处理,编译,汇编,链接,运行,结束等过程,同时还包括了它的进程管理、存储管理、IO管理。进行课程知识的梳理与回顾,来加深对“计算机系统”课程的理解。
关键词:hello;计算机系统;程序的生命周期;I/O;C语言
目 录
第1章 概述
1.1 Hello简介
P2P:hello.c经过cpp预处理、ccl的编译、as的汇编、ld的链接最终成为可执行目标程序hello,在shell中键入启动命令后,shell为其fork产生一个子进程,然后hello便从程序变为了进程。
020:shell使用execve函数运行hello程序,映射虚拟内存,并从程序入口开始载入物理内存,再进入main函数执行目标代码,此时CPU为运行的hello分配时间片执行逻辑控制流,并通过流水线机制运行该程序,当程序运行结束后,shell父进程负责回收hello进程,内核删除相关数据结构。
1.2 环境与工具
硬件环境:X64 CPU;2GHz;2G RAM;256GHD
软件环境:Windows10 64位;VirtualBox 11;Ubuntu 20.04 LTS
开发工具:Visual Studio 2021 64位;CodeBlocks 64位
1.3 中间结果
hello.i 预处理得到的文本文件
hello.s 编译后得到的文本文件
hello.o 汇编得到的可重定位目标文件
1.4 本章小结
第2章 预处理
2.1 预处理的概念与作用
概念:在程序设计领域,预处理一般是指程序源代码被翻译为目标代码的过程中,生成二进制代码之前的过程。由预处理器对程序源代码文本进行处理,得到的结果再由编译器核心进一步编译。这个过程并不对程序的源代码进行解析,但它把源代码分割或处理为特定的单位。最常见的预处理是C语言和C++语言。ISO C和ISO C++都规定程序由源代码被翻译分为若干有序的阶段(phase),通常前几个阶段由预处理器实现。
作用:将源文件中以”include”格式包含的文件复制到编译的源文件中;用实际值代替用#define定义的字符串;条件编译,根据#if后面的条件决定要进行编译的代码。
2.2在Ubuntu下预处理的命令
命令:gcc -E hello.c -o hello.i
2.3 Hello的预处理结果解析
如图所示
可以看到,文本内容大量增加,预处理器将原c文件中的头文件直接插入预处理之后的文件中,将#define相应的宏定义进行了扩充,将原本的C语言编码放到了文件最后。
2.4 本章小结
通过本章了解了C语言编译之前的预处理过程,学会了gcc下的预处理指令,理解了其概念和作用,并对hello.c到hello.i的过程与结果有了更好的理解。
第3章 编译
3.1 编译的概念与作用
编译是指:编译器将文本文件hello.i翻译成文本文件hello.s,以汇编语言或者机器语言表示的目标程序作为输出。
编译的作用为将高级语言转化为汇编语言,实现程序的优化。
3.2 在Ubuntu下编译的命令
命令:gcc -S hello.i -o hello.s
3.3 Hello的编译结果解析
如图所示
1.常数
存储在.text文件中,使用时加入寄存器中
2.变量
3.赋值
对计数器变量i的赋值,开始赋初值0,然后跳到L3判断
4.类型转换
(原函数)
atoi函数将argv[]中的值转为int型
5.算数操作
每次循环结束后都要进行一次i++操作;
6.关系操作
i=0;i<8;i++
If(argc!=4)
7.数组操作
对arvg数组的引用
- 函数操作
本程序主要有printf函数,sleep函数,以及atoi函数的调用,设置用于参数传递的寄存器的值,之后通过call指令进行函数的调用。
- 控制转移
3.4 本章小结
本章主要学习了编译的概念和作用,通过gcc实现了hello.i到Hello.s的过程,并结合了原代码对汇编结果进行了分析,对于文件内部的各种数据以及操作进行了详细的叙述,同时对程序的机器级表示方法更加熟练。
第4章 汇编
4.1 汇编的概念与作用
汇编是指将汇编语言程序翻译成机器指令,并将这些指令打包成一种叫做可重定位目标程序,并将这个结果保留.o目标文件中。
汇编的作用是将汇编语言转化为机器语言,实现文本文件到二进制文件的转化
4.2 在Ubuntu下汇编的命令
命令:gcc -c hello.s -o hello.o
4.3 可重定位目标elf格式
使用命令readelf -a hello.o > hello1elf.txt,以查看elf文件
1.查看ELF头,其中含有的信息有系统的字的大小和字节顺序,ELF头的大小、目标文件的类型、机器类型、节头部表的文件偏移,以及节头部表中条目的大小和数量。
- 查看节头,节头描述了所有节的基本信息,例如段的段名、段的长度、在文件中的偏移、读写权限及段的其它属性。
- 查看符号表
4.4 Hello.o的结果解析
机器语言是二进制机器指令的集合,是纯粹的二进制数据表示的语言,是电脑可以真正识别的语言。机器指令由操作码和操作数构成。
汇编语言的操作数都是十进制数,机器语言是十六进制数。
在汇编语言中,访问printf中的字符串使用段名称+%rip,而在机器语言对应的反汇编程序为0+%rip。
调用函数时,汇编语言直接用函数名调用,而机器语言仍是用相对位 置调用,再在下一行写出函数的名称。
4.5 本章小结
本章学习了hello 从hello.s 到hello.o 的汇编过程,分析了可重定位文件的结构和各个组成部分,以及它们的内容和功能,学习汇编指令和机器指令之间的映射关系,更深刻地理解了汇编语言到机器语言的转变。
第5章 链接
5.1 链接的概念与作用
链接是将各种代码和数据片段收集并组合成一个单一文件的过程,这个文件可以被加载到内存并执行。链接可以执行于编译时,也就是在源代码被编译成机器代码时;也可以执行于加载时,也就是在程序被加载器加载到内存并执行时;甚至于运行时,也就是由应用程序来执行。
链接的作用是把可重定位目标文件和命令行参数作为输入,产生一个完全链接的,可以加载运行的可执行目标文件。使得分离编译成为可能。
5.2 在Ubuntu下链接的命令
命令:ld -o hello -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o hello.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o
5.3 可执行目标文件hello的格式
命令readelf -a hello > hello2elf.txt
1.查看elf头,可知hello文件类型为EXEC,即是一个可执行目标文件,文件中共有27个节。
- 查看节头
从Size可知各个段的大小,从Address可知各个段的起始地址即为程序被载入虚拟地址后各段的起始地址,从offset可知各个段在程序中的偏移量。
- 程序头
- 符号表
5.4 hello的虚拟地址空间
使用edb加载hello
可知程序的虚拟地址开始于0x400000
5.5 链接的重定位过程分析
命令objdump -d -r hello > hello_dis.txt
在该过程中链接器将所有相同类型的节合并,这个节就作为可执行目标文件的聚合节,在此之后,链接器把运行时的内存地址赋给新的聚合节,赋给输入模块定义的每个节,以及赋给输入模块定义的每个符号,当这一步完成时,程序中每条指令和全局变量都有唯一运行时的地址。
不同之处在于,hello的反汇编代码地址,是经过重定位的,为0x40xxxx的类型,而.o文件则是虚拟地址0开始。相比于hello.o而言,hello的反汇编添加了更多的节。与此同时,hello的反汇编引入了许多函数,因此main中可以直接调用函数的地址,而hello只能调用函数名。hello的反汇编中已经确定了虚拟地址,而hello.o中并没有。
5.6 hello的执行流程
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。
ld-2.23.so!_dl_start 0x7fdc27adbdf0
ld-2.27.so! dl_init 0x7fdc27aebc10
ld-2.27.so!_libc_start_main 0x401145
libc-2.27.so! cxa_atexit 0x7fdc27aef550
libc-2.27.so!_setjmp 0x7fdc27ae60d0
libc-2.27.so!_sigsetjmp 0x7fdc27ae4460
libc-2.27.so!__sigjmp_save 0x7fdc27adb396
hello!puts@plt 0x401090
hello!exit@plt 0x4010d0
hello!printf@plt 0x4010a0
hello!sleep@plt 0x4010e0
hello!getchar@plt 0x4010b0
ld-2.23.so!_dl_runtime_resolve_avx 0x7fdc27aec980
libc-2.27.so!exit 0x7fdc27adb2f0
5.7 Hello的动态链接分析
分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变化。要截图标识说明。
对于动态共享链接库中PIC函数,编译器没有办法预测函数的运行时地址,所以需要为其添加重定位记录,并等待动态链接器处理。为避免运行时修改调用模块的代码段,链接器采用延迟绑定的策略。动态链接器使用过程链接表PLT和全局偏移量表GOT实现函数的动态链接。其中GOT 中存放函数目标地址,PLT使用 GOT中地址跳转到目标函数。
节头中.got信息如图所示
用edb查看位置
在之后的函数调用时,首先跳转到PLT执行.plt中逻辑,第一次访问跳转时,GOT地址为下一条指令,将函数序号压栈,然后跳转到PLT[0],在 PLT[0]中将重定位表地址压栈,然后访问动态链接器,在动态链接器中使用函数序号和重定位表确定函数运行时地址,重写 GOT,再将控制传递给目标函数。
5.8 本章小结
本章介绍了链接的内容,实现了在ubuntu下链接命令的执行,并对hello的elf格式进行了详细的分析对比,详细了解了重定位过程,遍历了整个hello的执行过程,同时在最后对hello进行了动态链接分析,使得对hello的链接过程有了一个更深刻的理解和体会。
第6章 hello进程管理
6.1 进程的概念与作用
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
进程有如下性质
动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。
多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
进程主要为用户提供了下列两个假象
(1)一个独立的逻辑流,提供程序独占使用处理器的假象。
(2)一个私有的虚拟地址空间,提供程序独占使用整个系统内存的假象。
6.2 简述壳Shell-bash的作用与处理流程
作用:shell是命令行界面,是系统内核的一层壳,作用是用来保护内核同时传递入与计算机交互的信息.它只是系统的一个工具,我们可以使用它来操作计算机。6.3 Hello的fork进程创建过程。
处理流程:
- 读取命令行的字符串
- 分割字符串,读取对应的命令
- 判断是否为内置命令,如果是则直接运行,不是则fork一个子进程运行
- 子进程用execve运行对应的命令
- 等待前台进程结束
- 返回读去阶段
6.3 Hello的fork进程创建过程
6.4 Hello的execve过程
1,hello子进程通过execve系统调用启动加载器。
2,加载器删除子进程所有的虚拟地址段,并创建一组新的代码、数据、堆段。新的栈和堆段被初始化为0。
3,通过将虚拟地址空间中的页映射到可执行文件的页大小的片(chunk),新的代码和数据段被初始化为可执行文件中的内容。
4,最后加载器跳到_start地址,它最终调用hello的main 函数。除了一些头部信息,在加载过程中没有从磁盘到内存的数据复制。直到CPU引用一个被映射的虚拟页时才会进行复制,此时,操作系统利用它的页面调度机制自动将页面从磁盘传送到内存。
6.5 Hello的进程执行
结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。
上下文信息:上下文指内核重新启动一个被抢占的进程所需要的状态,它由通用寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内 核数据结构等对象的值构成。
进程时间片:一个进程执行它的控制流的一部分的每一时间段叫做时间片。
调度:在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被强占的进程。
进程hello初始在用户模式中运行,当它通过执行系统调用函数sleep或者exit时,进入到内核。内核中,处理程序完成对系统函数的调用。之后上下文切换,将进程hello系统调用之后的语句。
6.6 hello的异常与信号处理
(以下格式自行编排,编辑时删除)
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
6.7本章小结
通过创建,加载,终止hello程序,了解了shell-bash的概念与作用,并学到了hello的异常与处理。
结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
- hello.c经过预编译变为hello.i 文件
- hello.i经过编译变为汇编语言hello.s文件
- hello.s经过汇编变为机器语言hello.o文件
- 在shell中输入命令行指令,运行hello程序。
- 如果不是内置指令,shell fork一个子进程
- 最后hello运行完毕,被shell回收
附件
hello.i 预处理得到的文本文件
hello.s 编译后得到的文本文件
hello.o 汇编得到的可重定位目标文件
参考文献
为完成本次大作业你翻阅的书籍与网站等
[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.