大作业
题 目 程序人生-Hello’s P2P
专 业 计算学部
学 号 xxxxxxxxxx
班 级 xxxxxx
学 生 xxx
指 导 教 师 xxx
计算机科学与技术学院
2021年6月
摘 要
本文以hello小程序为例,通过对其在Linux系统下的P2P、020过程的分析梳理,来完成对计算机系统课程的整体内容的梳理,借由Ubuntu虚拟机,gcc、gdb、edb等工具的操作过程,体现个人对计算机系统课程的学习体会与理解,展示各人的收获。
关键词:hello程序的一生;计算机系统;Linux;Ubuntu
目 录
第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.3.1 字符串 - 9 -
3.3.2 全局函数 - 10 -
3.3.3 赋值操作 - 10 -
3.3.4 算术操作 - 10 -
3.3.5 关系操作 - 11 -
3.3.6 控制转移指令 - 11 -
3.3.7 函数操作 - 12 -
3.3.8 类型转换 - 13 -
3.4 本章小结 - 13 -
第4章 汇编 - 14 -
4.1 汇编的概念与作用 - 14 -
4.2 在Ubuntu下汇编的命令 - 14 -
4.3 可重定位目标elf格式 - 14 -
4.4 Hello.o的结果解析 - 16 -
4.5 本章小结 - 17 -
第5章 链接 - 18 -
5.1 链接的概念与作用 - 18 -
5.2 在Ubuntu下链接的命令 - 18 -
5.3 可执行目标文件hello的格式 - 18 -
5.4 hello的虚拟地址空间 - 20 -
5.5 链接的重定位过程分析 - 22 -
5.6 hello的执行流程 - 23 -
5.7 Hello的动态链接分析 - 23 -
5.8 本章小结 - 24 -
第6章 hello进程管理 - 25 -
6.1 进程的概念与作用 - 25 -
6.2 简述壳Shell-bash的作用与处理流程 - 25 -
6.3 Hello的fork进程创建过程 - 25 -
6.4 Hello的execve过 - 25 -
6.5 Hello的进程执行 - 26 -
6.6 hello的异常与信号处理 - 26 -
6.7本章小结 - 30 -
第7章 hello的存储管理 - 31 -
7.1 hello的存储器地址空间 - 31 -
7.2 Intel逻辑地址到线性地址的变换-段式管理 - 31 -
7.3 Hello的线性地址到物理地址的变换-页式管理 - 31 -
7.4 TLB与四级页表支持下的VA到PA的变换 - 32 -
7.5 三级Cache支持下的物理内存访问 - 34 -
7.6 hello进程fork时的内存映射 - 35 -
7.7 hello进程execve时的内存映射 - 35 -
7.8 缺页故障与缺页中断处理 - 35 -
7.9动态存储分配管理 - 35 -
7.10本章小结 - 36 -
第8章 hello的IO管理 - 37 -
8.1 Linux的IO设备管理方法 - 37 -
8.2 简述Unix IO接口及其函数 - 37 -
8.3 printf的实现分析 - 37 -
8.4 getchar的实现分析 - 37 -
8.5本章小结 - 38 -
结论 - 38 -
附件 - 39 -
参考文献 - 40 -
根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。
P2P:From Program to Process
Program:在编辑器中编写hello.c的具体代码内容
Process:在Linux中,先通过预处理器(cpp)修改原始的c文件得到另一个以.i为文件扩展名的C程序;接着,编译器(ccl)将文本文件hello.i翻译成hello.s,这个文件包含一个汇编语言程序;然后,汇编器(as)将.s文件翻译成机器语言指令,将这些指令打包成可重定位目标程序的格式,并将结果保存在hello.o文件中;最后链接器(ld)负责处理.o文件的合并,来实现函数的正确调用,并得到最后的可执行文件hello,可以被加载到内存中由系统执行。
020:From Zero to Zero
shell接受到./hello的指令之后就调用fork开辟进程,execve映射虚拟内存,进入程序入口后程序开始载入物理内存。之后程序由CPU控制其逻辑流的运行,运行结束后,shell父进程负责回收资源,这就是hello的020.
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件环境:
软件环境:
VirtualBox;Ubuntu 20.04 LTS 64位
开发工具:
Visual Studio 2019 64位;CodeBlocks;vim+gcc
调试工具:
gdb;edb
列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。
中间结果文件 |
文件作用 |
hello.i |
预处理得到的文件 ASCII码的中间文件 |
hello.s |
ASCII汇编语言文件 |
hello.o |
as得到可重定位目标文件 |
Disas_hello.s |
反汇编得到的文本文件 |
elf.txt |
hello.o的elf文件 |
hello |
ld得到可执行目标文件 |
hello_5.3.elf |
hello的elf文件 |
hello_objdump.s |
hello的反汇编文件 |
本章简单阐述了Hello的P2P,020的整个过程,介绍了编写本文过程所处的软硬件环境和生成的中间文件。
预处理的概念:
预处理器(cpp)根据以字符#开头的命令,修改原始的C程序,试图解释为预处理指令(preprocessing directive) 。
ISO C/C++要求支持的预处理指令包括:
#if、 #ifdef、 #ifndef、 #else、 #elif、 #endif(条件编译)、 #define(宏定义)、 #include(源文件包含)、 #line(行控制)、 #error(错误指令)、 #pragma(和实现相关的杂注)以及单独的#(空指令)。
预处理指令一般被用来使源代码在不同的执行环境中被方便的修改或者编译。
预处理的作用:
cpp hello.c > hello.i
截图2-1
截图2-2
浏览hello.i文件可发现,只有28行的源码已经扩展至3065行,hello.i程序的开始是c程序头文件stdio.h unistd.h stdlib.h的依次展开,这三个头文件都被复制进来了。
截图2-3
本章简单介绍的与处理的概念及作用,完成了对hello.c文件的预处理操作,并简单解析了hello.i的预处理结果。
编译的概念:编译器将文本文件 hello.i 翻译成文本文件 hello.s,它包含一个汇编语言程序。其以高级程序设计语言书写的源程序作为输入,而以汇编语言或机器语言表示的目标程序作为输出。 这个过程称为编译,同时也是编译的作用。
编译的作用:编译程序的基本功能是把源程序(高级语言)翻译成目标程序。除了基本功能之外,编译程序还具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人际联系等重要功能。
截图3-1
截图3-4、3-5
main函数声明了一个局部变量i,编译器进行编译的时候会将局部变量i存在堆栈中。如图所示,局部变量i放在栈上-4(%rbp)的位置。
截图3-6
参数 argc 作为用户传给main的参数存放在堆栈中。
立即数直接体现在汇编代码中
数组char *argv[]是作为main函数的第二个参数,其中的每个元素都是一个指向字符类型的指针。数组的起始地址存放在栈中-32(%rbp)的位置,被两次调用将参数传给printf函数
截图3-7
其中:
movq -32(%rbp),%rax表示数组argv存放的位置-32(%rbp)
movq (%rax),%rdx
movq (%rax),%rax 分别获取argv[1]和argv[2]的地址
movq (%rax),%rsi
由c程序可知,hello.c声明了一个全局函数int main(int argc,char *argv[]),经过编译之后,main函数中使用的字符串常量也被存放在数据区。
截图3-8
这行汇编代码说明main函数是全局函数。
hello.c程序中的赋值操作为 i = 0
该操作在汇编代码中由mov指令实现,具体为:
movb:一个字节
movw:两个字节
movl:四个字节
movq:八个字节
hello.c程序中的算术操作为:i++。因为i为int类型,故汇编代码只用addl就能实现其他的操作有
指令 |
效果 |
leaq S,D |
D=&S |
INC D |
D+=1 |
DEC D |
D-=1 |
NEG D |
D=-D |
ADD S,D |
D=D+S |
SUB S,D |
D=D-S |
(1)argc!=3;是在一条件语句中的条件判断:argc!=3,进行编译时,这条指令被编译为:cmpl $3,-20(%rbp),同时这条cmpl的指令还有设置条件码的作用,当根据条件码来判断是否需要跳转到分支中。
截图3-9
(2)i < 8,在hello.c作为判断循环条件,在汇编代码被编译为:cmpl $9,-4(%rbp),计算 i-7然后设置 条件码,为下一步 jle 利用条件码进行跳转做准备。
截图3-10
首先设置条件码,然后根据条件码来进行控制转移。hello.c中有以下控制转移指令:
截图3-11
截图3-12
第一处画圈:i赋初值0,然后无条件跳转至判断条件的代码中
第二处画圈:判断i是否符合循环的条件,符合直接跳转至循环体的内部,即L4
调用函数时有以下操作:
(假设函数P调用函数Q)
(1)传递控制:进行过程 Q 的时候,程序计数器设置为 Q 的代码的起始地址;返回时,把程序计数器设置为 P 中调用 Q 后面那条指令的地址。
(2)传递数据:P 能够向 Q 提供一个或多个参数,而Q 能够向 P 中返回一个返回值。
(3) 分配和释放内存:开始时,Q 可能需要为局部变量分配空间,而在返回前需释放这些空间。
hello.c程序中涉及的函数操作有:
main函数,printf,exit,sleep ,getchar函数
main函数的参数是argc和argv;两次printf函数的参数恰好是那两个字符串
exit参数是1,sleep函数参数是atoi(argv[3])
函数的返回值存储在%eax寄存器中。
hello.c中涉及的类型转换是:atoi(argv[3]),将字符串类型转换为整数类型其他的类型转换还有int、float、double、short、char之间的转换。
本章主要阐述了编译阶段中编译器是如何处理各种数据和操作的,以及简单分析了c语言中各种类型和操作所对应的的汇编代码。
汇编的概念:驱动程序运行汇编器as,将汇编语言翻译成机器语言的过程称为汇编,同时这个机器语言文件也是可重定位目标文件。
汇编的作用:汇编是将高级语言转化为机器可直接识别执行的代码文件的过程,汇编器将.s 汇编程序翻译成机器语言指令,把这些指令打包成可重定位目标程序的格式,并将结果保存在.o 目标文件中,.o 文件是一个二进制文件,它包含程序的指令编码。
截图4-1
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
截图4-2
截图4-3
截图4-4
hello.c需要重定位的信息有:.rodata中的模式串、puts、exit、printf、slepsecs、sleep、getchar等符号。
截图4-5
截图4-6
objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
截图4-7
截图4-8
本章对hello.s的结果进行了阐述,分析了可重定位文件的ELF头、节头部表、符号表和可重定位节,比较了hello.s和hello.o反汇编代码的区别,分析了机器语言的构成与汇编语言的映射关系。
链接的概念:链接是将各种不同文件的代码和数据部分收集(符号解析和重定位)起来并组合成一个单一文件的过程。
链接的作用:令源程序节省空间而未编入的常用函数文件进行合并,生成可以正常工作的可执行文件。这令分离编译成为可能,节省了大量的工作空间。
指令:
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-1
指令:
ELF头:hello的文件头和hello.o文件头的不同之处如下图标记所示,Type类型为EXEC表明hello是一个可执行目标文件,有27个节头。
截图5-2
节头:描述各个节的大小、偏移量和其他属性。链接器链接时,会将各个文件的相同段合并成一段,并且根据该段的大小以及偏移量重新设置各个符号的地址。
截图5-3
截图5-4
重定位节
截图5-5
符号表
截图5-6
在edb中加载hello可执行文件
截图5-7
观察edb的Data Dump窗口。窗口显示虚拟地址由0x400000开始,到0x400fff结束,这之间的每一个节对应5.3中的每一个节头表的声明。
截图5-8
观察edb的Sympols Viewer,发现确实从虚拟地址从0x400000开始和5.3节中的节头表是对应的。
截图5-9
根据5.3中的的节头,可以在edb中找到各个节的信息。比如.rodata节,虚拟地址开始于0x402000,大小为0x2f
截图5-10
objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
指令:
截图5-11
hello与hello.o的不同:
截图5-12
链接的过程:
链接就是链接器(ld)将各个目标文件(各种.o文件)组装在一起,文件中的各个函数段按照一定规则累积在一起。
链接的重定位过程说明:
要合并相同的节,确定新节中所有定义符号在虚拟地址空间中的地址,还要对引用符号进行重定位(确定地址),修改.text节和.data节中对每个符号的引用(地址),而这些需要用到在.rel_data和.rel_text节中保存的重定位信息。
截图5-13
子程序地址:
7efb ff4d8ea0 |
7efb ff4e7630 |
004004c0 |
004004c0 |
004004a0 |
00400500 |
004004d0 |
004004f0 |
7efb ff122120 |
对于动态共享链接库中PIC函数,编译器没有办法预测函数的运行时地址,所以需要为其添加重定位记录,并等待动态链接器处理。为避免运行时修改调用模块的代码段,链接器采用延迟绑定的策略。动态链接器使用过程链接表PLT和全局偏移量表GOT实现函数的动态链接。其中GOT 中存放函数目标地址,PLT使用 GO T中地址跳转到目标函数。
在elf文件中可以找到:
截图5-14
edb执行init之前的地址:
截图5-15
edb在执行init之后的地址:
截图5-16
GOT表位置在调用dl_init之前0x600920后的16个字节均为0,调用后发生了变化。
之后的函数调用时,首先跳转到PLT执行.plt中逻辑,第一次访问跳转时,GOT 地址为下一条指令,将函数序号压栈,然后跳转到PLT[0],在 PLT[0]中将重 定位表地址压栈,然后访问动态链接器,在动态链接器中使用函数序号和重定位 表确定函数运行时地址,重写 GOT,再将控制传递给目标函数。之后如果对同样函数调用,第一次访问跳转直接跳转到目标函数。
本章温习了在linux中链接的过程。通过查看hello的虚拟地址空间,对比hello与hello.o的反汇编代码,进一步掌握了链接与中重定位的过程;遍历了整个hello的执行过程,在最后对hello进行了动态链接分析
进程的概念:
进程是执行中程序的抽象,是一个执行中程序的实例。
进程的作用:
能够实现计算机并行实现不同任务的构想,使得程序的模式切换更加自如迅速,效率更高。
进程提供给应用程序的关键抽象:一个独立的逻辑控制流,如同程序独占处理器;一个私有的地址空间,如同程序独占内存系统。
作用:
解释命令,连接用户和操作系统以及内核。
流程:
·终端进程读取用户由键盘输入的命令行。
·分析命令行字符串,获取命令行参数,并构造传递给execve的argv向量
·检查第一个(首个、第0个)命令行参数是否是一个内置的shell命令
·如果不是内部命令,调用fork( )创建新进程/子进程
·在子进程中,用步骤2获取的参数,调用execve( )执行指定程序。
·如果用户没要求后台运行(命令末尾没有&号)否则shell使用waitpid(或wait…等待作业终止后返回。
·如果用户要求后台运行(如果命令末尾有&号),则shell返回;
在shell的命令行,用户完成输入命令。shell在解析输入命令之后创建argv、envp等参数列表,以及参数个数argc。shell作为父进程创建新子进程。子进程与父进程拥有完全相同的虚拟内存地址以及副本,但虚拟地址确是独立的,而且PID也不相同。
fork之后子进程调用execve函数在当前进程的上下文中加载并运行一个新程序即hello程序。execve加载并运行可执行目标文件,且带参数列表argv和环境变量列表envp,并将控制传递给main函数。
结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。
逻辑控制流:一系列程序计数器PC的值的序列叫做逻辑控制流,这些值唯一地对应于包含在程序的可执行目标文件中的指令,或是包含在运行时动态链接到程序的共享对象中的指令。
时间片:一个进程执行它的控制流的一部分的每一时间段叫做时间片。
用户模式和内核模式:shell使得用户可以有机会修改内核,所以需要设置一些防护措施来保护内核,如限制指令的类型和可以作用的范围。
上下文切换:上下文就是内核重新启动一个被抢占的进程所需要的状态,是一种比较高层次的异常控制流。
开始Hello运行在用户模式,收到信号后进入内核模式,运行信号处理程序,之后再返回用户模式。运行过程中,cpu不断切换上下文,使运行过程被切分成时间片,与其他进程交替占用cpu,实现进程的调度。
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
hello的异常:
1)中断:来自处理器外部的I/O设备的信号的结果。
键盘上敲击CTRL -C或者CTRL-Z
产生的信号:
SIGINT,SIGSTP,SIGCONT,SIGWINCH
运行截图:
Ctrl+C(截图6-1)
Ctrl+Z(截图6-2)
Ctrl+Z后ps、jobs(截图6-3)
截图6-4
截图6-5
截图6-6
截图6-7
Pstree(截图6-8)
fg(截图6-9)
kill(截图6-10)
本章概述了进程的概念,简要介绍了shell处理过程的方式,介绍了fork和execve两个函数的执行过程以及信号异常的处理。
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
逻辑地址:格式为“段地址:偏移地址”,是CPU生成的地址,在内部和编程使用,并不唯一。
物理地址:加载到内存地址寄存器中的地址,内存单元的真正地址。CPU通过地址总线的寻址,找到真实的物理内存对应地址。在前端总线上传输的内存地址都是物理内存地址。
虚拟地址:有时我们也把逻辑地址称为虚拟地址。因为与虚拟内存空间的概念类似,逻辑地址也是与实际物理内存容量无关的,是hello中的虚拟地址。
物理地址:指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。如果启用了分页机制,那么hello的线性地址会使用页目录和页表中的项变换成hello的物理地址;如果没有启用分页机制,那么hello的线性地址就直接成为物理地址了。
分段功能在实模式和保护模式下有所不同。
实模式:逻辑地址=线性地址=实际的物理地址。段寄存器存放真实段基址,同时给出32位地址偏移量,则可以访问真实物理内存。
保护模式:线性地址还需要经过分页机制才能够得到物理地址,线性地址也需要逻辑地址通过段机制来得到。
段寄存器用于存放段选择符,通过段选择符可以得到对应段的首地址。处理器在通过段式管理寻址时,首先通过段描述符得到段基址,然后与偏移量结合得到线性地址,从而得到了虚拟地址。
将各进程的虚拟空间划分成若干个长度相等的页(page),页式管理把内存空间按页的大小划分成片或者页面(page frame),然后把页式虚拟地址与内存地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。页式管理采用请求调页或预调页技术实现了内外存存储器的统一管理。
使用K级页表的地址翻译
截图7-1
四级页表翻译
截图7-2
针对core i7页表翻译
截图7-3
Core i7 1-3级页表条目格式
截图7-4
其中,每个条目引用一个 4KB子页表:
1)P: 子页表在物理内存中 (1)不在 (0).
2)R/W: 对于所有可访问页,只读或者读写访问权限.
3)U/S: 对于所有可访问页,用户或超级用户 (内核)模式访问权限.
4)WT: 子页表的直写或写回缓存策略.
5)A: 引用位 (由MMU 在读或写时设置,由软件清除).
6)PS: 页大小为4 KB 或 4 MB (只对第一层PTE定义).
7)Page table physical base address: 子页表的物理基地址的最高40位 (强制页表 4KB 对齐)
8)XD: 能/不能从这个PTE可访问的所有页中取指令。
Core i7 第 4 级页表条目格式
截图7-5
P: 子页表在物理内存中 (1)不在 (0).
R/W: 对于所有可访问页,只读或者读写访问权限.
U/S: 对于所有可访问页,用户或超级用户 (内核)模式访问权限.
WT: 子页表的直写或写回缓存策略.
A:引用位 (由MMU 在读或写时设置,由软件清除).
D: 修改位 (由MMU 在读和写时设置,由软件清除)
Page table physical base address: 子页表的物理基地址的最高40位 (强制页表 4KB 对齐)
XD: 能/不能从这个PTE可访问的所有页中取指令.
1、CPU给出VA
2、MMU用VPN到TLB中找寻PTE,若命中,得到PA;若不命中,利用VPN(多级页表机制)到内存中找到对应的物理页面,得到PA。
3、PA分成PPN和PPO两部分。利用其中的PPO,将其分成CI和CO,CI作为cache组索引,CO作为块偏移,PPN作为tag。
先访问一级缓存,不命中时访问二级缓存,再不命中访问三级缓存,再不命中访问主存,如果主存缺页则访问硬盘
截图7-6
当 fork 函数被 shell 进程调用时,内核为新进程创建各种数据结构,并分配给 它一个唯一的 PID,为了给这个新进程创建虚拟内存,它创建了当前进程的 mm_struct、区域结构和页表的原样副本。它将这两个进程的每个页面都标记为只 读,并将两个进程中的每个区域结构都标记为私有的写时复制。
删除已存在的用户区域。
映射私有区域:为新程序的代码、数据、.bss和栈区域创建新的区域结构。
映射共享区:hello与系统执行文件链接映射到共享区域。
设置程序计数器PC:设置当前进程上下文中的PC,指向代码区域的入口点。
缺页故障是一种常见的故障,要访问的主页不在主存,需要操作系统调入才能访问。缺页中断处理函数为do_page_fault函数。
截图7-7
基本方法与策略:通过维护虚拟内存(堆),一种是隐式空闲链表,一种是显式空闲链表。显式空闲链表法是malloc(size_t size)每次声明内存空间都保证至少分配size_t大小的内存,双字对齐,每次必须从空闲块中分配空间,在申请空间时将空闲的空间碎片合并,以尽量减少浪费。
本章主要介绍了hello的存储器的地址空间,介绍了四种地址空间的差别和地址的相互转换。同时介绍了hello的四级页表的虚拟地址空间到物理地址的转换。简要阐述了三级cashe的物理内存访问、进程 fork 时的内存映射、execve 时的内存映射、缺页故障与缺页中断处理以及动态存储分配管理。
设备的模型化:文件:所有的I/O设备都被模型化为文件,甚至内核也被映射为文件
设备管理:unix io接口:所有的输入和输出都被当做对相应文件的读和写来执行,这种将设备优雅地映射为文件的方式,允许 Linux 内核引出一个简单低级的应用接口,称为 Unix I/O。
Linux以文件的方式对I/O设备进行读写,将设备均映射为文件。对文件的操作,内核提供了一种简单、低级的应用接口,即Unix I/O接口。
打开文件:int open(char *filename, int flags, mode_t mode);
关闭文件:int close(int fd);
读文件:ssize_t read(int fd, void *buf, size_t n);
写文件:ssize_t write(int fd, const void *buf, size_t n);
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
本章主要介绍了Linux的IO设备管理方法、Unix IO接口及函数,简要分析了printf和getchar函数的实现。
hello程序的过程可总结如下:
1、编写代码:用高级语言写.c文件
2、预处理:hello.c经过预编译,拓展得到hello.i文本文件
3、编译:由.i文件生成.s汇编文件
4、汇编:经过汇编,.s文件被翻译为机器语言指令,并打包成可重定位目标程序hello.o
5、链接:将.o可重定位目标文件和动态链接库链接成可执行目标程序hello。P2P过程完成。
6、运行:在shell中输入命令
1)创建子进程:shell嗲用fork为程序创建子进程
2)加载:shell调用execve函数,将hello程序加载到该子进程,映射虚拟内存
3)执行指令:CPU为进程分配时间片,加载器将计数器预置在程序入口点,则hello可以顺序执行自己的逻辑控制流
4)访问内存:MMU将虚拟内存地址映射成物理内存地址,CPU通过其来访问
5)动态内存分配:根据需要申请动态内存
6)信号:shell的信号处理函数可以接受程序的异常和用户的请求
7、终止:执行完成后父进程回收子进程,内核删除为该进程创建的数据结构
至此,hello运行结束。
中间结果文件 |
文件作用 |
hello.i |
预处理得到的文件 ASCII码的中间文件 |
hello.s |
ASCII汇编语言文件 |
hello.o |
as得到可重定位目标文件 |
Disas_hello.s |
反汇编得到的文本文件 |
elf.txt |
hello.o的elf文件 |
hello |
ld得到可执行目标文件 |
hello_5.3.elf |
hello的elf文件 |
hello_objdump.s |
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.
(参考文献0分,缺失 -1分)