计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算机
学 号
班 级
学 生
指 导 教 师
计算机科学与技术学院
2019年12月
本文主要介绍了hello.c从编写到执行的全过程,其中有预处理、编译、汇编、链接以及hello进程创建直到回收的全部过程,通过这些过程介绍了程序的实现和生命周期。
关键词:计算机系统;进程;P2P;020;
(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)
目 录
6.2 简述壳Shell-bash的作用与处理流程 - 10 -
7.2 Intel逻辑地址到线性地址的变换-段式管理 - 11 -
7.3 Hello的线性地址到物理地址的变换-页式管理 - 11 -
7.4 TLB与四级页表支持下的VA到PA的变换 - 11 -
7.7 hello进程execve时的内存映射 - 11 -
第1章 概述
1.1 Hello简介
根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。
Hello的P2P:hello.c进行预处理、编译、汇编、链接等过程生成可执行目标文件hello
Hello的O2O:在shell中,通过./hello运行程序,先进行fork进程,然后进行execve进程,CPU将程序映射mmp,分配时间片执行逻辑控制流。在运行时CPU在MMU上将虚拟地址转为物理地址,TLB以及多级页表加速访问,三级cache结构加快CPU访问物理内存数据。系统的IO和信号使程序能在键盘、主板、显卡、屏幕处理运行结束或者被信号终止时,hello进程结束。Shell父进程回收子进程。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件和软件环境:
处理器 IntelCore i7-8750H CPU @2.20GHz 2.21GHz
RAM 8.00GB
Windows10 64位操作系统
开发与调试工具:
VMWARE 14;Ubuntu 18.04
EDB;GDB;VSCODE;VIM.Objdump
readelf
1.3 中间结果
hello.i Hello.c的预处理文件
Hello.s 编译器编译hello.i产生的编译文件
Hello.o 汇编器汇编Hello.s产生的可重定向汇编文件
Hello 链接器链接Hello.o产生的可执行文件
Hello.od 反汇编hello.o产生的文件,查看汇编代码
Hello.d Hello的反汇编文件,查看链接器的链接
Hello.oelf Hello.o的ELF文件,用来查看其各节信息
Hello.elf Hello的ELF文件,用来查看其各节信息
1.4 本章小结
介绍了hello 的p2p o2o流程 以及简要的中间过程和相关工具
(第1章0.5分)
第2章 预处理
2.1 预处理的概念与作用
预处理一般是指在程序源代码被翻译为目标代码的过程中,生成二进制代码之前的过程。典型地,由预处理器(preprocessor) 对程序源代码文本进行处理,得到的结果再由编译器核心进一步编译。
作用:修改补充源代码。
2.2在Ubuntu下预处理的命令
2.3 Hello的预处理结果解析
hello.chan有三个头文件,预处理器寻找到这三个头文件的定义,并将其中的内容全部加载到hello.i文件当中
2.4 本章小结
预处理器将源代码引用的文件中用预处理指令,引入到源代码文件中,形成了hello.i预处理文件
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
编译是编译器将预处理文本翻译为汇编文本的过程
作用1.扫描(词法分析),2.语法分析,3.语义分析,4.源代码优化(中间语言生成),5.代码生成,目标代码优化。
3.2 在Ubuntu下编译的命令
3.3 Hello的编译结果解析
3.3.1数据
int sleepsecs;
整型全局变量 为对齐方式是4类型是object,大小是4字节
int argc main()整型参数存在%edi
argv[] 字符串
int i; 整型局部变量
3.3.2赋值
sleepsecs赋值2 在.rodata节
i赋值0 movl $0, %eax
3.3.3类型转换
整型型的sleepsecs赋值2.5被直接隐式的赋值2 .long 2
3.3.4算术操作
i++ addl $1, -4(%rbp)
3.3.5 关系操作
i<10 cmpl $9, -4(%rbp)
argc!=3 cmpl $3, -20(%rbp)
3.3.6数组操作
char *argv[]
地址
argv[0]movq -32(%rbp), %rax
argv[1]addq $8, %rax
argv[2]addq $16, %rax
3.3.8函数操作
main函数:
参数传递:传入参数argc (%rdi)和argv (%rsi),
函数调用:被系统启动函数调用。
函数返回:设置%eax为0并返回。
2.printf函数:
参数传递:call、puts传入字符串首地址;for循环中call、printf时传入了
argv[1]和argc[2]的地址。
函数调用:在for循环被调用。
3.exit函数:
参数传递:传入的参数为1,则退出。
函数调用:if判断条件满足后被调用。
- sleep函数:
参数传递:传入参数sleepsecs,传递控制call sleep
函数调用:for循环下被调用
5.getchar
传递控制:call getchar。
函数调用:在main中被调用。
3.4 本章小结
本章hello.i 转为hello.s从c转为汇编语言,并详细解读了汇编代码理解了c是如何翻译为汇编的。
(第3章2分)
第4章 汇编
4.1 汇编的概念与作用
把汇编语言翻译成机器语言的过程称为汇编
作用 汇编语言翻译成机器语言,形成可执行的机器指令
4.2 在Ubuntu下汇编的命令
4.3 可重定位目标elf格式
1.ELF头描述了生成该文件的系统的字的大小和字节顺序,并且包含帮助链接器语法分析和解释目标文件的信息。
2.节头部表描述了不同节的位置和大小,其中目标文件中每个节都有一个固定大小的条目。具体的描述包括节的名称、类型、地址和偏移量等。
- 重定位条目告诉链接器在将目标文件合并成可执行目标文件时如何修改这个引用。代码的重定位条目放在.rel.text中,已初始化数据的重定位条目放在.rel.data中。
- 符号表存放在程序中定义和引用的函数和全局变量的信息
4.4 Hello.o的结果解析
- 反汇编和hello.s对比
- 反汇编为十六进制。
- 分支转移:反汇编中jmp后面跟的是地址,而hello.s是段标签。
- 函数调用:.s文件中call指令后面跟的是函数名的符号,而反汇编得到的代码中call的后面是一个待重定位的相对地址,
- 全局变量的访问:在hello.s文件中,等全局变量的访问,有具体地址而在反汇编代码中没有,因为它地址是在运行时确定的
4.5 本章小结
本章分析了hello.o的elf格式,对比了反汇编和.s文件,了解了汇编语言到机器语言实现地转变。
(第4章1分)
第5章 链接
5.1 链接的概念与作用
链接是将各种代码和数据片段收集并组合成一个单一文件的过程,这个文件可被加载(复制)到内存并执行
作用:链接器使得分编译(separate com pilation)成为可能。我们不用将一个大型的应用程序组织为一个巨大的源文件,而是可以把它分解为更小、更好管理的模块,可以独立地修改和编译这些模块。当我们改变这些模块中的一个时,只需简单地重新编译它,并重新链接应用,而不必重新编译其他文件。
5.2 在Ubuntu下链接的命令
使用ld的链接命令,应截图,展示汇编过程! 注意不只连接hello.o文件
5.3 可执行目标文件hello的格式
节头(Section Headers)给出Hello程序中各节的信息,包括该节的大小(Size),地址和该节在程序代码中的偏移量等。
5.4 hello的虚拟地址空间
edb中打开hello,通过Data Dump查看hello程序的虚拟地址空间各段信息
.init
.plt
.text
5.5 链接的重定位过程分析
1.hello中加入了共享库的函数,如puts、getchar、printf等和.init和.plt节。
2.hello.o中相对偏移地址,和重定位条目,而hello中是已经重定位后的虚拟内存地址
连接过程:链接器ld将各个重定位目标文件.o按照链接规则组装在一起生成可执行文件。
重定位过程:1.重定位节和符号定义。在这一步中,链接器将合并所有相同类型的节。然后,连接器将运行时内存地址赋给合并后的节和符号2.重定位节中的符号引用。修改代码节和数据节中对每个符号的引用,使得它们指向正确运行时的地址。
5.6 hello的执行流程
0x400430 init;
0x400460 puts@plt;
0x400470 printf@plt;
0x400480 __libc_start_main@plt;
0x400490 getchar@plt;
0x4004a0 exit@plt;
0x4004b0 sleep@plt;
0x4004d0 _start;
0x4004fa main;
0x400580 __libc_csu_init;
0x4005f0 __libc_csu_fini;
0x4005f4 _fini;
5.7 Hello的动态链接分析
在执行函数dl_init的前后,地址0x600ff0中的值由发生了变化
.got是地址0x600ff0而got是一个全局函数表。这个表中的信息是动态的链接进来的真实的地址信息会在程序执行的过程中用动态链接的方式加入到程序中。
5.8 本章小结
本章介绍了链接的概念与作用比较了hello与hello.o反汇编,分析了hello的动态链接,从hello.o到hello的通过链接和重定位生成可执行文件
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
进程是一个执行中程序的示例
作用:提供给应用进程两个关键抽象1.一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占地使用处理器。2.一个私有的地址空间,它提供一个假象,好像我们程序在独占整个内存系统。
6.2 简述壳Shell-bash的作用与处理流程
Shell是用户和Linux内核之间的接口程序,用户输入的命令通过shell解释,然后传给Linux内核,然后将内核的处理结果翻译给用户。
流程如下:
用户在命令行中键入命令;
Shell通过parseline builtin函数将命令字符串分割填充到参数数组,传个main;
Shell判断是否是内置命令,若是,立即执行;
若非内置则调用相应程序(execve和fork)为其分配子进程;
Shell可以接受信号,并且做出相应处理。
6.3 Hello的fork进程创建过程
执行文件hello父进程会通过fork函数创建一个新的运行的子进程Hello。Hello进程得到与父进程相同的代码、数据段、堆、共享库以及用户栈这些信息,父进程调用fork时,Hello进程可以读写父进程中打开的任何文件。在父进程中,fork返回Hello进程的PID,在Hello进程中,fork返回0
6.4 Hello的execve过程
使用execve在当前进程中加载并运行一个新程序Hello。而execve直接在当前的进程中删除当前进程中现有的虚拟内存段,并穿件一组新的代码、数据、堆和用户栈的段。将覆盖当前进程的代码、数据和堆栈,但保留PID并继承打开的文件描述符和信号上下文
6.5 Hello的进程执行
shell通过加载器加载可执行目标文件hello,操作系统进行上下文切换,切换到hello的进程中,内核调度hello后,它就抢占当前进程并使用上下文切换转移控制到hello进程。接下来hello调用sleep函数,进入内核态,程序陷入休眠状态,内核调度其他进程,而sleep函数结束后,hello进程重新进入待执行进程队列中等待内核调度。
6.6 hello的异常与信号处理
在程序运行过程中,键入Ctrl-C,使当前进程中断
输入回车会被忽略
乱按无反应
在程序运行过程中输入Ctrl-Z,将当前进程挂起
ps查看进程及其运行时间
jobs查看当前暂停的进程
fg使进程在前台执行
kill杀死特定进程
Ctrl z
Jobs
Pstree
Fg
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
6.7本章小结
阐述了进程的概念与作用,以及shell的执行流程,进程产生信号和信号的处理。
第7章 hello的存储管理
7.1 hello的存储器地址空间
逻辑地址:又称相对地址,是程序运行由CPU产生的与段相关的偏移地址部分。由一个段标识符加上一个指定段内相对地址的偏移量。
线性地址:逻辑地址到物理地址变换之间的中间层,线性地址是分页机制之前的地址。在分段部件中逻辑地址是段中的偏移地址,然后加上基地址就是线性地址。
虚拟地址是保护模式下,这样程序访问存储器所使用的逻辑地址称为虚拟地址
物理地址:加载到内存地址寄存器中的地址,内存单元的真正地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
一个逻辑地址由两部分组成,段标识符和段内偏移量。段标识符是由一个16位长的字段组成,称为段选择符。其中前13位是一个索引号。后面3位包含一些硬件细节。可以通过段标识符的前13位,直接在段描述符表中找到一个具体的段描述符,这个描述符就描述了一个段。一些全局的段描述符,就放在“全局段描述符表(GDT)”中,一些局部的,例如每个进程自己的,就放在所谓的“局部段描述符表(LDT)”中。
具体的转换步骤如下:
给定一个完整的逻辑地址[段选择符:段内偏移地址。
看段选择符的T1=0还是1,知道当前要转换是GDT中的段,还是LDT中的段,再根据相应寄存器,得到其地址和大小。可以得到一个数组。
取出段选择符中前13位,在数组中查找到对应的段描述符,得到Base,也就是基地址。
线性地址 = Base + offset。
7.3 性地址到物理地址的变换-页式管理
Hello的线概念上而言,虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每字节都有一个唯一的虚拟地址,作为到数组的索引。磁盘上数组的内容被缓存在主存中。和存储器层次结构中其他缓存一样,磁盘(较低层)上的数据被分割成块, 这些块作为磁盘和主存(较高层)之间的传输单元。VM系统通过将虚拟内存分割为称为虚拟页(Virtual Page,VP)的大小固定的块来处理这个问题。每个虚拟页的大小为P一2r字节。类似地,物理内存被分割为物理页(Physical Page, PP),大小也为P字节(物理页也被称为页帧。
在任意时刻,虚拟页面的集合都分为三个不相交的子集:
未分配的:VM 系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相
关联,因此也就不占用任何磁盘空间。
缓存的:当前已缓存在物理内存中的已分配页。
未缓存的:未缓存在物理内存中的已分配页。
7.4 TLB与四级页表支持下的VA到PA的变换
7.5 三级Cache支持下的物理内存访问
在三级cache下,将物理地址分成CT(标记)+CI(索引)+CO(偏移量),首先在一级cache下找,若发生不命中miss则到下一级缓存即二级cache下找,若不命中则到三级cache下访问。
7.6 hello进程fork时的内存映射
- 创建当前进程的mm_struct,vm_area_struct和页表的原样副本。
- 两个进程的每个页面都标记为只读页面。
- 两个进程的每个vm_area_struct都标记为私有,这样就只能在写入时复制
7.7 hello进程execve时的内存映射
1.删除当前进程虚拟地址的用户部分中的已存在的区域结构。
2.创建新的区域结构,这些新的区域都是私有的、写时复制的,代码和初始化数据映射到.text和.data区,.bss和栈堆映射到匿名文件。
3.映射共享区域。如果a.out程序与共享对象链接,那么这些对象都是动态链接到这个程序的,再映射到用户虚拟地址空间中的共享区域内。
4.设置程序计数器(PC)。设置当前进程上下文中的程序计数器,使之指向代码区域的入口点。
7.8 缺页故障与缺页中断处理
当出现缺页故障时,此时调用缺页处理程序,内存会确定一个牺牲页,若页面被修改,则换出到磁盘,再将新的目标页替换牺牲页写入,缺页处理程序返回到原来的进程,重启导致缺页的指令
7.9动态存储分配管理
动态内存分配器维护看一个进程的虚拟内存区域,称为堆(heap)。假设堆是一个请求二进制零的区域,它紧接在未初始化的数据区域后开始,并向上生长(向更高的地址)。对于每个进程,内核维护着一个变量brk(读做“break”),它指向堆的顶部。
分配器将堆视为一组不同大小的块(block)的集合来维护。每个块就是一个连续的虚拟内存片(chunk), 要么是已分配的,要么是空闲的。已分配的块显式地
保留为供应用程序使用。空闲块可用来分配。空闲块保持空闲,直到它显式地被应用所分配。一个已分配的块保持已分配状态,直到它被释放,这种释放要么是应用程序显式执行的,要么是内存分配器自身隐式执行的。
显式分配器:要求应用显式地释放任何已分配的块。例如C程序通过调用malloc函数来分配一个块,通过调用free函数来释放一个块。
隐式分配器:也叫做垃圾收集器,例如,诸如Lisp、ML、以及Java之类的高级语言就依赖垃圾收集来释放已分配的块。
放置策略:
首次适配:从头搜索,遇到第一个合适的块就停止;
下次适配:从头搜索,遇到下一个合适的块停止;
最佳适配:全部搜索,选择合适的块停止。
7.10本章小结
本章介绍了储存器的虚拟地址、物理地址、线性地址、逻辑地址进程fork和execve时的内存映射,缺页故障与缺页中断处理以及动态内存分配。
(第7章 2分)
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
设备的模型化:文件
设备管理:unix io接口
所有的I/ O 设备(例如网络、磁盘和终端)都被模型化为文件,而所有的输入和输出都被当作对相应文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix
I/O。
8.2 简述Unix IO接口及其函数
Unix I/O接口:
1.打开文件:一个应用程序通过要求内核打开相应的文件,来宣告它想要访问一个I/O设备,内核返回一个小的非负整数,叫做描述符,它在后续对此文件的所有操作中标识这个文件,内核记录有关这个打开文件的所有信息。应用程序只需要记住这个描述符。
2.Linux Shell创建的每个进程都有三个打开的文件:标准输入(描述符为0),标准输出(描述符为1)和标准错误(描述符为2)。头文件<unistd.h>定义了常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,它们可以用来代替显式的描述符值。
3.改变当前的文件位置:对于每个打开的文件,内核保持着一个文件位置 k,初始为0。这个文件位置是从文件开头起始的字节偏移量,应用程序能够通过执行seek操作,显式地将改变当前文件位置为k。
4.读写文件:一个读操作就是从文件复制n>0个字节到内存,从当前文件位置k开始,然后将k增加到 k+n。给定一个大小为m字节的文件,当k>=m时执行读写操作会触发一个称为end-of-file(EOF)的条件,应用程序能检测到这个条件。类似地,写操作就是从内存中复制n>0个字节到一个文件,从当前文件位置k开始,然后更新k。
5.关闭文件:当应用完成了对文件的访问之后,它就会通知内核关闭这个文件。作为相应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中去。无论一个进程因何种原因终止时,内核都会关闭所有打开的文件并释放它们的内存资源。
open()
功能:用于打开或创建文件
参数:
pathname:被打开的文件名
flags:文件打开方式,
返回值:
成功:返回文件描述符;
失败:返回-1
close()
功能描述:用于关闭一个被打开的的文件
参数:fd文件描述符
函数返回值:
0成功,
-1出错
read()
功能描述: 从文件读取数据。
参数:
fd:将要读取数据的文件描述词。
buf:指缓冲区,即读取的数据会被放到这个缓冲区中去。
count: 表示调用一次read操作,应该读多少数量的字符。
返回值:
返回所读取的字节数;
0(读到EOF);-1(出错)。
write()
功能描述: 向文件写入数据。
返回值:
写入文件的字节数(成功);
-1(出错)
lseek()
功能描述: 用于在指定的文件描述符中将将文件指针定位到相应位置。
参数:
fd;文件描述符。
offset:偏移量,每一个读写操作所需要移动的距离,
返回值:
成功:返回当前位移;
失败:返回-1
8.3 printf的实现分析
int printf(const char *fmt, ...)
{
int i;
char buf[256];
va_list arg = (va_list)((char*)(&fmt) + 4);
i = vsprintf(buf, fmt, arg);
write(buf, i);
return i;
}
代码位置:D:/~/funny/kernel/printf.c
从vsprintf生成显示信息,显示信息传送到write系统函数,write函数再陷阱-系统调用 int 0x80或syscall.字符显示驱动子程序。从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
本章介绍了I/O接口和函数 和IO 设备管理方法,分析了printf函数和getchar 函数
(第8章1分)
结论
1.hello被IO设备编写,存为.c文件。
2.hello.c预处理为hello.i文件
3.hello.i被编译为hello.s文件
4.hello.s汇编成hello.o文件
5.链接器将hello.o和外部文件链接成可执行文件hello
6.shell下,fork,execve得到进程hello
7.shell接受键盘的信号做出不同的处理,
8.shell父进程回收hello子进程,内核删除为hello创建的所有数据结构
感悟;hello只有短短几行代码,运行只要数秒钟,但是他背后是非常复杂的计算机部件和程序的共同协作,完成了将几行代码转换为指令控制机器实现的壮举,让我感受到了计算机的严密逻辑性,使我更加了解计算机。
(结论0分,缺失 -1分,根据内容酌情加分)
附件
hello.c源代码
hello.i预处理文件
hello.s汇编文件
hello.o可重定位目标执行
hello可执行目标文件
(附件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分)