目 录
2.2在Ubuntu下预处理的命令............................................................................. - 5 -
5.3 可执行目标文件hello的格式...................................................................... - 8 -
6.2 简述壳Shell-bash的作用与处理流程..................................................... - 10 -
6.3 Hello的fork进程创建过程..................................................................... - 10 -
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 -
第1章 概述
1.1 Hello简介
根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。
源文件经编译、汇编、链接成为可执行文件,shell读命令行,解析命令,利用fork创建子进程,并在子进程中调用execve在进程的上下文中加载并运行hello程序,至此program到process完成;hello程序终止后,被shell回收,O2O完成。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中:
硬件环境:X64 CPU;2.5Hz;8G RAM;1THDD+128GSSD
软件环境:ubuntu 19.04
开发与调试:codeblocks、visual studio、gcc、vim、gdb
1.3 中间结果
列出你为编写本论文,生成的中间文件的名字,文件的作用等。
hello.i 用于解析预处理
hello.s 用于解析编译结果
hello.o 用于解析编译结果
1.4 本章小结
(第1章0.5分)
第2章 预处理
2.1 预处理的概念与作用
概念:根据以字符#开头的命令,修改原始的c程序
作用:
删除#define并展开宏定义;
处理所有的条件预编译指令;
插入头文件到“#include”处
删除所有的注释;
添加行号和文件名标识,以便编译时编译器产生调试用的行号信息;
保留所有#program编译指令
2.2在Ubuntu下预处理的命令
命令:gcc -E hello.c -o hello.i
2.3 Hello的预处理结果解析
- 注释被删
- 不再有#include,取而代之的是许多extern、typedef、struct、enum、
显然,代码所依赖的库里的函数,被加上了extern放在.i文件中;各种定义被挪到了.i文件中
- 剩下的内容原封不动地出现在末尾
2.4 本章小结
(以下格式自行编排,编辑时删除)
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
注意:这儿的编译是指从 .i 到 .s 即预处理后的文件到生成汇编语言程序
概念:将文本文件hello.i翻译成hello.s
功能:将.i文件进行词法分析,语法分析、语义分析、优化后,生成汇编代码文件。
3.2 在Ubuntu下编译的命令
gcc -S hello.i -o hello.s
3.3 Hello的编译结果解析
-
-
- 全局变量sleepsecs,被注明放在.text:
- 常量字符串:被注明放在.rodata里,中文已经被编码
- 函数调用:这里的调用,调用的都是动态链接共享库的函数,方式为将要传递的变量,放在寄存器里,然后call函数。
-
-
-
- 关系操作符:!=,使用je来达到目的,逻辑是,若等于,跳转到等于的那一分支,否则,顺序执行,即执行不等于的那一分支
-
-
-
- 关系操作符:<;源文件中的<10以cmp,若<=9,则跳转
-
-
-
- 控制转移 if 见3.1.4
- 控制转移for
-
通过跳转实现;
.L2到.L4处的内容是为i赋初值、
.L4到.L3处的内容是循环体、
.L3之后几行是循环条件判断
-
-
- 赋值 mov指令
- 算数操作++ add指令
- return 用到了rbp,以leave 和 ret指令返回调用函数
-
3.4 本章小结
(以下格式自行编排,编辑时删除)
(第3章2分)
第4章 汇编
4.1 汇编的概念与作用
将.s翻译成机器语言指令并将这些指令打包成一个叫做可重定位目标程序,将结果保存在.o文件中。
4.2 在Ubuntu下汇编的命令
gcc -c hello.s -o hello.o
4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
4.4 Hello.o的结果解析
(以下格式自行编排,编辑时删除)
objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等。
4.5 本章小结
(以下格式自行编排,编辑时删除)
(第4章1分)
第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的格式
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。
5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
5.5 链接的重定位过程分析
(以下格式自行编排,编辑时删除)
objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
5.6 hello的执行流程
(以下格式自行编排,编辑时删除)
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。
5.7 Hello的动态链接分析
(以下格式自行编排,编辑时删除)
分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变化。要截图标识说明。
5.8 本章小结
(以下格式自行编排,编辑时删除)
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
具有独立功能的一个程序关于某个数据集合的一次运行活动,因而进程具有动态的含义。
6.2 简述壳Shell-bash的作用与处理流程
作用:代表用户运行其他程序
处理流程:
1. 读取用户命令行,对命令行进行分析
2. 判断要执行的是否是内置函数,若为内置函数,shell 直接运行,若非内置
函数需要调用 fork、execve 为其分配空间
3. 若进程是前台进程,shell 会显式等待进程执行完毕
6.3 Hello的fork进程创建过程
- 创建当前进程的mm_struct,vm_area_struct和页表的原样副本
- 两个进程的每个页面都标记为只读
- 两个进程中的每个区域结构(vm_area_struct)都标记为私有的写时复制(COW)
6.4 Hello的execve过程
- 删除已存在的用户区域
- 创建新的区域结构:代码和初始化数据映射到.text和.data区;.bss和栈映射到匿名文件
- 设置PC,指向代码区域的入口点:linux根据需要换入代码和数据页面
6.5 Hello的进程执行
hello执行过程中,是与其他进程一起轮流使用处理器的,在某些时刻,如定时器中断,内核认为hello已经运行了足够长的时间,就会调度一个新的进程,hello进程就被抢占,此时,hello进程的上下文,包括目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构(页表、进程表、文件表)就会被保存,然后在某个时刻,内核再次调度hello进程,hello的上下文就会被恢复,控制再次被传递给hello进程,故而,hello的执行可能被分成几个时间段,而每一个时间段,都是一个时间片;
当hello要发起IO操作,需要系统调用,引发一个陷阱,进入内核模式,在陷阱处理程序后完成后,返回并执行下一条指令,当要用户的输入需要等待时,hello被抢占,当输入结束后,会有中断信号,hello被调度,hello进行sleep系统调用时,同上。
6.6 hello的异常与信号处理
异步异常:
中断:
时钟中断——上下文切换
同步异常:
陷阱:
系统调用——陷入内核状态
故障:
缺页故障——调用缺页处理程序
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
6.7本章小结
(以下格式自行编排,编辑时删除)
(第6章1分)
第7章 hello的存储管理
7.1 hello的存储器地址空间
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
逻辑地址:段中的偏移地址
线性地址:逻辑地址加上基地址
虚拟地址:需要通过页表找到对应的物理页,利用PPN和VPO计算出物理地址,由于每个进程都有独立的虚拟地址空间,虚拟地址和物理地址,可以是多对一、一对多的关系。
物理地址:计算机系统的内存被组织成M个连续字节大小的单元组成的数组,每个字节有一个唯一的地址,就是物理地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
(以下格式自行编排,编辑时删除)
7.3 Hello的线性地址到物理地址的变换-页式管理
(以下格式自行编排,编辑时删除)
7.4 TLB与四级页表支持下的VA到PA的变换
虚拟地址将被视为VPN1、VPN2、VPN3、VPN4、VPO
首先根据VPN1查找页全局目录里的PTE,此目录中的PTE指向一个二级页表,再根据VPN2在这个二级页表里查找指向三级页表的PTE,一样的方法找到指向四级页表的PTE,最后来到内存PPN的页表,根据得到的PPN和VPO得到PA。
7.5 三级Cache支持下的物理内存访问
物理地址依据cache结构被视为CT、CI、CO,若发生不命中,会从下一级存储器中查找放入,直到在内存中查找。如果发生不命中,在下级存储器中找到了就会放入cache,如果发生冲突,会驱逐一个块再放入。
7.6 hello进程fork时的内存映射
7.7 hello进程execve时的内存映射
7.8 缺页故障与缺页中断处理
缺页故障:引用某个VPN的时候发现它的有效位为0,页面出错
缺页中断处理:缺页处理程序选择一个牺牲页,从磁盘复制VPN到内存中,更新PTE,然后返回,重启导致却也的指令
7.9动态存储分配管理
7.10本章小结
(以下格式自行编排,编辑时删除)
(第7章 2分)
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:所有的I/O设备都被模型化为文件,I/O操作可看作对响应文件的读或写
设备管理:通过应用接口unix io,
打开文件。一个应用程序通过要求内核打开相应的文件,来宣告它想要访问一个I/O设备。内核返回一个小的非负整数,叫做描述符,它在后续对此文件的所有操作中标识这个文件。内核记录有关这个打开文件的所有信息。应用程序只需记住这个描述符。
Linux shell创建的每个进程开始时都有三个打开的文件:标准输入(描述符为0)、标准输出(描述符为1)和标准错误(描述符为2)。头文件<unistd.h>定义了常量STDINFILENO、STDOUT FILENO 和STDERR FILENO,它们可用来代替显式的描述符值。
改变当前的文件位置。对于每个打开的文件,内核保持着一个文件位置k,初始为0。这个文件位置是从文件开头起始的字节偏移量。应用程序能够通过执行seek操作,显式地设置文件的当前位置为k。
读写文件。一个读操作就是从文件复制n>0个字节到内存,从当前文件位置k开始,然后将k增加到k十n。给定一个大小为m字节的文件,当k≥m时执行读操作会触发一个称为end-of-file(EOF)的条件,应用程序能检测到这个条件。在文件结尾处并没有明确的“EOF符号”。
类似地,写操作就是从内存复制n>0个字节到一个文件,从当前文件位置k开始,然后更新k。
关闭文件。当应用完成了对文件的访问之后,它就通知内核关闭这个文件。作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。无论一个进程因为何种原因终止时,内核都会关闭所有打开的文件并释放它们的内存资源。
8.2 简述Unix IO接口及其函数
打开和关闭文件:open(),close()
读写文件read(),write()
改变当前的文件位置lseek()
8.3 printf的实现分析
(以下格式自行编排,编辑时删除)
https://www.cnblogs.com/pianist/p/3315801.html
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
(以下格式自行编排,编辑时删除)
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
(以下格式自行编排,编辑时删除)
(第8章1分)
结论
hello经历了预处理、编译、汇编、链接、被映射到内存、被加载到内存、分配空间、进行系统调用、结束、被回收。
附件
hello.i 用于解析预处理
hello.s 用于解析编译结果
hello.o 用于解析编译结果
参考文献
为完成本次大作业你翻阅的书籍与网站等
[1] 深入理解系算计系统.机械工业出版社
[2] www.csdn.net
(参考文献0分,确实 -1分)