ToB企服应用市场:ToB评测及商务社交产业平台
标题: 步伐人生 Hello’s P2P -2024ICS SPRING [打印本页]
作者: 尚未崩坏 时间: 2024-6-22 13:09
标题: 步伐人生 Hello’s P2P -2024ICS SPRING
摘 要
本文通过hello小步伐的一生,对我们所学的CSAPP课程进行全面的梳理与回顾。对hello步伐的整个生命周期进行了系统的分析,从hello.c源步伐开始,经过预处置惩罚、编译、汇编、链接、创建历程、加载hello…最后结束历程并由父历程进行接纳这一系列分析,对于hello在计算机系统的一生有深入的明白。
关键词:编译;汇编;链接;预处置惩罚;hello的历程管理;p2p;020
目 录
第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 -
结论......................................................................................................................... - 14 -
附件......................................................................................................................... - 15 -
参考文献................................................................................................................. - 16 -
第1章 概述
1.1 Hello简介
P2P:From Program to Program。
图1 从源文件到可实验文件
a.编写代码,得到源步伐hello.c,这就是Program。
b.预处置惩罚器cpp读取头文件内容,直接插入到步伐文本,得到中间文件hello.i。
c.编译器gcc得到翻译成汇编语言文件hello.s。
d.汇编器as得到可重定位目标文件hello.o。
e.链接器ld得到可实验目标文件hello。
f.最后在shell键入启动此步伐,shell调用fork函数为其产生子历程,hello便成为了历程Process。完成了P2P。
O2O:From Zero-0 to Zero-0。
OS的历程管理调用fork函数产生子历程,调用execve函数,并进行假造内存映射(mmp),并为运行的hello分配时间片以实验取指译码流水线等操作。OS的存储管理以及MMU办理VA到PA的转换,cache、TLB、页表等加速访问过程,IO管理与信号处置惩罚综合软硬件对信号等进行处置惩罚;步伐结束时,shell接纳hello历程,内核将其所有陈迹从系统中清除。至此,从0开始编写的hello.c履历了它短暂的一生,又回到了最初的起点
1.2 环境与工具
CPU i7-12700H,16G RAM,1T SSD;
Win11,VMware,Ubuntu20.04
1.3 中间效果
hello.i :预处置惩罚
hello.s :所得汇编代码
hello.o :所得的可重定位目标实验文件
hello.out :链接后所得二进制文件
hello :可实验步伐
1.4 本章小结
对hello做了基础的先容,简介了P2P,O2O;先容了作业环境,使用的工具和中间效果的文件名称。
第2章 预处置惩罚
2.1 预处置惩罚的概念与作用
概念:预处置惩罚(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。预处置惩罚指令指示在步伐正式编译前就由编译器进行的操作,可放在步伐中任何位置。
作用:
a.将源文件中以”include”格式包含的文件复制到编译的源文件中。
b.用现实值更换用“#define”定义的字符串。
c.根据“#if”后面的条件决定必要编译的代码。
d.公道使用预处置惩罚功能编写的步伐便于阅读、修改、移植和调试,也有利于模块化步伐计划。
2.2在Ubuntu下预处置惩罚的命令
图2 预处置惩罚命令
2.3 Hello的预处置惩罚效果解析
由图3可以看出,预处置惩罚对原文件中的宏进行了宏展开,文件最开头的三个#include消散,一段代码代替了三个#include。头文件中的内容被包含进该文件中。比方声明函数、定义结构体、定义变量、定义宏等内容,最后hello.c文件变为hello.i文件。而且hello.c的主体部分还存在于hello.i中。
图3 hello.i部分文件内容
2.4 本章小结
本章说明了预处置惩罚的概念以及作用,命令以及hello.c文件的预处置惩罚效果hello.i文本文件解析。详细相识了预处置惩罚的内涵,知道了预处置惩罚这一阶段一共完成多少事变:头文件的展开、宏更换、去掉注释、条件编译。同时截图展示了预处置惩罚的过程和效果。
第3章 编译
3.1 编译的概念与作用
概念:编译过程是整个步伐构建的核心部分,将源代码由文本形式转换成呆板语言,编译过程就是把预处置惩罚完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。也就是将hello.i翻译成汇编语言文件hello.s的过程。
作用: 将高级语言步伐转化为呆板可直接识别处置惩罚实验的的呆板码的中间步骤,为后面的汇编做好预备。详细来说有以下几部分作用:词法分析,对输入的字符串进行分析和分割,形成所使用的源步伐语言所允许的记号,同时标注不规范记号,产生错误提示信息;语法分析,分析词法分析得到的记号序列,并按一定规则识别并生成中间表示形式,以及符号表。同时将不符合语法规则的记号识别出其位置并产生错误提示语句;语义分析,即静态语法检查,分析语法分析过程中产生的中间表示形式和符号表,以检查源步伐的语义是否与源语言的静态语义属性符合合;代码优化,将中间表示形式进行分析并转换为功能等价但是运行时间更短或占用资源更少的等价中间代码。
3.2 在Ubuntu下编译的命令
命令:gcc hello.i -S -o hello.s
图4 在Ubuntu下编译命令
3.3 Hello的编译效果解析
3.3.1 数据
a.常量
图5 hello.s中的常量
由图5,常量是两个字符串,这两个字符串都是printf函数的参数。即
用法: Hello 学号 姓名 手机号 秒数!
Hello %s %s %s\n
b.变量
main函数里声明了一个局部变量i,在编译器编译生成汇编语言后,i被存储在了-4(%rbp)的位置,如下图所示:
图6 局部变量i
main函数的参数argc和argv,此中argv为指针数组。同时由寄存器规则可知,argc存储在了寄存器%edi(第一个参数)中,argv存储在了寄存器%rsi(第二个参数)中,每个地点是八位。
图7 参数argc和指针数组argv
3.3.2 赋值
hello.c步伐中的赋值操作为i=0,详细在汇编代码中的实现形式为movl $0, -4(%rbp),此中l后缀表明i是双字类型的整数数据,即占4个字节的整数数据(int型)。
图8 赋值i=0
3.3.3 类型转换
atoi(argv[4]),该语句实现了将字符串类型转换为整数类型。
3.3.4 算术操作
i++操作以及计算格式串地点操作。
图9 计算格式串地点
图10 i++指令
3.3.5 关系操作
argc!=5,该语句用于判断argc的值是否与5相等,该语句被编译为cmpl $5, -20(%rbp)。比力完成后会设置条件码,通过条件码判断跳转位置。
图11 比力argc!=5
i<10。该语句用于判断局部变量i和8的大小作为循环的条件,在汇编代码中被编译为cmpl $9, -4(%rbp)。通过比力完成后的条件码确定跳转位置。
图12 比力i<10
3.3.6 数组
数组argv[],指针数组,见3.3.1。
3.3.7 控制转移
同3.3.5 关系操作中指令与图。
3.3.8 函数操作
a.main函数
main函数的参数为argc和argv。argc存储在%edi中,argv存储在%rsi中。返回值为int类型,存储在%eax中。
b.printf函数
hello.c步伐中调用了两次printf函数,但是两次调用传入的参数不同。第一次传入的是.LC0处的字符串,第二次传入的是.LC1处的字符串以及argv[1]和argv[2]。
图13 第一次调用printf
图14 第二次调用printf
c.exit函数
exit函数实现从main函数退出。hello.c步伐中传入的参数是1,表示非正常退出。
图15 exit函数调用
d.atoi函数
atoi函数实现将字符串类型的数据转变成int类型的数据。
图16 atoi函数调用
e.sleep函数
进行休眠,秒数=手机号%5。
图17 sleep函数调用
f.getchar函数
getchar函数实现读取缓冲区字符。不必要通报参数,直接调用即可。
图18 getchar函数调用
3.4 本章小结
本章主要详细先容了编译的概念与作用,以及编译的指令,最后对编译文件hello.s按照PPT中P4给出的参考对以下方面进行了表明:数据(常量、变量)、类型转换、算术操作、关系操作、数组、控制转移、函数操作(参数通报(地点/值)、函数调用()、函数返回)。在编译的过程中,编译器将高级语言编译生成了汇编语言,作为到呆板语言的一个过渡,我们明白汇编语言可以明白编程的底层实现,对于代码优化、代码效率等方面都有帮助。
第4章 汇编
4.1 汇编的概念与作用
概念:把汇编语言翻译成呆板语言的过程称为汇编。在汇编语言中,用助记符(Memoni)代替操作码,用地点符号(Symbol)或标号(Label)代替地点码。这样用符号代替呆板语言的二进制码,就把呆板语言变成了汇编语言。于是汇编语言亦称为符号语言。用汇编语言编写的步伐,呆板不能直接识别,要由一种步伐将汇编语言翻译成呆板语言,这种起翻译作用的步伐叫汇编步伐,汇编步伐是系统软件中语言处置惩罚的系统软件。
作用:汇编过程将汇编代码转换为计算性能够明白并实验的二进制呆板代码,这个二进制呆板代码是步伐在本呆板上的呆板语言的表示。
4.2 在Ubuntu下汇编的命令
gcc hello.s -c -o hello.o
图19 汇编命令和生成方式
4.3 可重定位目标elf格式
4.3.1 EFL头
用命令readelf -h hello.o查看,ELF头以一个16字节的序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助链接器语法分析息争释目标文件的信息。此中包罗ELF头的大小、目标文件的类型、呆板类型、节头部表的文件偏移,以及节头部表中条目的大小和数量。由上图可以看出,hello.o为64位文件;数据接纳补码表示,小端存储;文件类型为REL(可重定位的目标文件);步伐的入口地点为0x0,由于hell.o还未实现重定位;可重定位文件没有段头表(Start of program headers的值为0);节头表的起始位置为1264;文件中共有14节。
图20 EFL头内容
4.3.2 节头表
命令readelf -S hello.o,节头表包含了文件中出现的各个节的语义,包罗节的类型、位置和大小等信息。 由于是可重定位目标文件,以是每个节都从0开始,用于重定位。在文件头中得到节头表的信息,然后再使用节头表中的字节偏移信息得到各节在文件中的起始位置,以及各节所占空间的大小,同时可以观察到,代码是可实验的,但是不能写;数据段和只读数据段都不可实验,而且只读数据段也不可写。
图21 节头表内容
4.3.3 符号表
readelf -s hello.o,符合表存放步伐中定义和引用的函数和全局变量的信息。符号表中存储了步伐中定义和使用的各种符号,包罗函数名,全局变量名等等。此中每一个符号有其对应的值,大小,类型,名字等等内容。
图22 符号表内容
4.3.4 重定位节
readelf -r hello.o,重定位节:一个.text 节中位置的列表,包含.text 节中必要进行重定位的信息,当链接器把这个目标文件和其他文件组合时,必要修改这些位置。Offset:必要被修改的引用节的偏移。Info:包罗symbol和type两个部分,symbol在前面四个字节,type在后面四个字节。symbol:标识被修改引用应该指向的符号;type:重定位的类型。Type:告知链接器应该怎样修改新的应用。Addend:一个有符号常数,一些重定位要使用它对被修改引用的值做偏移调整。 Name:重定向到的目标的名称。
图23 重定位节内容
4.4 Hello.o的效果解析
反汇编代码和hello.s中的代码并没有太大的差别。反汇编代码中不但有汇编代码,还有其对应的呆板语言代码。呆板语言代码中包含操作码,数据,寄存器编号等内容,此中呆板语言的每一个操作码,寄存器编号等都与汇编语言一一对应。呆板语言中的数据接纳小端存储的二进制形式表示,而在汇编语言中接纳的是顺序十六进制形式表示。通过这些映射关系就可以实现呆板语言与汇编语言的一一对应。
分支转移:反汇编代码中用的不是hello.s中的符号来代表位置,而是用的相对地点表示。hello.s中的.L1等只是便于编写的助记符。
函数调用:在.s 文件中,函数调用之后直接跟着函数名称,而在反汇编代码中,call的目标地点是当前下一条指令。这是由于 hello.c 中调用的函数都是共享库中的函数,终极必要通过动态链接器才气确定函数的运行时实验地点。在汇编成为呆板语言的时间,对于这些不确定地点的函数调用,将其call指令后的相对地点设置为全0,最后在链接时才填入正确的地点。
图24-1 反汇编代码
图24-2 反汇编代码
4.5 本章小结
本章先容了汇编的概念和作用,并通过对hello.s的汇编效果的分析简要讲述了可重定位文件的格式,重点讲述了可重定位文件的ELF头,节头表,符号表和重定位节的内容。最后比力了反汇编效果与汇编文件hello.s的区别。
第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
图25 链接命令和生成文件
5.3 可实验目标文件hello的格式
5.3.1 ELF头
hello的ELF头中指出hello的类型为EXEC类型,即hello为可实验目标文件,同时hello的入口地点非零,说明重定位工作已完成。留意到hello的ELF头中program headers的偏移量非零,说明hello文件中比hello.o文件中多了一个段头表。同时hello文件中节头表的条目数量为27,比hello.o文件中的数目多。
图26 链接后EFL头内容
5.3.2 节头表
hello中节头表的条目数多于hello.o中节头表的条目数。值得留意的是每一节都有了现实地点,而不是像在hello.o中那样地点值全为0。这说明重定位工作已完成。同时多出的节是为了能够实现动态链接。
图27 节头表内容(部分)
5.3.3 符号表
hello步伐的符号表包含编号Num、Value、Size、Type、Bind、Vis、Ndx、Name字段。
图28 hello符号表内容(部分)
5.3.4 段头表
段头表描述了可实验目标文件的连续的片与连续的假造内存段之间的映射关系。从段头表中可以看到根据可实验目标文件的内容初始化为两个内存段,分别为只读内存段(代码段)和读写代码段(数据段)。
图29 hello段头表内容(部分)
5.4 hello的假造地点空间
窗口显示假造地点由0x401000开始,到0x402000结束,这之间的每一个节对应5.3中的每一个节头表的声明。
图30 edb
5.5 链接的重定位过程分析
hello.o的反汇编代码的地点从0开始,而hello的反汇编代码从0x400000开始。这说明hello.o还未实现重定位的过程,每个符号还没有确定的地点,而hello已经实现了重定位,每个符号都有其确定的地点。hello中除了main函数的汇编代码,还有许多别的函数的汇编代码。对于跳转,返回指令的地点hello中已经有了明确的数据(PC相对或者是绝对),而hello.o中的地点位置全为0。链接是会为地点不确定的符号分配一个确定的地点,而在该符号的引用处也将地点改为确定值。
图31 hello反汇编(main)
重定位过程:在汇编器生成一个目标模块时,它并不知道数据和代码终极将放在内存中的什么位置。以是,无论何时汇编器遇到对终极位置未知的目标引用,它就会生成一个重定位条目,告诉链接器在将目标文件合并成可实验文件时怎样修改这个引用。在开头hello多了.init,.fini,.plt,.plt.got节,分别是步伐初始化实验的代码,步伐停止时必要实验的代码,动态链接中的过程毗连表,动态链接中的全局偏移表。
5.6 hello的实验流程
使用edb实验hello,从加载hello到_start,到call main,以及步伐停止的主要过程如下:
子步伐名
| 步伐地点(16进制)
|
ld-2.27.so!_dl_start
| 7efb ff4d8ea0
|
ld-2.27.so!_dl_init
| 7efb ff4e7630
|
hello!_start
| 400500
|
libc-2.27.so!__libc_start_main
| 7efb ff100ab0
|
hello!puts@plt
| 4004b0
|
hello!exit@plt
| 4004e0
|
5.7 Hello的动态链接分析
动态链接使我们在调用一个共享库定义的函数可以在运行时找到函数的地点。但是在调用时编译器没办法预测这个函数(共享库定义)的运行时地点,由于定义它的共享模块可以在运行时加载到任何位置。但是GNU编译系统通过耽误绑定技能来办理这个问题,将过程地点的绑定推迟到第一次调用该过程中。
耽误绑定通过:GOT和PLT实现,如果一个目标模块调用定义在共享库中的任何函数,那么他就有自己的GOT和PLT。
第一次调用共享库函数时,不调用共享库函数,直接进入函数对应的PLT中,接着PLT指令通过对应的GOT指令进行间接跳转,由于每个GOT指令初始时都指向他对应的PLT条目的第二条指令,以是这个间接跳转只是简单的把控制传回PLT条目的下一条指令。接着把函数的ID入栈PLT跳转到PLT[0],PLT[0]再将动态链接器的一个参数入栈,然后间接跳转到动态链接器中。动态链接器依据两个栈条目确定函数的运行位置,重写对应的GOT条目,再把控制传给函数。
以是,在运行dl_init前,GOT表中存放的都是对应PLT条目的第二条指令,在运行dl_init后,GOT表中存放的就是对应的函数的地点。
5.8 本章小结
本章结合实验中的hello可实验步伐依此先容了链接的概念及作用,在Ubuntu下链接的命令行;并对hello的elf格式进行了详细的分析对比,同时留意到了hello的假造地点空间知识;并通过反汇编hello文件,将其与hello.o反汇编文件对比,详细相识了重定位过程;遍历了整个hello的实验过程,在最后对hello进行了动态链接分析。
第6章 hello历程管理
6.1 历程的概念与作用
概念:历程是一个实验中的步伐的实例,系统中的每个步伐都运行在某个历程的上下文中。上下文是由步伐正确运行所需的状态组成的。这个状态包罗存放在内存中的步伐的代码和数据,它的栈、通用目的寄存器的内容、步伐计数器、环境变量以及打开文件描述符的聚集。
作用:历程提供给应用步伐两个关键抽象。逻辑控制流:每个步伐好像独占地使用CPU,通过OS内核的上下文切换机制提供。私有地点空间:每个步伐好像独占地使用内存系统,OS内核的假造内存机制提供。
6.2 简述壳Shell-bash的作用与处置惩罚流程
Shell是一个命令表明器,它表明由用户输入的命令而且把它们送到内核。不但如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的步伐。Shell编程语言具有平凡编程语言的许多特点,比如它也有循环结构和分支控制结构等。
Shell处置惩罚流程:
1.打印提示信息
2.等待用户输入
3.接奉命令
4.表明命令
5.找到该命令,实验命令,如果命令含有参数,输入的命令表明它
6.实验完成,返回第一步
6.3 Hello的fork历程创建过程
shell先判断出不是内置命令,于是加载可实验文件hello,通过fork创建一个子历程,子历程得到与父历程用户级假造地点空间相同的一份副本。子历程还获得与父历程任何打开文件描述符相同的副本。子历程与父历程有不同的pid。fork被调用一次,返回两次。在父历程中fork返回子历程的pid,在子历程中fork返回0。父历程与子历程是并发运行的独立历程。
6.4 Hello的execve过程
在shell创建的子历程中将会调用execve函数,来调用加载器,加载器将可实验目标文件中的代码和数据从磁盘复制到内存中,然后通过跳转到步伐的第一条指令或入口点来运行该步伐。这个将步伐复制到内存并运行的过程叫做加载。每个步伐都有一个运行时内存映像。当加载器运行时,它创建内存映像。在步伐头部表的引导下,加载器将可实验文件的片(chunk)复制到代码段和数据段。接下来,加载器跳转到步伐的入口点,也就是_start函数的地点。这个函数是在系统目标文件ctrl.o中定义的,对所哟额C步伐都是一样的。_start函数调用系统启动函数_ _libc_start_main,该函数定义在libc.so中,它初始化实验环境,调用用户层的main函数,处置惩罚main函数的返回值,而且在必要的时间把控制返回给内核。
6.5 Hello的历程实验
系统中的每个步伐都运行在某个历程的上下文中。上下文由步伐正确运行所需的状态组成,这个状态包罗存放在内存中的步伐的代码和数据,它的栈、通用目的寄存器的内容、步伐计数器、环境变量以及打开文件描述符的聚集。
内核调度hello的历程开始进行,输出Hello与之前输入的内容,然后实验sleep函数,这个函数是系统调用,它显示地哀求让调用历程休眠。内核转而实验其他历程,这时就会发生一个上下文转换。2s后,又会发生一次历程转换,恢复hello历程的上下文,继承实验hello历程。重复9次这个过程。
循环结束后,后面实验到getchar函数,这时读取数据一般必要很长的时间,以是将会发生一个上下文切换转而实验其他历程,当数据已经被读取到缓存区中,将会发生一个停止,使内核发生上下文切换,重新实验hello历程。
6.6 hello的异常与信号处置惩罚
hello实验过程中会出现哪几类异常,会产生哪些信号,又怎么处置惩罚的。
步伐运行过程中可以按键盘,如不停乱按,包罗回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处置惩罚。
6.6.1 不停乱按
如果乱按过程中没有按回车,则只会在屏幕上显示输入的内容。如果输入回车,则getchar读回车,并把回车前的字符串当作shell输入的命令。
图32 不停乱按效果
6.6.2 Ctrl-Z
如果输入Ctrl+Z会发送一个SIGTSTP信号给前台历程组的每个历程,效果是停止前台作业。
图33 Ctrl-Z效果
6.6.3 Ctrl-C
如果在步伐运行过程中输入Ctrl+C,会让内核发送一个SIGINT信号给到前台历程组中的每个历程,效果是停止前台历程。
图34 Ctrl-C效果
6.6.4 Ctrl-z后运行ps jobs pstree fg kill 等命令
Ctrl-Z后输入ps,jobs等命令仍会正常工作,同时可以看出此时hello步伐的状态为Stopped。fg的功能是使第一个后台作业变为前台,而第一个后台作业是hello,以是输入fg 后hello步伐又在前台开始运行。
图35 Ctrl-Z后输入其他命令效果
6.7本章小结
异常控制流发生在计算机系统的各个层次,是计算机系统中提供并发的基本机制。
1)在硬件层,异常是由处置惩罚器中的事件触发的控制流中的突变
2)在操作系统层,内核用ECF提供历程的基本概念。
3)在操作系统和应用步伐之间的接口处,应用步伐可以创建子进,等待他们的子历程停止或者停止,运行新的步伐,以及捕捉来自其他历程的信号。
4)最后在应用层,C步伐可以使用非本地跳转来规避正常的调用/返回栈规则,而且直接从一个函数分支到另一个函数。
同时还有四种不同类型的异常:停止,故障,停止和陷阱。
第7章 hello的存储管理
7.1 hello的存储器地点空间
逻辑地点:步伐经过编译后出如今汇编代码中的地点。逻辑地点用来指定一个操作数或者是一条指令的地点。是由一个段标识符加上一个指定段内相对地点的偏移量,表示为 [段标识符:段内偏移量]。
线性地点:也叫假造地点,和逻辑地点雷同,也是一个不真实的地点,如果逻辑地点是对应的硬件平台段式管理转换前地点的话,那么线性地点则对应了硬件也是内存的转换前地点。
假造地点:也就是线性地点。
物理地点:用于内存芯片级的单元寻址,与处置惩罚器和CPU链接的地点总线相对应。可以直接把物理地点明白成插在呆板上那根内存本身,把内存当作一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地点。
7.2 Intel逻辑地点到线性地点的变换-段式管理
段式内存管理方式就是直接将逻辑地点转换成物理地点,也就是CPU不支持分页机制。其地点的基本组成方式是段号+段内偏移地点。
在x86掩护模式下,段的信息即段描述符占8个字节,段信息无法直接存放在段寄存器中。Intel的计划是段描述符会合存放在GDT或LDT中,而段寄存器存放的是段描述符在GDT或LDT内的索引值。
起首给定一个完备的逻辑地点
1.看段选择描述符中的T1字段是0照旧1,可以知道当前要转换的是GDT中的段,照旧LDT中的段,再根据指定的相应的寄存器,得到其地点和大小,我们就有了一个数组了。
2.拿出段选择符中的前13位,可以在这个数组中查找到对应的段描述符,这样就有了Base,即基地点就知道了。
3.把基地点Base+Offset,就是要转换的下一个阶段的地点。
7.3 Hello的线性地点到物理地点的变换-页式管理
线性地点的表示方式是:前部分是假造页号后部分是假造页偏移。
CPU通过将逻辑地点转换为假造地点来访问主存,这个假造地点在访问主存前必须先转换成适当的物理地点。CPU芯片上叫做内存管理单元(MMU)的专用硬件,使用存放在主存中的查询表来动态翻译假造地点。然后CPU会通过这个物理地点来访问物理内存。
页表结构:在物理内存中存放着一个叫做页表的数据结构,页表将假造页映射到物理页,每次地点翻译硬件将一个假造地点转换为物理地点时,都会读取页表。
页表就是一个页表条目(PTE)数组,假造地点空间中的每个页在页表中的一个固定偏移量处都有一个PTE。PTE是由一个有用位和一个n个字段组成的。有用位表明了该假造页当前是否被缓存在DRAM中。如果设置了有用位,那么地点字段就表示DRAM中相应的物理页的起始位置。
MMU使用假造页号(VPN)来在假造页表中选择合适的PTE,当找到合适的PTE之后,PTE中的物理页号(PPN)和假造页偏移量(VPO)就会组合形成物理地点。此中VPO与PPO相同,由于假造页大小和物理页大小相同,所必要的偏移量位数也就相同。此时,物理地点就通过物理页号先找到对应的物理页,然后再根据物理页偏移找到详细的字节。
图36 页式管理
7.4 TLB与四级页表支持下的VA到PA的变换
在酷睿i7中,36位的假造地点被分割成4个9位的片。CR3寄存器包含L1页表的物理地点。VPN1有一个到L1 PTE的偏移量,找到这个PTE以后又会包含到L2页表的基础地点;VPN2包含一个到L2PTE的偏移量,找到这个PTE以后又会包含到L3页表的基础地点;VPN3包含一个到L3PTE的偏移量,找到这个PTE以后又会包含到L4页表的基础地点;VPN4包含一个到L4PTE的偏移量,找到这个PTE以后就是相应的PPN。
7.5 三级Cache支持下的物理内存访问
酷睿i7 MMU使用四级页表来将假造地点翻译成物理地点,得到了物理地点PA。如今分析三级cache支持下的物理内存访问。
L1 Cache是8路64组相联。块大小为64B。因此CO和CI都是6位,CT是40位。根据物理地点(PA),起首使用CI组索引,每组8路,分别匹配标记CT。如果匹配成功且块的有用位是1,则命中,根据块偏移CO返回数据。
如果没有匹配成功或者匹配成功但是标记位是1,则不命中,向下一级缓存中取出被哀求的块,然后将新的块存储在组索引指示的组中的一个高速缓存行中。一般而言,如果映射到的组内有空闲块,则直接放置,否则必须驱逐出一个现存的块,一般接纳最近最少被使用策略LRU进行更换。
7.6 hello历程fork时的内存映射
在用fork创建假造内存的时间,要履历以下步骤:a.创建当进步程的mm_struct,vm_area_struct和页表的原样副本。b.两个历程的每个页面都被标记为只读页面。c.两个历程的每个vm_area_struct都被标记为私有。
图37 fork内存映射
7.7 hello历程execve时的内存映射
exceve函数加载和实验步伐Hello,必要以下几个步骤:
a.删除已存在的用户区域。
b.映射私有区域。为Hello的代码、数据、bss和栈区域创建新的区域结构,所有这些区域都是私有的、写时复制的。
c.映射共享区域。比如Hello步伐与标准C库libc.so链接,这些对象都是动态链接到Hello的,然后再用户假造地点空间中的共享区域内。
d.设置步伐计数器(PC)。exceve做的最后一件事就是设置当进步程的上下文中。
7.8 缺页故障与缺页停止处置惩罚
缺页故障:当指令引用一个相应的假造地点,而与改地点相应的物理页面不再内存中,会触发缺页故障。
缺页停止处置惩罚:通过查询页表PTE可以知道假造页在磁盘的位置。缺页处置惩罚步伐从指定的位置加载页面 到物理内存中,并更新PTE。然后控制返回给引起缺页故障的指令。当指令再次实验时,相应的物理页面已经驻留在内存中,因此指令可以没有故障的运行完成。
7.9动态存储分配管理
基本方法:维护一个假造内存区域“堆”,将堆视为一组不同大小的块的聚集来维护,每个块要么是已分配的,要么是空闲的,必要时选择一个合适的内存块进行分配。
a.记载空闲块,可以选择隐式空闲链表,显示空闲链表,分离的空闲链表和按块大小排序创建平衡树。
b.放置策略,可以选择初次适配,下一次适配,最佳适配。
c.合并策略,可以选择立即合并,耽误合并。
d.必要思量分割空闲块的时机,对内部碎片的忍耐阈值。
7.10本章小结
a.假造内存是对主存的一个抽象。支持假造内存的处置惩罚器通过使用一种叫做假造内存寻址的间接形式来引用主存。处置惩罚器产生一个假造地点,在被发送到主存之前,这个地点被翻译成一个物理地点。从假造地点空间到物理地点空间的地点翻译要求硬件和软件紧密合作。专门的硬件使用页表来翻译假造地点,而页表的内容是由操作系统提供的。
b.假造内存提供三个功能:简化了内存掩护;简化了内存管理;在主存中主动缓存最近使用的存放在磁盘上的假造地点空间的内容。
c.地点翻译的过程必须和系统中的所有的硬件缓存的操作集成在一起。
d.内存映射为共享数据、创建历程以及加载步伐提供了一种高效的机制。
e.动态内存分配器直接操作内存,无需类型系统的许多帮助。
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
所有的I/O设备(比方网络、磁盘和终端)都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来实验,这种将设备优雅地映射为文件的方式,允许Linux内核引出一个简单低级的应用接口,称为Unix I/O。
设备的模型化:文件
文件的类型:
平凡文件:包含任意数据的文件。
目次:包含一组链接的文件,每个链接都将一个文件名映射到一个文件(他还有另一个名字叫做“文件夹”)。
套接字:用来与另一个历程进行跨网络通信的文件
命名通道
符号链接
字符和块设备
设备管理:unix io接口
打开和关闭文件
读取和写入文件
改变当前文件的位置
8.2 简述Unix IO接口及其函数
a.Unix IO接口:
打开文件:一个应用步伐通过要求内核打开相应的文件,宣告它想要访问一个I/O设备。内核返回一个小的非负整数,叫做描述符。它在后续对此文件的所有操作中标识这个文件。内核记载有关这个打开文件的所有信息。应用步伐只需记取这个描述符。
shell创建的每个历程开始时都有三个打开的文件:标准输入、标准输出和标准错误。
改变当前的文件位置:对于每个打开的文件,内核保持着一个文件的位置k,初始为0,这个文件的位置是从文件开头起始的字符偏移量。应用步伐能够通过实验seek操作,将文件的当前位置设置为k。
读写文件:读操作就是从文件中复制n>0个字节到内存中,从当前文件位置k开始,然后将k增加到k+n。而写操作就是从内存复制字节到文件中。
关闭文件:当应用完成了对文件的访问后,它就通知内核关闭这个文件。作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。无论一个历程由于何种原因停止时,内核都会关闭所有打开的文件并释放它们的内存资源。
b.Unix IO函数:
open 函数:调要open函数可以打开或创建一个文件。
create函数:创建一个文件,也可通过以特定参数使用open来实现。
close函数:读文件进行关闭。
Iseek函数:为一个打开的文件设置其偏移量。
read函数:从打开的文件中读数据到buf。
write函数:写入文件。
pread,prwrite函数:主要用于办理文件共享问题。
dup函数
syns函数:用于办理耽误写问题,包管磁盘上现实文件系统和缓冲区高速缓存中内容的一致性。
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;
}
调用了两个函数vsprintf,write。
vsprintf函数的作用是将所有的参数内容格式化之后存入buf,然后返回格式化数组的长度。
write函数是将buf中的i个元素写到终端的函数。
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.
字符显示驱动子步伐:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
int getchar(void)
{
static char buf[BUFSIZ];
static char *bb = buf;
static int n = 0;
if(n == 0)
{
n = read(0, buf, BUFSIZ);
bb = buf;
}
return(–n >= 0)?(unsigned char) *bb++ : EOF;
}
getchar函数调用read函数,将整个缓冲区都读到buf里,并将缓冲区的长度赋值给n。返回时返回buf的第一个元素,除非n<0。
异步异常-键盘停止的处置惩罚:键盘停止处置惩罚子步伐。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
本章主要先容了Linux的IO设备管理方法、Unix IO接口及其函数,分析了printf和getchar函数的实现。
结论
C语言编写hello.c;
预处置惩罚hello.c,得到hello.i;
编译hello.i成为汇编文件hello.s;
汇编hello.s,将其变为可重定位目标文件hello.o;
链接,将hello.o与可重定位目标文件和动态链接库链接成为可实验步伐hello
运行hello,在shell中输入./hello 1190201214 zzq
shell调用fork创建子历程
shell调用execve,映射假造内存
进入步伐,载入物理内存,进入main函数
实验指令:CPU为其分配时间片,在一个时间片中,hello享有CPU资源,顺序实验自己的控制逻辑流
访问内存:MMU将步伐中使用的假造内存地点通过页表映射成物理地点。
动态申请内存:printf会调用malloc向动态内存分配器申请堆中的内存。
信号:运行途中键入不同指令,做出不同反应。
结束:shell父历程接纳子历程,内核删除为这个历程创建的所有数据结构。
附件
hello.c:源步伐
hello.i:预处置惩罚后的文本文件
hello.s:编译后的汇编文件
hello.o:汇编后的可重定位目标文件
hello2.txt:hello得到的反汇编文件
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.
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) |
Powered by Discuz! X3.4 |