计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 医学与健康学院
学 号 2022112326
班 级 2252002
学 生 陆禹聪
指 导 教 师 史先俊
计算机科学与技术学院
2024年5月
本文旨在于深度融合在csapp课程中学习到的计算机系统知识,以提供的hello.c程序为基础,探索程序在UBUNTU虚拟机linux系统下探究程序的整个生命周期,从硬件和软件两个方面全方位解读程序运行过程发生的变化,具体包括从源程序hello.c,经过预处理,汇编,编译,链接,具体的呈现,进程的进一步管理以及进程生命周期终止时的情况,并且在过程中,结合具体情况,详细论述分析系统中的存储管理,I/O管理。同时,利用多种多样的调试工具,我们在这里将完整展现hello.c执行过程中每一步系统的变化,深刻理解硬件对于整个程序进程的调控,伴随程序体验计算机系统世界的奇妙。
关键词:hello.c ,linux ,计算机系统,UBUNTU,debug
(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)
目 录
第1章 概述................................................................................... - 4 -
1.1 Hello简介............................................................................ - 4 -
1.2 环境与工具........................................................................... - 4 -
1.3 中间结果............................................................................... - 4 -
1.4 本章小结............................................................................... - 4 -
第2章 预处理............................................................................... - 5 -
2.1 预处理的概念与作用........................................................... - 5 -
2.2在Ubuntu下预处理的命令................................................ - 5 -
2.3 Hello的预处理结果解析.................................................... - 5 -
2.4 本章小结............................................................................... - 5 -
第3章 编译................................................................................... - 6 -
3.1 编译的概念与作用............................................................... - 6 -
3.2 在Ubuntu下编译的命令.................................................... - 6 -
3.3 Hello的编译结果解析........................................................ - 6 -
3.4 本章小结............................................................................... - 6 -
第4章 汇编................................................................................... - 7 -
4.1 汇编的概念与作用............................................................... - 7 -
4.2 在Ubuntu下汇编的命令.................................................... - 7 -
4.3 可重定位目标elf格式........................................................ - 7 -
4.4 Hello.o的结果解析............................................................. - 7 -
4.5 本章小结............................................................................... - 7 -
第5章 链接................................................................................... - 8 -
5.1 链接的概念与作用............................................................... - 8 -
5.2 在Ubuntu下链接的命令.................................................... - 8 -
5.3 可执行目标文件hello的格式........................................... - 8 -
5.4 hello的虚拟地址空间......................................................... - 8 -
5.5 链接的重定位过程分析....................................................... - 8 -
5.6 hello的执行流程................................................................. - 8 -
5.7 Hello的动态链接分析........................................................ - 8 -
5.8 本章小结............................................................................... - 9 -
第6章 hello进程管理.......................................................... - 10 -
6.1 进程的概念与作用............................................................. - 10 -
6.2 简述壳Shell-bash的作用与处理流程........................... - 10 -
6.3 Hello的fork进程创建过程............................................ - 10 -
6.4 Hello的execve过程........................................................ - 10 -
6.5 Hello的进程执行.............................................................. - 10 -
6.6 hello的异常与信号处理................................................... - 10 -
6.7本章小结.............................................................................. - 10 -
第7章 hello的存储管理...................................................... - 11 -
7.1 hello的存储器地址空间................................................... - 11 -
7.2 Intel逻辑地址到线性地址的变换-段式管理................... - 11 -
7.3 Hello的线性地址到物理地址的变换-页式管理............. - 11 -
7.4 TLB与四级页表支持下的VA到PA的变换.................... - 11 -
7.5 三级Cache支持下的物理内存访问................................ - 11 -
7.6 hello进程fork时的内存映射......................................... - 11 -
7.7 hello进程execve时的内存映射..................................... - 11 -
7.8 缺页故障与缺页中断处理................................................. - 11 -
7.9动态存储分配管理.............................................................. - 11 -
7.10本章小结............................................................................ - 12 -
第8章 hello的IO管理....................................................... - 13 -
8.1 Linux的IO设备管理方法................................................. - 13 -
8.2 简述Unix IO接口及其函数.............................................. - 13 -
8.3 printf的实现分析.............................................................. - 13 -
8.4 getchar的实现分析.......................................................... - 13 -
8.5本章小结.............................................................................. - 13 -
参考文献....................................................................................... - 16 -
第1章 概述
1.1 Hello简介
1.p2p FROM PROGRAM TO PROCESS
在相关编程软件如codeblocks,vscode中编程得到hello.c c源文件,为了实现其执行,每条语句都应该被转化为一系列低级机器语言指令,并将其最终转化为一种称为可执行目标程序的格式,以二进制磁盘形式存储,从源文件到可执行文件的转化主要由编译器驱动程序完成,首先由cpp进行预处理,读取#开头文件内容并插入文本中,得到.i文件,随后经过编译器,将其转化为汇编语言得到一个.s文件,接下来由汇编器将其翻译为机器语言指令,得到hello.o,这是一个二进制文件,最后由链接器将不同的单独编译好的文件链接,得到一个可执行目标文件。当在shell中输入./hello,首先经过命令行解析,调用fork函数创建进程,利用exceve函数加载执行hello程序,这样就从,program转化为了一个进程process,程序正式开始运行了。
图 1 Hello的编译过程
2.020 FROM 0 TO 0
从0开始创建程序,再到运行结束,生命周期终止,一个程序就从无到有由从归于无,从p2p过程完成了进程的创建,exceve将程序映射虚拟空间,跳转到第一条指令执行后,hello进程持续运行,当他终止后,僵死等待父程序来回收hello,彻底不再占用内存空间,回归0.
1.2 环境与工具
环境与工具硬件环境:处理器:X64 CPU;12th Gen Intel(R) Core(TM) i7-12650H ;2.30 GHz;机带:16G RAM;256G SSD Disk;1T HDD Disk软件环境:Windows11家庭中文版 64位;VMware Workstation PRO 17;Ubuntu 20.04.2 LTS 64位开发/调试工具:Visual Studio 2022;vim/gpedit+gcc/as/ld/edb/readelf;VSCode
1.3 中间结果
文件名 作用
hello.i 预处理完成的文件
hello.s 编译完成后的文件
hello.o 汇编后的可重定位文件
hello111 链接后的可执行目标文件
elf.txt ELF格式的hello.o
hello_o_disass.s hello.o反汇编代码
elf_hello.txt hello111ELF格式
hello_disass.s hello111反汇编代码
1.4 本章小结
本章主要概括了p2p和020,并介绍了之后可能用到的文件以及硬件环境。
(第1章0.5分)
第2章 预处理
2.1 预处理的概念与作用
预处理是指,在传递给编译器进行编译之前,先对,c文件进行相关处理,主要是针对以#开头的文件比如可能涉及的头文件调用以及相关的宏定义,将这些对应的命令插入到文本中,使其满足下一步编译的需要。
在#后跟随如系统头文件的内容时,系统将读取头文件内容,并直接插入到文本中,实现对头文件内容的调用。
同时,如果其后跟随一个宏定义,也会用实际值替换文本中出现的定义
还可以去选择性进行编译,根据后面跟随的if等命令进行选择,在处理过程中还会将所有的注释转化为空格。
2.2在Ubuntu下预处理的命令
命令: gcc -E hello.c -o hello.i
-E主要代表制定了编译过程应该为预处理,而-o则代表制定一个输出的文件,这里则是制定了hello.i
2.3 Hello的预处理结果解析
分析上述图片中展示的hello.i文件内容,可以发现,结尾处仍然保留着原有c代码的格式,这一段并没有被明显处理,但是开头以#开头的文件被大量代码替换,实际上是已经将头文件内容插入,便于下一步编译处理
2.4 本章小结
主要描述了预处理的全过程,依托于hello.程序为基础,展示了预处理的全过程,并详细分析了其每一步,每一种处理方式的作用,这些预处理将为下一步的编译做好准备,便于系统编译。
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
计算机执行机器代码,编译器将以汇编代码的形式输出,汇编代码实际上是机器代码的一种文本表示,将程序中具体地每一条指令给出,编译的过程实际上可以理解为是更便于人类理解的高级语言转化为更有利于计算机理解的语言的过程,高级语言抽象有时会隐蔽需要了解的程序行为,而汇编语言更便于理解机器行为,同时也是机器能理解的语言,从.i到.s文件,以高级语言为输入,汇编语言为输出,便于机器理解。
3.2 在Ubuntu下编译的命令
类似刚才的预处理阶段,-s制定了为编译处理,-o制定输出文件
3.3 Hello的编译结果解析
如上是具体的编译结果,可以发现已经转化为了汇编语言,接下来进行进一步详细分析。
3.3.1 伪指令
首先观察编译结果,我们会发现有很多以.开头的段,这些行都是指导汇编器和连接器工作的伪指令,我们通常情况下可以忽略他们,他们也不存在具体的和源代码的对应关系。
以这一小段代码为例,其中,.file声明源文件,.text指定了代码节,.section指示文件代码段,.aligon指示了数据指令地址对齐方式,便于数据读取,.string声明字符串,.global声明全局变量,还常出现.rodata,证明这是一个只读文件。
3.3.2 数据
- 常量
如图所示的部分,就代表一个字符串,因为其值是常量不应被修改,储存在.rodata节,只读,如果是数值型常量,比如100,也会采取同样的处理方式。
2.变量
变量区分为全局变量和局部变量,二者的存储实现方式有所不同
- 全局变量存储在.data节
- 局部变量,局部变量在程序执行过程中开辟,主要储存在寄存器和栈中,可以动态变化,本程序中的int i就是局部变量
上述的rbp作为帧指针,表示栈的位置,从而将这个数字传输到栈中。
3.操作数
立即数,在上述图片中,以$开头的数字,就是立即数,直接表示常数值,在上一个图片中,表示把0这个整数传入对应位置。
寄存器,表示某个寄存器内容
这里的rax,rbp等都是寄存器,表示数据在他们之间进行传递,带有括号则指示了对应的寻址方式
3.3.3 操作
- 压栈,弹栈
将数据压入栈使用pushq指令,弹出则使用poq指令,每条指令实际上都对应着两个操作,首先是对栈得收缩,然后是将对应元素移入栈
这里将rbp移入栈就使用了pushq指令,使rbp作为帧指针,指向当时得栈指针得位置,可用于变长栈帧技术。
2.算数操作
在这个程序中,使用了i++得增值操作,每次循环使i+1
这里发先具有不同得后缀q,代表传送字节大小不同,l代表双字,q代表四字,
3.赋值操作
主要通过mov指令实现
4.关系指令,跳转
本程序主要使用!=和<=,!=判断使用jne,<=使用jle
5.函数调用操作
前面部分曾介绍过部分参数传递的机制,在64位编译模式下,汇编程序的参数传递先借助寄存器,前六个参数使用寄存器rsi、rdi、rdx、rcx、r8、r9,之后的参数在利用栈,将其压入栈中。前面的分析过程中包含了printf函数和main函数的传参机制。
首先调用函数时,将返回地址压栈,之后观察是否压入所需参数,为了实现变长栈帧,压入帧指针rbp,如果有被调用者保存寄存器,如在递归中,则需要把这些寄存器也压入栈,函数调用完成返回后,弹出返回地址,回到源位置继续执行
5.数组指针操作
Main中有argv指针数组,argv[0]指向输入程序路径和名称,argv[1],argv[2]则代表两个字符串。
3.4 本章小结
本章介绍了整个编译环节,详细解释了汇编语言得含义,分别描述了其中如数据,操作,条件转移,控制,函数调用,栈得调用等诸多数据与操作,详细展示了汇编代码得转化过程。
(以下格式自行编排,编辑时删除)
(第3章2分)
第4章 汇编
4.1 汇编的概念与作用
汇编程序是在汇编器将汇编语言转化为机器可以直接理解得机器语言,将指令整合成可移植得目标程序格式,其结果存储在.o文件中,以二进制形式储存,机器可以直接理解,同时其中也包含了程序得指令编码
汇编实际上就主要用于使文件从汇编语言文件转化为可重定位文件(以二进制形式存储)
4.2 在Ubuntu下汇编的命令
As hello.s -o hello.o gcc -c hello.s -o hello.o
同前述 -c指定了汇编,as则是直接指定了使用汇编器as
4.3 可重定位目标elf格式
使用命令 readelf -a hello.o > ./elf.txt转化为elf格式,主要由四部分组成,头部(Header)、程序头部表(Program Header Table)、节头部表(Section Header Table)以及各种节(Section)。
- ELF文件头,ELF头主要记录文件整体结构,以一个16字节序列开始,主要用于描述生成文件得系统字大小和字节顺序,剩余部分则主要包含帮助连接器语法分析和解释目标文件得信息。主要包括ELF头得大小,目标文件类型,机器类型,还有节头部表得文件偏移,以及其中条目得大小和数量。
ELF头文件部分
- 节头部表
主要负责描述节得位置和大小,其中目标文件中每节都有一个固定大小条目,
节头部表和ELF头中间所夹部分都是节
上述为节头部表得主要内容
- 重定位节
重定位节主要包括了rel.text,rel.data等节,主要存储文件的重定位信息,rel.text存储了一个text节中位置的列表,当链接器连接时,需要把这些位置重新修改,调用外部函数或引用全局变量的指令都需要进行修改,rel.data则主要包含了被模块引用或定义的所有全局变量的重定位信息。主要表述各个段引用的外部符号,在连接时需要对这些位置的地址进行重定位修改。
- 符号表
存放在程序中定义和引用的函数和全局变量的信息
4 Hello.o的结果解析
使用命令
objdump -d -r hello.o >hello_o_disass.s进行反汇编
注意在过程中,反汇编不关注具体的代码源文件,只根据.o文件的字节序列进行反汇编得到结果
对比先前汇编得到.s文件发现,由于从.o文件反汇编而来,左边多了机器码
操作数在.s文件中是十进制,而反汇编则转变为了十六进制格式,带有0x
对于跳转指令call,.s文件直接指明跳转函数名,而在反汇编文件中则加上了偏移地址,这是因为在链接时才确认了确定的地址,这个过程在重定位完成
4.5 本章小结
本章主要描述了在经过预处理和编译后,进一步执行汇编的过程,介绍了汇编的具体信息以及过程,描述了其所得到文件的性质组成,还进一步描述了基于.o文件的反汇编,对二者进行了区分,体现汇编一步对代码产生的影响。
(第4章1分)
第5章 链接
5.1 链接的概念与作用
链接是将各种不同文件的代码和数据部分组合成一个单一文件的过程,可以执行于加载时,也可以执行在运行时,链接由链接器自动执行
使分离编译成为可能,可以将他分解为更小的模块,更便于管里。
注意:这儿的链接是指从 hello.o 到hello生成过程。
5.2 在Ubuntu下链接的命令
使用命令:ld -o hello111 -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
通过上述代码,既可以将其转化为一个可执行文件,链接已经完成。
使用ld的链接命令,应截图,展示汇编过程! 注意不只连接hello.o文件
5.3 可执行目标文件hello的格式
使用命令readeld -a hello111 >elf_hello.txt,使用这种方法既可以对其进行查看
5.3.1 ELF文件头
TYPe发生了变化,节头部表数量也发生了变化
- 节头部表
对其中所用信息进行了声明,如大小,起始地址,对齐方式等。
3.程序头部表
- 符号表
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。
5.4 hello的虚拟地址空间
在虚拟机条件下安装配置edb 然后在终端输入edb运行edb
在edb中运行可执行文件
观察虚拟空间区域,发现起始地址为0x401000,这就是程序的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
观察上述的节头部表,由于节头部表描述了对应节的起始位置以及大小,如果能和在edb中得到的虚拟地址空间对应,则证明我们的分析正确。
利用上述代码实现反汇编,并指定得到一个反汇编文件
为了确定重定位过程的作用以及影响,我们在这里可以先对已经经历过链接过程的可执行文件进行反汇编,再与.o文件反汇编得到的文件进行比对,观察是否有什么区别,从而确定重定位过程的影响
观察分析其不同
观察发现,出现了很多先前没有的函数,这是因为,链接了库函数,现在为他们也在虚拟空间中分配了地址
在已连接完成程序中,直接使用确定的内存地址,而未连接的只是使用偏移地址,这里的区别在于,只有当链接完成后才能确定在虚拟地址空间中的确定位置。
则可以推断重定位的过程大致为
- 首先将所有相同类型的节合并为同一类型的新聚合节,比如所有.data节被合并为一个大.data节,然后连接器将内存地址赋给新的聚合节,赋给输入定义的每个节,以及赋给输入模块定义的每个符号,程序中的指令和全局变量就有了确定的地址了
- 重定位节中的符号引用。连接器修改代码节和数据节中对每个符号的引用,使其指向正确的运行时地址,其依赖于可重定位模块中称为重定位条目的书局结构
Objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
子程序名 地址
_init 0x401000
_ start 0x4014d0
_libc_csu_init 0x401190
_init 0x401000
main 0x401105
puts@plt 0x401080
exit@plt 0x4010b0
_fini 0x401208
使用gdb/edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程(主要函数)。请列出其调用与跳转的各个子程序名或程序地址。
5.7 Hello的动态链接分析
Got函数在动态连接中会被修改,我们首先发现got函数定位在0x404000,edb运行前观测datadump该处值,然后运行程序,发现出现了改变,证明发生了动态链接。
分析hello程序的动态链接项目,通过edb/gdb调试,分析在动态链接前后,这些项目的内容变化。要截图标识说明。
5.8 本章小结
详细论述了链接的过程作用,以及其反汇编文件还进一步介绍了动态链接的内容。
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
经典定义是一个执行中程序的实例,系统中每个程序都运行在特定进程的上下文中。上下文由程序正确运行所需的状态组成,包括存放在内存中的程序的代码和数据,还有他的栈,程序计数器,环境变量以及打开文件描述符的集合。
进程运行时就提供了一个假象,好像我们的程序独占的使用内存和处理器,处理器好像无间断都使用处理器,而内存中只有这一个进程存储。
通过进程概念的确立,我们可以更好的实现任务的并发,提高效率,还可以通过进程的抽象,实现对资源的共享,让多个进程利用同一块空间,并且每个进程具有独立空间地址,便于保护
(以下格式自行编排,编辑时删除)
6.2 简述壳Shell-bash的作用与处理流程
Shell本身是一个命令行解释器,它可以解释用户输入的命令,并将其传递到内核,便于用户和系统进行交互、
- shell首先调用parseline函数,此函数将解析以空格分隔的命令行参数,并通过对命令行的解析,构建出argv向量传递给execve函数,便于之后利用execve函数加载并运行对应程序
- 解析命令行之后,调用另一个函数,检查第一个命令行参数是不是内置shell命令,判断后,如果是,返回1,立即执行内置shell命令,如果不是,则这个命令将会被解读为请求在子进程中执行的程序,返回0.
- 如果判断是要执行的程序,shell调用fork函数创建一个子进程,并利用execve函数加载并执行程序。
- 同时,如果结尾是“&”则应该在后台执行,否则将在前台执行,shell将等待其终止并回收。
(以下格式自行编排,编辑时删除)
6.3 Hello的fork进程创建过程
在shell命令行输入./hello命令运行hello程序,由于此命令不是内置命令,则直接调用fork函数,创建一个新的子进程,在fork运行过程中,会将子进程的pid在父进程返回,同时在子进程中返回0,也就是调用了一次,但是返回了两次,这个标识符pid是新的,不同于父进程,分派完pid后,内核中就会分配一个进程控制块,然后操作系统将父进程的整个虚拟地址空间复制到子进程中。
同时在这个过程中,子进程会获得父进程打开的文件的副本,并标记为私有的写时复制,子进程拥有和父进程相同但独立的虚拟地址空间,最主要区别时pid不同。
6.4 Hello的execve过程
执行execve函数加载并运行hello程序时,会将子进程用户空间栈清空,然后将其参数argv,envp压入栈中,压入完成后,控制权转移到将执行的第一条指令处,以第一条指令为入口开始执行,同时,还会把其所需要的共享库也加入到内存中,完成后,还需要重新设置程序计数器。
Execve覆盖了原有的用户空间,但保留有相同的PID,调用execve函数,不会返回,除非没有找到目标文件。
6.5 Hello的进程执行
Hello进程在操作系统中的执行由进程调度器进行时间片调度,并由内核控制实现上下文切换,通过这种方式,系统可以在不同进程间切换,切换时,上下文会由内核保存,当重新运行这个程序,会把保存的上下文重新加载。
在我们的hello.c进程中,当他进行开始,首先输出HELlo与其之前的内容,然后会执行sleep函数进行休眠,这时内核执行一个切换,去执行其他进程,按其参数,2s后,再次发生进程转换,然后重复这个过程
当循环完成,进行getchar函数,执行过程花费时间较长,再次执行进程切换,在等待期间执行其他进程,完成后,上下文再次切换,重新执行hello
6.6 hello的异常与信号处理
分为中断,陷阱,故障,终止
中断为异步,来自I/O设备信号,回到下一条指令
其他为同步 陷阱 有意异常 回到下一条指令
故障潜在可恢复错误 可能返回当前指令
终止不可恢复错误 不会返回
pl
手机号输入15214566200,取余为0,输入0直接结束,无法操作,输入1
- 回车,直接插入空行
- CRTL——z
按下CRTL-z发现被挂起,ps检查发现程序仍然存在,kill输入对应进程号,发现彻底杀死此进程,终止
进程树
- CRTl-c
直接终止没有进程
- 乱按
解读为命令,留在缓冲区
6.7本章小结
论述了进程具体的管理方式,还有信号的机制,进一步利用edb展示了具体的实际过程。
(第6章1分)
第7章 hello的存储管理
7.1 hello的存储器地址空间
主要有逻辑地址,线性地址,虚拟地址,物理地址
其中逻辑地址,主要指由程序产生的与段偏移相关的偏移地址部分,线性地址则代表了逻辑地址经过段机制转化后得到的结果,是描述符和偏移量的组合形式,在页形式时,线性地址将作为输入
虚拟地址 主要指实际对内存的地址请求,是逻辑和线性地址的总和
物理地址,则指实际存在于内存中的地址,主要由页表机制,从虚拟地址转换来。
在程序运行时,指令和数据将首先被加载到逻辑地址空间,再经过进一步分段分页处理后得到线性地址,在转化为虚拟地址访问内存,最后利用页表转化为物理地址,实际执行。
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
7.2 Intel逻辑地址到线性地址的变换-段式管理
逻辑地址主要构成部分有两个1.段标识符2.段内偏移量 内存再段式存储管理中以段为单位分配内存,每个段各自对应一个连续内存区,每个段内的区域要求连续,段间则可以有空隙,这样的设计让对地址的管理更加高效。
上述的两个部分中,段描述符不直接存储再段寄存器中,而是集中存放于GDT或LDT,在段寄存器中存放对他们的索引,将得到的段首地址加上偏移地址既可以得到线性地址
7.3 Hello的线性地址到物理地址的变换-页式管理
从段式的划分,进入到了页的划分,我们的程序首先会将逻辑地址空间和物理内存确定为不同的页面,更加有利于管理。
页式存储管理是一种高效的内存管理办法,每个进程的虚拟空间将划分为若干个相等程度的页,通过页的管理,这些将被划分为多个页面,当页面建立后,则可以将虚拟地址和物理内存对应起来,并建立起相应页表,在虚拟地址中,前一部分是虚拟页号VPN,后一部分则为虚拟页偏移量。页表项则主要描述了虚拟页所映射的信息,也包括了他的权限。
7.4 TLB与四级页表支持下的VA到PA的变换
实现四级页表,先将VA中VPN分成三段,根据TLBT和TLBI,在块表中寻找对应的PPN,若未找到,则触发一个缺页异常,到在内存中的页表内去查找。
VPN可以分成四段,每一段对应继续往下寻找,条目也逐渐减少,直到完成四层寻址,寻找到要找的PPN,和原有的虚拟地址中VPO结合既可以得到PA。
7.5 三级Cache支持下的物理内存访问
由于已经获得了物理地址PA,现在可以对CACHE进行访问,首先根据CACHE的不同特点,拆分为合适的三部分 CT,CI,CO, CT首先在一级CACHE中搜索对应组,若未找到,则继续去下一组找,重复上述步骤,直到找到,命中返回结果
7.6 hello进程fork时的内存映射
Mm_struct :描述一个进程整个虚拟内存空间
VM_area_struct:描述进程虚拟内存空间中的一个区域
具体调用fork函数进行创建时
- 创建当前进程mm_struct,vm_area_struct以及页表的副本
- 将两个进程的每个页面都标记为只读以及私有的写时复制
7.7 hello进程execve时的内存映射
1.删除原有的用户区域
2,创建新的私有区域
3.映射新的共享区域
4,设置程序计数器pc,使其指向入口指令。
7.8 缺页故障与缺页中断处理
当触发一个缺页时,首先要判断他对应的地址是否合法,可能是无效的地址空间,如果是非法的,则返回一个段错误,同时还要查看是否拥有权限,是否有对这个地址进行读写的权限,若有权限,则代表是一个合法的缺页,缺页处理程序会确定牺牲页,并换入新页面更新页表。
7.9动态存储分配管理
重点在于虚拟内存区域堆的维护,分配器会把堆视为大小不同的块,有已分配的,也有空闲的,需要选择合适的内存快进行分配。
策略:
- 记录空闲块,可选隐式空闲链表,显示空闲链表,分离的空闲链表和按块大小排序建立平衡树。
- 放置策略,可以选择首次适配,下一次适配,最佳适配
- 合并策略,可以选择立即合并,延迟合并
7.10本章小结
本章我们主要研究了hello程序在运行过程中,存储器的地址空间,区分并详细介绍了段式与页式管理。还描述了fork和execve函数具体的内存映射实现机制,展示了虚拟地址的组成,以及内存动态分配的过程。
(第7章 2分)
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:文件
几种文件:
- 普通文件:包含任意数据
- 目录:包含一组链接的文件,每个链接将一个文件映射到另一个文件
- 套接字:主要用来跨网络通信
- 字符和块设备
- 命名通道
设备管理:unix io接口
- 打开和关闭文件
- 读取和写入文件
- 改变当前文件的位置
8.2 简述Unix IO接口及其函数
Unix有一种统一的方式去管理输入和输出
在打开文件时,程序会向内核发送一个请求,请求打开访问对应的某个文件(Unix中I/O设备可以看作一个文件代表,及希望访问这个I/O设备),内核将返回一个描述符,用于在后续操作标识这个文件。
改变当前文件的位置,对于每一个打开的文件,内核将维护一个文件位置k,这个文件位置,是从文件开头起始的字节,偏移量。
读写文件,读操作代表把文件的几个字复制到内存,并且将文件位置k加上对应的数字,代表字节偏移增加,如果剩余字符不足够,将会触发EOF。写操作则是从内存复制几个字节到文件,同样从字节偏移处开始。
关闭文件:完成了对文件的访问之后,告知内核关闭该文件,文件打开时创建的数据结构将被释放,一个进程终止时,所有文件都会被关闭释放。
Unix 函数
- open函数:打开文件
打开一个已经存在的文件,,如果不存在,就新创建一个
- close函数:关闭文件
告知内核关闭文件,同上述,清除相关创建的数据结构。
- read函数:读取文件
将文件内容复制到内存,可能出现不足值
- write函数:写入文件
- lseek函数:改变文件位置
可以修改偏移量k
8.3 printf的实现分析
(以下格式自行编排,编辑时删除)
https://www.cnblogs.com/pianist/p/3315801.html
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
首先调用read函数,将缓冲区读入buf,并返回目前缓冲区的长度。注意,当buf长度为0时才会调用read,否则直接将buf最前元素返回
异步异常以及键盘中断的处理:键盘中断处理子程序。
Gatchar等调用read系统函数,由系统调用读取ascll码,直到回车出现。
8.5本章小结
主要介绍了Unix I/O的核心机制,介绍了其函数和对文件的操作,并进一步结合文件操作详细解析了printf和getchar函数的实现。
(第8章1分)
结论
Hello经历过程
1:预处理,插入扩展文本,将.c文件转化为.i文件
2.编译,将.i文件转化为汇编代码文件.s
3.汇编:将.s文件转化为二进制可重定位文件
4.链接:将hello.o与可重定位文件动态链接库链接得到可执行文件
5.运行:在shell中输入命令行解析后运行
6.子进程创建:用fork函数创建子进程
7.程序运行:shell调用execve函数加载并运行程序
8,指令执行,每个进程分配有时间片,自己的时间片内,独享cpu资源
9,内存访问:确立存储的地址空间
10,动态内存申请:printf调用malloc函数向动态内存申请分配
11,信号;一条小消息
12,进程结束,父程序回收子程序,彻底从内存清除其痕迹
感悟;
计算机世界庞大神奇,堪称人类最狂野的设想,源于几代人的冥思苦想,凭借一个个奇妙的灵感,从无到有搭建出了这的运算机器,比拟甚至超出人脑,这首先离不开各位计算机界的祖师爷,是他们的灵感缔造了如今繁荣昌盛的信息时代,但其中似乎并不是不存在问题,观察当今计算机和人脑的区别,似乎二者间还存在很多不同之处,观察人的思维模式,似乎人总是可以同时连续的处理许多事件,具有及其良好的“多核”思维模式,而计算机只能通过“并行化”模拟并行处理,而单纯提高核数也存在着这种并行上不能突破的瓶颈,虽然有深度学习大语言模型等人工智能算法,不断研发更高性能的AI,但似乎对人脑深层机制的模拟并不完全成功,这或许源于当前硬件设计的局限,仍然有不断尝试硬件新设计的必要。
(结论0分,缺失 -1分,根据内容酌情加分)
附件
文件名 作用
hello.i 预处理完成的文件
hello.s 编译完成后的文件
hello.o 汇编后的可重定位文件
hello111 链接后的可执行目标文件
elf.txt ELF格式的hello.o
hello_o_disass.s hello.o反汇编代码
elf_hello.txt hello111ELF格式
hello_disass.s hello111反汇编代码
(附件0分,缺失 -1分)
参考文献
为完成本次大作业你翻阅的书籍与网站等
[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分)