ToB企服应用市场:ToB评测及商务社交产业平台
标题: 程序人生-Hello’s P2P [打印本页]
作者: 去皮卡多 时间: 2024-11-23 13:44
标题: 程序人生-Hello’s P2P
摘 要
本文通过一个结构简单的hello程序,说明白hello由文本到可执行的文件,再到一个进程的整个过程中,盘算机系统都起到了怎样的作用。在这一过程中,我们会打仗到程序预处置惩罚、编译、汇编、链接等过程,同时也先容了有关进程、存储、I/O等相关的知识,深入系统底层的软硬件结合的部门,对盘算机系统进行了较为系统和广泛的探讨。
关键词:盘算机系统;程序;进程
(择要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)
目 录
第1章 概述
1.1 Hello简介
1.2 情况与工具
1.3 中心结果
1.4 本章小结
第2章 预处置惩罚
2.1 预处置惩罚的概念与作用
2.2在Ubuntu下预处置惩罚的下令
2.3 Hello的预处置惩罚结果解析
2.4 本章小结
第3章 编译
3.1 编译的概念与作用
3.2 在Ubuntu下编译的下令
3.3 Hello的编译结果解析
3.4 本章小结
第4章 汇编
4.1 汇编的概念与作用
4.2 在Ubuntu下汇编的下令
4.3 可重定位目的elf格式
4.4 Hello.o的结果解析
4.5 本章小结
第5章 链接
5.1 链接的概念与作用
5.2 在Ubuntu下链接的下令
5.3 可执行目的文件hello的格式
5.4 hello的虚拟地址空间
5.5 链接的重定位过程分析
5.6 hello的执行流程
5.7 Hello的动态链接分析
5.8 本章小结
第6章 hello进程管理
6.1 进程的概念与作用
6.2 简述壳Shell-bash的作用与处置惩罚流程
6.3 Hello的fork进程创建过程
6.4 Hello的execve过程
6.5 Hello的进程执行
6.6 hello的异常与信号处置惩罚
6.7本章小结
第7章 hello的存储管理
7.1 hello的存储器地址空间
7.2 Intel逻辑地址到线性地址的变换-段式管理
7.3 Hello的线性地址到物理地址的变换-页式管理
7.4 TLB与四级页表支持下的VA到PA的变换
7.5 三级Cache支持下的物理内存访问
7.6 hello进程fork时的内存映射
7.7 hello进程execve时的内存映射
7.8 缺页故障与缺页中断处置惩罚
7.9动态存储分配管理
7.10本章小结
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
8.2 简述Unix IO接口及其函数
8.3 printf的实现分析
8.4 getchar的实现分析
8.5本章小结
结论
附件
参考文献
第1章 概述
1.1 Hello简介
P2P:是指from program to process. 在linux中,对源程序进行预处置惩罚、编译、汇编、链接生成可执行目的文件。
O2O:是指from zero to zero. 程序开始执行后,OS为其映射到虚拟内存,管理hello进程,分配物理内存,然后将其结果输出到表现器,末了回收内存空间。
1.2 情况与工具
1.硬件情况:
X64 CPU;2GHz;2G RAM;256GHD Disk 以上
2.软件情况:
Windows7/10 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位 以上
3.开辟与调试工具:
Codeblocks 64位;gcc; Visual Studio 2010 64位以上;edb
1.3 中心结果
hello.i:C预处置惩罚器产生的一个ASCII码的中心文件,用于分析预处置惩罚过程。
hello.s:C编译器产生的一个ASCII汇编语言文件,用于分析编译的过程。
hello.o:汇编器产生的可重定位目的程序,用于分析汇编的过程。
hello:链接器产生的可执行目的文件,用于分析链接的过程。
obj_hello.o.text:hello.o的反汇编文件,用于分析可重定位目的文件hello.o。
obj_hello.text:hello的反汇编文件,用于分析可执行目的文件hello。
hello_elf.text:hello的ELF格式,用于分析可执行目的文件hello。
1.4 本章小结
本章简述了hello从程序到进程再到运行履历了P2P和020两个过程,从整体上大致先容了hello的一生,并列出了测试情况和工具,以及生成的中心结果名字和作用。
(第1章0.5分)
第2章 预处置惩罚
2.1 预处置惩罚的概念与作用
预处置惩罚阶段,预处置惩罚器(cpp)根据以字符#开头的下令,修改原始的C程序。好比hello.c中第1行的#include < stdio.h>下令告诉预处置惩罚器读取系统头文件stdio.h 的内容,并把它直接插入程序文本中。结果就得到了另一个C程序,通常是以.i作为文件扩展名。
预处置惩罚的作用: 扩展源代码、宏定义、文件包含、条件编译。
2.2在Ubuntu下预处置惩罚的下令
下令:gcc –E hello.c –o hello.i
2.3 Hello的预处置惩罚结果解析
hello.c文件
hello.i文件
分析:由图可知,原来仅三十行左右的代码扩展到了三千多行。此中main函数部门没有发生变革,而头文件部门展开,而宏定义也由其相应的文件取代。
2.4 本章小结
本章主要先容了预处置惩罚的概念和作用,并分析hello.c预处置惩罚的过程——头文件展开和宏定义处置惩罚,以及得到的结果。
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
编译是使用编译程序从预处置惩罚文本文件(.i文件)产生汇编程序(.s文件)的过程。主要包罗一下五个阶段:词法分析、语义检查、中心代码生成、目的代码生成与优化。
注意:这儿的编译是指从 .i 到 .s 即预处置惩罚后的文件到生成汇编语言程序
编译的作用
1.词法分析:将源代码输入扫描器,其字符序列被分割成一系列记号。
2.语法分析:基于词法分析生成的一系列记号,生成语法树。
3.语义分析:由语义分析器完成,指示判断是否正当,并不判断对错。
4.目的代码的生成与优化:目的代码生成阶段编译器会选择合适的寻址方式,左移大概右移代替乘除,删除多条指令。
3.2 在Ubuntu下编译的下令
下令:gcc -S hello.i -o hello.s
3.3 Hello的编译结果解析
hello.s文件
3.3.1文件声明
.file 源文件名
.text代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。
.section 指示把代码分别成若干个段
.rodata 用于维护只读数据
.align 8 地址对齐的伪指令,用来指定符号的对齐方式
.string 字符串的存储位置
.global用来让一个符号对链接器可见,可以供其他链接对象模块使用;告诉编译器后续跟的是一个全局可见的名字
.type 指定是对象类型或是函数类型
3.3.2数据类型
1.字符常量:
字符常量多为字符或字符串。
源程序中有2个字符串常量,均在printf函数中出现,这两个字符串前都被编译器声明白.rodata,即这两个字符串都将存放在只读数据区。
2.整型数
全局变量:未赋初值的在.bss节中,赋初值的在.data中
局部变量:会在汇编语言里用寄存器表示,或存放在堆栈里
hello.s中申请了整型变量i,该变量是一个局部变量.编译器将局部变量存储在寄存器或栈中,在hello.s中编译器将i存储在-4(%rbp)中可以看出i占4个字节
argc 储存在寄存器%edi中,作为参数传入到-20(%rbp)的内存位置
3.3.3赋值操作
hello.s中的赋值操作:i= 0
该语句用movl指令来完成;0以立即数的情势存储,将0送给寄存器eax。赋值完成。
3.3.4算数操作
hello.s中的算数操作:i++;
使用addl指令来完成,addl $1, -4(%rbp)
3.3.5关系操作
1.argc!=4:用cmpl指令对4和存放在-20(%rbp)中的argc进行比较,相等则跳转,否者继续执行。Cmpl指令的功能相称于减法指令,不外不保存结果,只是对标志寄存器产生影响,只必要对标志寄存器进行判断。
2.i<8:用cmpl指令对7和存放在-4(%rbp)中的i进行比较,小于等于则执行循环体
3.3.6控制转移
1.if(avgc!=4) 使用cmp指令比较avgc与4,假如相等则使用je语句直接跳转到L2,假如不相等,则顺序执行。
2.for(i = 0;i<8;i++) 先给在L2给i赋值,然后跳转到L3,L3中进行比较假如满足i<=7则进入循环,否则循环结束,调到循环外的下一条语句。
3.3.7函数操作
1.main函数
功能:主函数
参数:调用了argc 和argv两个参数,%edi存储着argc的值
返回:返回值为0
2.exit函数
参数:将立即数1传给%edi
3.atoi函数
参数:将%rdi设置为1
返回:将要返回的值存储在%eax中,并用ret返回
4.sleep函数
参数:将%edi设置为atoi(argv[3])(即调用atoi函数返回的数据)
5.printf函数
在hello.s中printf被替换成了puts
参数:第一个printf将字符串的首地址传给了%rdi,然后调用了puts函数。第二个printf将“Hello %s %s\n”的首地址传给了%rdi,设置%rsi为argv[1],%rdx为argv[2]
6.getchar函数
3.4 本章小结
本章主要讲解了编译器将hello.i处置惩罚为hello.s的过程。偏重描述编译时编译器如那边理数据并进行赋值操作、运算操作、关系操作、控制操作及函数操作等
(第3章2分)
第4章 汇编
4.1 汇编的概念与作用
概念:汇编器(as)将hello.s文件翻译成机器能读懂的机器语言指令,并将这些指令打包成可重定位目的文件hello.o。
注意:这儿的汇编是指从 .s 到 .o 即编译后的文件到生成机器语言二进制程序的过程。
作用:产生气器能读懂的代码,使得程序能被机器执行。
4.2 在Ubuntu下汇编的下令
下令:gcc -c hello.s -o hello.o
4.3 可重定位目的elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特殊是重定位项目分析。
获得hello.o文件的elf格式的指令:readelf -a hello.o > hello.elf
1.ELF头
ELF头以一个十六字节的序列开始,描述了数据字节顺序数据表示方法、目的文件类型、系统架构、入口点地址、程序头起点、节头部的起始位置、ELF头的大小以及节头部表中条目的大小与数量等信息。
2.节头部表
节头部表描述了各个节的类型、位置和大小等信息。
3.重定位节
重定位节包含了.text 节必要重定位的信息,在生成可执行文件的时间会修改。图中包罗puts,exit,printf,atoi,sleep,getchar这几个函数位置的描述。
4.4 Hello.o的结果解析
指令:objdump -d -r hello.o
分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
说明机器语言的构成,与汇编语言的映射关系。特殊是机器语言中的操作数与汇编语言不一致,特殊是分支转移函数调用等。
与hello.s文件进行比较:
1.hello.o文件中每条语句都有了一个偏移量,便于跳转寻址。
2.hello.txt采用十六进制,而hello.s中采用十进制。
3.hello.s中函数调用的方式是call后直接跟着函数名,而hello.txt中函数的调用方式是call后跟随着一个相对地址(函数与下一条指令的相对位置加上下一条指令的地址)来调用。
4.分支转移:在.s文件中使用段名称如.LC0,反汇编代码中确定的地址。
4.5 本章小结
本章简单先容了汇编的过程,分析了elf的格式和内容,之后通过查看反汇编代码,比较与.o文件的差别。
(第4章1分)
第5章 链接
5.1 链接的概念与作用
概念:将各种代码和数据片断网络并组合成一个单一文件的过程,这个文件可以被加载到内存中执行。
作用:链接操作将各个.o里面的函数引用,全局变量引用进行重定位,最终得到一个可执行目的文件,这个文件可以被加载到内存并运行。
注意:这儿的链接是指从 hello.o 到hello生成过程。
5.2 在Ubuntu下链接的下令
ld -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 /usr/lib/gcc/x86_64-linux-gnu/11/crtbegin.o hello.o -lc /usr/lib/gcc/x86_64-linux-gnu/11/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o -z relro -o hello
使用ld的链接下令,应截图,展示汇编过程! 注意不只连接hello.o文件
5.3 可执行目的文件hello的格式
指令:readelf -a hello > hello1.elf
分析hello的ELF格式,用readelf等列出其各段的基本信息,包罗各段的起始地址,大小等信息。
5.3.1ELF头
ELF头以一个序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部门包含帮助链接器语法分析息争释目的文件的信息。此中包罗ELF头的大小、目的文件的类型、机器类型、节头部表的文件偏移,以及节头部表中条目的大小和数量。
如图所示,hello的ELF以一个16进制序列:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00作为ELF头的开头。这个序列描述了生成该文件的系统的字的大小为8字节,而且字节顺序为小端序。
此中的信息表明:ELF头的大小为64字节;目的文件的类型为REL(可重定位文件);机器类型为Advanced Micro Devices X86-64(即AMD X86-64);节头部表的文件偏移为0;以及节头部表中条目的大小,其数量为25。
5.3.2节头部表
如图所示,hello的节头部表描述了25个节的相关信息,与hello.o的节头部表相比,多出来的部门:
.interp:动态链接器在操作系统中的位置不是由系统设置决定,也不是由情况参数指定,而是由ELF文件中的 .interp段指定。该段里保存的是一个字符串,这个字符串就是可执行文件所必要的动态链接器的位置,常位于/lib/ld-linux.so.2。
.dynamic:该段中保存了动态链接器所必要的基本信息,是一个结构数组,可以看做动态链接下 ELF文件的“文件头”。存储了动态链接会用到的各个表的位置等信息。
.dynsym:该段与 “.symtab”段类似,但只保存了与动态链接相关的符号,很多时间,ELF文件同时拥有 .symtab 与 .synsym段,此中 .symtab 将包含 .synsym 中的符号。该符号表中记载了动态链接符号在动态符号字符串表中的偏移,与.symtab中记载对应。
.dynstr:该段是 .dynsym 段的辅助段,.dynstr 与 .dynsym 的关系,类比与 .symtab 与 .strtab的关系 hash段:在动态链接下,必要在程序运行时查找符号,为了加速符号查找过程,增加了辅助的符号哈希表,功能与 .dynstr 类似
.rel.dyn:对数据引用的修正,其所修正的位置位于 “.got”以及数据段(类似重定位段 “rel.data”)
.rel.plt:对函数引用的修正,其所修正的位置位于 “.got.plt”。
5.3.3符号表
符号表存放的内容为:在程序中定义和引用的函数和全局变量的信息。存在编号Num、Value、Size、Type、Bind、Vis、Ndx、Name字段。
与hello.o文件相比,此中的函数名被替换为更为详细的内容,如puts被替换为puts@GLIBC_2.2.5,说明其找到了该函数的定义。而且与hello.o相比,多了一个.dynsym节。
另外,此中还含有.symtab节。
5.3.4重定位信息
如图所示,与hello.o相比,程序多出来了一个节:.rela.dyn,存放和动态链接相关的信息,是对于数据引用的修正,修正.got及数据段。
同时与hello.o相比,程序的很多函数酿成了类似puts@GLIBC_2.2.5+0的情势,说明其在相关的库中找到了这个函数,是对函数引用的修正,用于修正.got.plt。
5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
使用edb打开hello的可执行文件后,可以在Data Dump中找到hello的虚拟地址空间。程序的虚拟地址空间为 0x00000000004001000-0x0000000000402000。
程序包含PHDR,INTERP,LOAD,DYNAMIC,NOTE,GNU_STACK,GNU_RELRO几个部门,此中PHDR 保存程序头表。INTERP 指定在程序已经从可执行文件映射到内存之后,必须调用的解释器。LOAD 表示一个必要从二进制文件映射到虚拟地址空间的段。此中保存了常量数据、程序的目的代码等。DYNAMIC 保存了由动态链接器使用的信息。NOTE 保存辅助信息。GNU_STACK:权限标志,用于标志栈是否是可执行。GNU_RELRO:指定在重定位结束之后哪些内存区域是必要设置只读。
5.5 链接的重定位过程分析
指令:objdump -d -r hello>hello1.txt
分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
- 链接将程序中调用过得函数的汇编代码也参加到了程序里,hello1.txt中出现了puts getchar,atio,exit,sleep的汇编代码
2.hello1.txt文件中增加了_init和.plt节
3.函数调用,链接后每个函数都有了确定的运行地址
4.相对偏移地址变为了虚拟内存的地址。链接时,链接器通过符号表和节头相识到.data和.text在每个文件中的偏移和大小,进行合并,然后为新的合并出来的数据和代码节分配内存,并映射虚拟内存地址。末了修改对各种符号的引用,完成重定位。
5.6 hello的执行流程
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的全部过程。请列出其调用与跳转的各个子程序名或程序地址。
从加载hello到_start,到call main,以及程序终止的全部过程中调用的子程序名:
ld-2.23.so!_dl_start
ld-2.23.so! dl_init
hello!_start
hello!__libc_start_main
libc-2.23.so!__libc_start_main
libc-2.23.so! cxa_atexit
hello!__libc_csu_init
hello!_init
libc-2.23.so!_setjmp
libc-2.23.so!_sigsetjmp
hello!main
hello!puts@plt
hello!exit@plt
hello!printf@plt
hello!sleep@plt
hello!getchar@plt
ld-2.23.so!_dl_runtime_resolve_avx
libc-2.23.so!exit
5.7 Hello的动态链接分析
分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变革。要截图标识说明。
当程序调用一个由共享库定义的函数时,编译器没有办法预测这个函数的运行时地址,因为定义它的共享模块在运行时可以加载到任意位置。正常的方法是为该引用生成一条重定位记载,然后动态链接器在程序加载的时间再解析它。但这必要链接器修改调用模块的代码段,GNU编译系统使用一种称为耽误绑定的技术将过程地址的绑定推迟到第一次调用该过程时。
耽误绑定是通过两个数据结构之间的交互来实现的,分别是GOT和PLT,GOT是数据段的一部门,而PLT是代码段的一部门。PLT与GOT的协作可以在运行时解析函数的地址,实现函数的动态链接。
过程链接表PLT是一个数组,每个条目是16字节代码。PLT[0]是一个特殊条目,跳转到动态链接器中。每个被可执行程序调用的库函数都有它本身的PLT条目。
根据节头表中给出的偏移地址可以看到.got和.got.plt段位置在0x403ff0和0x404000处, 即可在data dump中观察数据的变革。
调用dl_init前后:
5.8 本章小结
本章简要先容了链接的概念和作用,以及Ubuntu下的链接下令。并以hello文件为例,查看了链接后的文件格式,并对虚拟地址分配,重定位,动态链接等过程进行了分析。
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
概念:指程序的依次运行过程。更确切说,进程是具有独立功能的一个程序关于某个数据集合的依次运行活动,进而进程具有动态含义。同一个程序处置惩罚不同的数据就是不同的进程。
作用:给应用程序提供两个关键抽象——
1.一个独立的逻辑控制流,提供一个假象,似乎程序独占地使用处置惩罚器。
2.一个私有地址空间,提供一个假象,似乎程序独占地使用内存系统。
6.2 简述壳Shell-bash的作用与处置惩罚流程
Shell 既是一种下令语言,又是一种程序设计语言。Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问 Linux 内核的服务。
作用:Shell是一个下令解释器,是用户使用Linux的桥梁,它解释由用户输入的下令而且把它们送到内核,提供用户与内核进行交互操作的一种接口,而且允许用户编写由shell下令构成的程序。
处置惩罚流程:用户输入键盘信号,shell应该接受这些键盘输入信号,并对这些信号进行相应处置惩罚,具体处置惩罚流程如下:
(1)从终端读入输入的下令,将输入字符串切分获得全部的参数。
(2)shell对用户输入下令进行解析,判断是否为内置下令,假如是则立即执行。
(3)若不是内置下令,则会检查是否为一个可执行文件,假如是,则会fork子进程,启动加载器在当进步程中加载并运行程序。
(4)假如不是内置下令且无法找到这个可执行文件,则会表现一条错误信息。
(5)假如程序是前台运行程序,则调用等待函数等待前台作业结束。否则将程序转入后台,直接开始下一进程。
6.3 Hello的fork进程创建过程
在终端中输入下令行./hello后,shell会处置惩罚该下令,假如判断出不是内置下令,则会调用fork函数创建一个新的子进程,子进程险些但不完全与父进程相同。通过fork函数,子进程得到与父进程用户级虚拟地址空间相同的但是独立的一份副本,拥有不同的PID。
6.4 Hello的execve过程
execve函数在加载并运行可执行目的文件hello,且带列表argv和情况变量列表envp。该函数的作用就是在当进步程的上下文中加载并运行一个新的程序。
只有当出现错误时,比方找不到hello时,execve才会返回到调用程序,这里与一次调用两次返回的fork不同。
在execve加载了hello之后,它调用启动代码。启动代码设置栈,并将控制传递给新程序的主函数,该主函数有如下的原型:
int main(intargc ,char **argv, char *envp)
结合虚拟内存和内存映射过程,可以更详细地说明exceve函数实际上是如何加载和执行程序hello:
(1)删除已存在的用户区域(自父进程独立)。
(2)共享区映射:好比hello程序与标准C库libc.so链接,这些对象都是动态链接到hello的,然后再用户虚拟地址空间中的共享区域内。
(3)私有区映射:为Hello的代码、数据、.bss和栈区域创建新的区域结构,全部这些区域都是私有的、写时才复制的。
(4)设置PC:exceve会设置当进步程的上下文中的程序计数器,指向代码区的入口。
6.5 Hello的进程执行
结合进程上下文信息、进程时间片,阐述进程调理的过程,用户态与焦点态转换等等。
同一时间,有多个使命在系统上并行执行,操作系统内核使用一种称为上下文切换的较高层情势的异常控制流来实现多使命。上下文就是内核重启一个被抢占的进程所必要的状态。
在hello执行过程中,内核可以决定抢占当进步程,并重新开始一个先前被抢占的进程,这个决策称为调理。调理的过程是由调理器完成的,当内核调理新的进程运行后,它就会抢占当进步程,并进行:
(1)保存以进步程的上下文。
(2)恢复新恢复进程被保存的上下文。
(3)将控制传递给这个新恢复的进程,来完成上下文切换。
6.6 hello的异常与信号处置惩罚
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处置惩罚的。
程序运行过程中可以按键盘,如不停乱按,包罗回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等下令,请分别给出各下令及运行截屏,说明异常与信号的处置惩罚。
6.6.1hello执行过程中可能出现的异常
hello执行过程中可能出现四类异常:中断、陷阱、故障和终止。
(1)中断是异步发生的,是来自外部I/O设备的信号的结果,中断处置惩罚程序对其进行处置惩罚,返回后继续执行调用前待执行的下一条代码,就像没有发生过中断一样。
(2)陷阱是同步发生的,是故意的异常,是执行一条指令的结果,调用后也会返回到下一条指令,用来调用内核的服务进行操作。帮助程序从用户模式切换到内核模式。
(3)故障是同步发生的,是由错误情况引起的,它可能可以或许被故障处置惩罚程序修正。假如修正成功,则将控制返回到引起故障的指令,否则将终止程序。
(4)终止是同步发生的,是不可恢复的致命错误造成的结果,通常是一些硬件的错误,处置惩罚程序会将控制返回给一个abort例程,该例程会终止这个应用程序。
6.2.2信号处置惩罚
假如乱按过程中没有回车,这个时间只是把输入屏幕的字符串缓存起来。下一条屏幕输出内容在乱按的内容后边,仍然是原本应该输出的内容。
假如输入末了是回车,getchar读回车,并把回车前的字符串看成shell输入的下令
输入Ctrl+C会让内核发送一个SIGINT信号给到前台进程组中的每个进程,结果是终止前台进程——即hello程序,通过ps下令发现这时hello进程已经被回收。
输入Ctrl+Z会发送一个SIGTSTP信号给前台进程组的每个进程,结果是停止前台进程——即hello程序。
Ctrl-z后可以运行ps jobs pstree fg kill 等下令,请分别给出各下令及运行截屏,说明异常与信号的处置惩罚。
(3)Ctrl+Z后运行pstree
fg的功能是使第一个后台作业变为前台,而第一个后台作业是hello,以是输入fg 后hello程序又在前台开始运行,而且是继续刚才的进程。在本程序中一共输出9行。
(5)Ctrl+Z后运行kill
如图,先使用ps查看hello进程的PID然后使用kill -9 20857强制杀死hello进程,再次用ps查看,发现hello程序已经被终止。
6.7本章小结
本章主要先容了有关hello进程管理的内容,通过shell我们可以管理盘算机运行的进程。我们还先容了hello程序的fork、execve过程,然后通过下令行研究了程序运行当中可能会遇见的异常,以及我们的系统是如那边理这些由异常发出的信号的。
(第6章1分)
第7章 hello的存储管理
7.1 hello的存储器地址空间
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
逻辑地址,是指由程序hello产生的与段相关的偏移地址部门,hello.o文件中的地址就是逻辑地址。
线性地址,是逻辑地址到物理地址变换之间的中心层。程序hello的代码会产生逻辑地址——也就是段中的偏移地址,它加上相应段的基地址就会生成线性地址。
虚拟地址,是由CPU生成的一个仰赖访问主存的地址,它会被送到内存之前先转换成得当的物理地址,地址翻译的使命由CPU芯片上的内存管理单位MMU来承担,MMU会用存放在主存中的查询表来动态翻译虚拟地址,该表的内容由操作系统管理。在linux系统中,只会分页而不会分段,因此对于我们的hello程序逻辑地址险些就是虚拟地址。
物理地址,是主存上被组织成一个由M个连续的字节大小的单位构成的数组,每个字节都有一个唯一的物理地址,hello的物理地址来自于虚拟地址的地址转换,它也是程序运行的最终地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
以下为三个基本概念,能帮助我们理解线性地址:
(1)一个逻辑地址由段标识符和段内偏移量构成。
(2)段标识符是一个16位长的字段。可以通过段标识符的前13位,直接在段描述符表中找到一个具体的段描述符,这个描述符就描述了一个段。
(3)全局的段描述符,放在“全局段描述符表(GDT)”中,一些局部的段描述符,放在“局部段描述符表(LDT)”中。
对于给定一个完备的逻辑地址段选择符+段内偏移地址,确定线性地址的顺序如下:
(1)看段选择符的T1= = 0还是= = 1,知道当前要转换是GDT中的段,还是LDT中的段。
(2)再根据相应寄存器,得到其地址和大小。
(3)拿出段选择符中前13位,在这个数组中,查找到对应的段描述符,由此得到了其基地址。
(4)Base + offset = 线性地址。
7.3 Hello的线性地址到物理地址的变换-页式管理
页式管理是一种内存空间存储管理的技术,页式管理分为静态页式管理和动态页式管理。将各进程的虚拟空间分别成若干个长度相等的页(page),页式管理把内存空间按页的大小分别成片大概页面(page frame),然后把页式虚拟地址与内存地址创建一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。页式管理采用请求调页或预调页技术实现了表里存存储器的同一管理。
1.根据线性地址前十位找到对应页表的地址。
2.根据线性地址中心十位找到对应页的起始地址。
3.页的起始地址加上线性地址末了十二位,得到物理地址。
7.4 TLB与四级页表支持下的VA到PA的变换
TLB的支持:在MMU中包罗一个关于PTE的缓存,称为翻译后备缓冲器(TLB)。TLB是一个小的、虚拟寻址的缓存,每一行保存着一个由单个PTE构成的块。由于VA到PA的转换过程中,必要使用VPN确定相应的页表条目,因此TLB必要通过VPN来探求PTE。和其他缓存一样,必要进行组索引和行匹配。假如TLB有2t个组,那么TLB的索引TLBI由VPN的t个最低位构成,TLB标记TLBT由VPN中剩余的位构成。
当MMU进行地址翻译时,会先将VPN传给TLB,看TLB中是否已经缓存了必要的PTE,假如TLB命中,可以直接从TLB中获取PTE,将PTE中的物理页号和虚拟地址中的VPO连接起来就得到相应的物理地址。这时全部的地址翻译步调都是在芯片上的MMU中执行的,因此非常快。假如TLB不命中,那和7.3中描述的过程类似,必要从cache大概内存中取出相应的PTE。
四级页表的支持:多级页表可以用来压缩页表,对于k级页表层次结构,虚拟地址的VPN被分为k个,每个VPNi是一个到第i级页表的索引。当1≤j≤k-1时,第j级页表中的每个PTE指向某个第j+1级页表的基址。第k级页表中的每个PTE和未使用多级页表时一样,包含某个物理页面的PPN大概一个磁盘块的地址。对于Intel Core i7,使用了4级页表(如图7-1所示),每个VPNi有9位。当TLB未命中时,36位的VPN被分为VPN1、VPN2、VPN3、VPN4,每个VPNi被用作到一个页表的偏移量。CR3寄存器包含L1 页表的物理地址,VPN1提供到一个L1 PTE的偏移量,这个PTE包含某个L2页表的基址。VPN2提供到这个L2页表中某个PTE的偏移量,以此类推。末了得到的L4 PTE包含了必要的物理页号,和虚拟地址中的VPO连接起来就得到相应的物理地址。
7.5 三级Cache支持下的物理内存访问
获得物理地址之后,先取出组索引对应位,在L1中探求对应组。假如存在,则比较标志位,相等后检查有用位是否为1.假如都满足则命中取出值传给CPU,否则按顺序对L2cache、L3cache、内存进行相同操作,直到出现命中。然后再一级一级向上传,假如有空闲块则将目的块放置到空闲块中,否则将缓存中的某个块驱逐,将目的块放到被驱逐块的位置。
7.6 hello进程fork时的内存映射。
当fork函数被当进步程hello调用时,内核为新进程hello创建各种数据结构,并分配给它一个唯一的PID。为了给这个新的hello创建虚拟内存,它创建了当进步程的mm_struct、区域结构和页表的原样副本。它将两个进程中的每个页面都标记为只读,并将两个进程中的每个区域结构都标记为私有的写时复制。
7.7 hello进程execve时的内存映射
execve 函数调用驻留在内核区域的启动加载器代码,在当进步程中加载并运行包含在可执行目的文件 hello 中的程序,用 hello 程序有用地替代了当前程序。加载并运行 hello 必要以下几个步调: 1. 删除已存在的用户区域,删除当进步程虚拟地址的用户部门中的已存在的区域构。 2. 映射私有区域 , 为新程序的代码、数据、 bss 和栈区域创建新的区域结构,全部这些新的区域都是私有的、写时复制的. 代码和数据区域被映射为 hello 文件中的 .text和.data 区, bss 区域是请求二进制零的,映射到匿名文件,其大小包含在 hello 中,栈和堆地址也是请求二进制零的,初始长度为零。 3. 映射共享区域, hello 程序与共享对象 libc.so 链接, libc.so 是动态链接到这个程序中的,然后再映射到用户虚拟地址空间中的共享区域内。 4. 设置程序计数器(PC), execve 做的末了一件事情就是设置当进步程上下文的程序计数器,使之指向代码区域的入口点。 7.8 缺页故障与缺页中断处置惩罚
缺页故障处置惩罚: DRAM 缓存不命中称为缺页,缺页异常调用内核中缺页异常处置惩罚程序,该程序从内存选择一个捐躯页,将其复制回磁盘,随后内核将所需页面复制到内存相应位置,更新页表后返回,重新启动导致缺页的指令,该指令会盘算机系统基础课程报告把导致缺页的虚拟地址重发送到地址翻译硬件。 缺页中断处置惩罚:缺页处置惩罚程序是系统内核中的代码,选择一个捐躯页面,假如这个捐躯页面被修改过,那么就将它交换出去,换入新的页面并更新页表。缺页处置惩罚程序返回时,CPU 重新启动引起缺页的指令,这条指令再次发送 VA 到MMU,这次 MMU 就能正常翻译 VA 了。 7.9动态存储分配管理
Printf 会调用 malloc ,请简述动态内存管理的基本方法与策略。 分配器有两种风格,表现分配器(要求应用显式地开释任何已分配的块隐式分配器(要求分配器检测一个已分配块是否仍然必要,不必要则开释)。 分配策略: 1. 空闲链表: ( 1 ) 隐式:在每块的头,尾部增加 32 位存储块大小,以及是否空闲。 (2) 显式:在隐式的基础上在头部增加对前后空闲块的指针。 (3) 分离:同时维护多个空闲链表。 2. 带边界标记的合并:使用每块头尾的大小和空闲状态信息合并空闲块。 3. 无合适空闲块时,申请额外的堆空间。 7.10本章小结
本章先容了储存器的地址空间,讲述了虚拟地址、物理地址、线性地址、逻辑地址的概念,另有进程fork和execve时的内存映射的内容。描述了系统如何应对那些缺页异常,末了描述了动态内存分配管理机制。
(第7章 2分)
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:文件
设备管理:unix io接口
8.2 简述Unix IO接口及其函数
(以下格式自行编排,编辑时删除)
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程序所履历的过程:
生成阶段:预处置惩罚→编译→汇编→链接;
加载阶段:shell fork子进程→execve;
执行阶段:磁盘读取、虚拟内存映射、CPU执行指令、内核调理、缓存加载数据、信号处置惩罚、Unix I/O输入与输出;
终止阶段:进程终止、shell与内核对其进行回收。
感悟:通过分析各种文件,我对编译汇编链接等过程的理解更加深刻了。盘算机上任何一个简单的程序,都必要软硬件协作经过一系列复查的过程才气完成,深入理解盘算机系统,有助于我们相识这一过程,对我们编写面向盘算机友好的系统有很大帮助。
(结论0分,缺失 -1分,根据内容酌情加分)
附件
列出全部的中心产物的文件名,并予以说明起作用。
hello.i:C预处置惩罚器产生的一个ASCII码的中心文件,用于分析预处置惩罚过程。
hello.s:C编译器产生的一个ASCII汇编语言文件,用于分析编译的过程。
hello.o:汇编器产生的可重定位目的程序,用于分析汇编的过程。
hello:链接器产生的可执行目的文件,用于分析链接的过程。
obj_hello.o.text:hello.o的反汇编文件,用于分析可重定位目的文件hello.o。
obj_hello.text:hello的反汇编文件,用于分析可执行目的文件hello。
hello_elf.text:hello的ELF格式,用于分析可执行目的文件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分)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) |
Powered by Discuz! X3.4 |