首页 计算机系统基础第七章异常控制流

计算机系统基础第七章异常控制流

举报
开通vip

计算机系统基础第七章异常控制流第七章异常控制流CPU控制流的概念进程上下文切换异常和中断的基本概念异常和中断的响应和处理异常控制流 主要教学目标 使学生了解程序执行过程中正常的控制流和异常控制流的区别 了解在较低层次上如何实现异常控制流 初步理解硬件如何和操作系统协调工作,从而为将来理解和掌握操作系统核心内容打下良好基础。 主要教学内容 CPU控制流、异常控制流 进程和进程上下文切换 异常和中断的基本概念 异常和中断的响应和处理异常控制流 分以下两个部分介绍 第一讲:进程与进程的上下文切换 CPU的控制流、异常控制流 程序和进程、引入进程的好处...

计算机系统基础第七章异常控制流
第七章异常控制流CPU控制流的概念进程上下文切换异常和中断的基本概念异常和中断的响应和处理异常控制流 主要教学目标 使学生了解程序执行过程中正常的控制流和异常控制流的区别 了解在较低层次上如何实现异常控制流 初步理解硬件如何和操作系统协调工作,从而为将来理解和掌握操作系统核心内容打下良好基础。 主要教学内容 CPU控制流、异常控制流 进程和进程上下文切换 异常和中断的基本概念 异常和中断的响应和处理异常控制流 分以下两个部分介绍 第一讲:进程与进程的上下文切换 CPU的控制流、异常控制流 程序和进程、引入进程的好处 逻辑控制流和物理控制流 进程与进程的上下文切换 程序的加载和运行 第二讲:异常和中断 异常和中断的基本概念 异常和中断的响应、处理 IA-32/Linux下的异常/中断机制回顾:程序的机器级表示与执行intsum(inta[],unsignedlen){inti,sum=0;for(i=0;i<=len–1;i++) sum+=a[i];returnsum;}sum:….L3:…movl-4(%ebp),%eaxmovl12(%ebp),%edxsubl$1,%edxcmpl%edx,%eaxjbe .L3…程序的正常执行顺序有哪两种?(1)按顺序取下一条指令执行(2)通过CALL/RET/Jcc/JMP等指令跳转到转移目标地址处执行CPU所执行的指令的地址序列称为CPU的控制流,通过上述两种方式得到的控制流为正常控制流。程序始终按正常控制流执行吗?异常控制流 CPU会因为遇到内部异常或外部中断等原因而打断程序的正常控制流,转去执行操作系统提供的针对这些特殊事件的处理程序。 由于某些特殊情况引起用户程序的正常执行被打断所形成的意外控制流称为异常控制流(ExceptionalControlofFlow,ECF)。 异常控制流的形成原因: 内部异常(缺页、越权、越级、整除0、溢出等) 外部中断(Ctrl-C、打印缺纸、DMA结束等) 进程的上下文切换(发生在操作系统层) 一个进程直接发送信号给另一个进程(发生在应用软件层)本章主要介绍发生在OS层和硬件层的异常控制流“程序”和“进程” 进程是OS对CPU执行的程序的运行过程的一种抽象。进程有自己的生命周期,它由于任务的启动而创建,随着任务的完成(或终止)而消亡,它所占用的资源也随着进程的终止而释放。 一个可执行目标文件(即程序)可被加载执行多次,也即,一个程序可能对应多个不同的进程。 例如,用word程序编辑一个文档时,相应的用户进程就是winword.exe,如果多次启动同一个word程序,就得到多个winword.exe进程,处理不同的数据。程序(program)指按某种方式组合形成的代码和数据集合,代码即是机器指令序列,因而程序是一种静态概念。进程(process)指程序的一次运行过程。更确切说,进程是具有独立功能的一个程序关于某个数据集合的一次运行活动,因而进程具有动态含义。同一个程序处理不同的数据就是不同的进程进程的概念 操作系统(管理任务)以外的都属于“用户”的任务。 计算机处理的所有“用户”的任务由进程完成。 为强调进程完成的是用户的任务,通常将进程称为用户进程。 计算机系统中的任务通常就是指进程。例如, Linux内核中通常把进程称为任务,每个进程主要通过一个称为进程描述符(processdescriptor)的结构来描述,其结构类型定义为task_struct,包含了一个进程的所有信息。 所有进程通过一个双向循环链表实现的任务列表(tasklist)来描述,任务列表中每个元素是一个进程描述符。 IA-32中的任务状态段(TSS)、任务门(taskgate)等概念中所称的任务,实际上也是指进程。回顾:Linux将虚存空间组织成“区域”的集合pgd:全局页目录地址vm_prot:访问权限vm_flags:共享/本进程私有task_struct是某个进程(即任务)所有相关信息的描述结构(称进程描述符),其中mm是其虚拟空间的描述结构引入“进程”的好处 “进程”的引入为应用程序提供了以下两方面的抽象: 一个独立的逻辑控制流 每个进程拥有一个独立的逻辑控制流,使得程序员以为自己的程序在执行过程中独占使用处理器 一个私有的虚拟地址空间 每个进程拥有一个私有的虚拟地址空间,使得程序员以为自己的程序在执行过程中独占使用存储器 进程”的引入简化了程序员的编程以及语言处理系统的处理,即简化了编程、编译、链接、共享和加载等整个过程。逻辑控制流t0t1t2t3t4t5t6WordWordIEt7t8对于确定的数据集,某进程指令执行地址序列是确定的。称为进程的逻辑控制流。对于单处理器系统,进程会轮流使用处理器,即处理器的物理控制流由多个逻辑控制流组成。p1的逻辑控制流为A11~A13、A11~A14、A15~A16。在A12处被打断一次!逻辑控制流不会因被其他进程打断而改变,还能回到原被打断的“断点”处继续执行。进程p2的逻辑控制流为A21~A22、A23~A25。在A24处被打断一次!P3未被打断不同进程的逻辑控制流在时间上交错或重叠的情况称为并发(concurrency)P1和P2、P2和P3是并发执行;P1和P3不是并发执行!复习:Hello程序的数据流动过程Hello可执行文件Red:shell命令行处理Blue:可执行文件加载Cyan:hello程序执行过程“hello”“hello,world/n”“hello,world/n”问题:hello程序何时被装?谁来装入?被谁启动?每次是否被装到相同的地方?hello程序是否知道还有其他程序同时运行?这些问题是本章要回答的!Unix>./hellohello,worldUnix>“进程”与“上下文切换”$./hellohello,world$“$”是shell命令行提示符,说明正在运行shell进程。在一个进程的生命周期中,可能会有其他不同进程在处理器上交替运行!感觉到的运行时间比真实执行时间要长!OS通过处理器调度让处理器轮流执行多个进程。实现不同进程中指令交替执行的机制称为进程的上下文切换(contextswitching)处理器调度等事件会引起用户进程正常执行被打断,因而形成异常控制流。进程的上下文切换机制很好地解决了这类异常控制流,实现了从一个进程安全切换到另一个进程执行的过程。“进程”的“上下文” 进程的物理实体(代码和数据等)和支持进程运行的环境合称为进程的上下文。 由进程的程序块、数据块、运行时的堆和用户栈(两者通称为用户堆栈)等组成的用户空间信息被称为用户级上下文; 由进程标识信息、进程现场信息、进程控制信息和系统内核栈等组成的内核空间信息被称为系统级上下文; 处理器中各寄存器的内容被称为寄存器上下文(也称硬件上下文),即进程的现场信息。 在进行进程上下文切换时,操作系统把换下进程的寄存器上下文保存到系统级上下文中的现场信息位置。 用户级上下文地址空间和系统级上下文地址空间一起构成了一个进程的整个存储器映像进程的存储器映像 IA-32/Linux平台下,每个(用户)进程具有独立的私有地址空间(虚拟地址空间) 每个进程的地址空间划分(即存储映像)布局相同(如右图)进程的地址空间用户级上下文回顾:用户模式和内核模式 为了使OS能够起到管理程序执行的目的,在一些时候处理器中必须运行内核代码 为了区分处理器运行的是用户代码还是内核代码,必须有一个状态位来标识,这个状态位称为模式位 处理器模式分用户模式(用户态)和内核模式(核心态) 用户模式(也称目态、用户态)下,处理器运行用户进程,此时不允许使用特权指令 内核模式(有时称系统模式、管理模式、超级用户模式、管态、内核态、核心态)下处理器运行内核代码,允许使用特权指令,例如:停机指令、开/关中断指令、Cache冲刷指令等。回顾:程序的加载和运行 UNIX/Linux系统中,可通过调用execve()函数来启动加载器。 execve()函数的功能是在当前进程上下文中加载并运行一个新程序。execve()函数的用法如下: intexecve(char*filename,char*argv[],*envp[]); filename是加载并运行的可执行文件名(如./hello),可带参数列表argv和环境变量列表envp。若错误(如找不到指定文件filename),则返回-1,并将控制权交给调用程序;若函数执行成功,则不返回,最终将控制权传递到可执行目标中的主函数main。 主函数main()的原型形式如下: intmain(intargc,char**argv,char**envp);或者: intmain(intargc,char*argv[],char*envp[]); argc指定参数个数,参数列表中第一个总是命令名(可执行文件名) 例如:命令行为“ld-otestmain.otest.o”时,argc=5回顾:程序的加载和运行Unix>ld-otestmain.otest.o若在shell命令行提示符下输入以下命令行ld是可执行文件名(即命令名),随后是命令的若干参数,argv是一个以null结尾的指针数组,argc=5在shell命令行提示符后键入命令并按“enter”键后,便构造argv和envp,然后调用execve()函数来启动加载器,最终转main()函数执行intexecve(char*filename,char*argv[],*envp[]);intmain(intargc,char*argv[],char*envp[]);回顾:程序的加载和运行问题:hello程序的加载和运行过程是怎样的?Step1:在shell命令行提示符后输入命令:$./hello[enter]Step2:shell命令行解释器构造argv和envpStep3:调用fork()函数,创建一个子进程,与父进程shell完全相同(只读/共享),包括只读代码段、可读写数据段、堆以及用户栈等。Step4:调用execve()函数,在当前进程(新创建的子进程)的上下文中加载并运行hello程序。将hello中的.text节、.data节、.bss节等内容加载到当前进程的虚拟地址空间(仅修改当前进程上下文中关于存储映像的一些数据结构,不从磁盘拷贝代码和数据等内容)Step5:调用hello程序的main()函数,hello程序开始在一个进程的上下文中运行。intmain(intargc,char*argv[],char*envp[]);回顾:可执行文件的加载 通过调用execve系统调用函数来调用加载器 加载器(loader)根据可执行文件的程序(段)头表中的信息,将可执行文件的代码和数据从磁盘“拷贝”到存储器中(实际上不会真正拷贝,仅建立一种映像,这涉及到许多复杂的过程和一些重要概念,将在后续课上学习) 加载后,将PC(EIP)设定指向Entrypoint(即符号_start处),最终执行main函数,以启动程序执行。程序被启动如$./P调用fork()以构造的argv和envp为参数调用execve()execve()调用加载器进行可执行文件加载,并最终转去执行main__libc_init_first_initatexitmain_exit_start:ELF文件信息举例$readelf-hmainELFHeader:Magic:7f454c46010101000000000000000000Class:ELF32Data:2'scomplement,littleendianVersion:1(current)OS/ABI:UNIX-SystemVABIVersion:0Type:EXEC(Executablefile)Machine:Intel80386Version:0x1Entrypointaddress:x8048580Startofprogramheaders:52(bytesintofile)Startofsectionheaders:3232(bytesintofile)Flags:0x0Sizeofthisheader:52(bytes)Sizeofprogramheaders:32(bytes)Numberofprogramheaders:8Sizeofsectionheaders:40(bytes)Numberofsectionheaders:29Sectionheaderstringtableindex:26可执行目标文件的ELF头程序加载和运行fork、execve等OS内核代码当IA-32/Linux系统开始执行main()函数时,在虚拟地址空间的用户栈中的结构如右图所示intmain(intargc,char*argv[],char*envp[]);shell命令行解释器异常控制流 分以下两个部分介绍 第一讲:进程与进程的上下文切换 CPU的控制流、异常控制流 程序和进程、引入进程的好处 逻辑控制流和物理控制流 进程与进程的上下文切换 程序的加载和运行 第二讲:异常和中断 异常和中断的基本概念 异常和中断的响应、处理 IA-32/Linux下的异常/中断机制异常和中断 程序执行过程中CPU会遇到一些特殊情况,使正在执行的程序被“中断” CPU中止原来正在执行的程序,转到处理异常情况或特殊事件的程序去执行,结束后再返回到原被中止的程序处(断点)继续执行。 程序执行被“中断”的事件(在硬件层面)有两类 内部“异常”:在CPU内部发生的意外事件或特殊事件 按发生原因分为硬故障中断和程序性中断两类 硬故障中断:如电源掉电、硬件线路故障等 程序性中断:执行某条指令时发生的“例外(Exception)”事件,如溢出、缺页、越界、越权、越级、非法指令、除数为0、堆/栈溢出、访问超时、断点设置、单步、系统调用等 外部“中断”:在CPU外部发生的特殊事件,通过“中断请求”信号向CPU请求处理。如实时钟、控制台、打印机缺纸、外设准备好、采样计时到、DMA传输结束等。一种情况:上课时由于机器死机( ppt 关于艾滋病ppt课件精益管理ppt下载地图下载ppt可编辑假如ppt教学课件下载triz基础知识ppt 不能放)或屏幕保护(黑屏)等,使上课不能再正常继续下去----“内部异常”另一种情况:上课时突然有紧急事情需要上课老师出去处理一下,回头继续上课----“外部中断”打铃下课是“内部异常”还是“外部中断”?回顾:逻辑地址向线性地址转换举例 已知变量y和数组a都是int型,a的首地址为0x8048a00。假设编译器将a的首地址分配在ECX中,数组的下标变量i分配在EDX中,y分配在EAX中,C语言赋值语句“y=a[i];”被编译为指令“movl(%ecx,%edx,4),%eax”。若在IA-32/Linux环境下执行指令地址为0x80483c8的该指令时,CS段寄存器对应的描述符cache中存放的是表6.2中所示的用户代码段信息且CPL=3,DS段寄存器对应的描述符cache中存放的是表6.2中所示的用户数据段信息,则当i=100时,取指令操作过程中MMU得到的指令的线性地址是多少?取数操作过程中MMU得到的操作数的线性地址是多少?intfunc(inta[],intc){ inti,y=0; for(i=0;i<c;i++){ y=a[i];……} ……}80483c8:movl(%ecx,%edx,4),%eax代码和数据段DPL都为3,即CPL最低应为3,而CPL=3,故访问未越级指令的线性地址:代码段基地址+EA=0+0x80483c8=0x80483c8操作数的线性地址:数据段基地址+EA=0+R[ecx]+R[edx]×4=0x8048a00+100×4=0x8048b90异常和中断的处理 发生异常(exception)和中断(interrupt)事件后,系统将进入OS内核态对相应事件进行处理,即改变处理器状态(用户态→内核态)用户进程OS响应异常/中断具体的异常或中断处理 返回当前指令 返回下条指令 终止(abort)事件当前指令下条指令中断或异常处理执行的代码不是一个进程,而是“内核控制路径”,它代表异常或中断发生时正在运行的当前进程在内核态执行一个独立的指令序列。内核控制路径比进程更“轻”,其上下文信息比进程上下文信息少得多。而上下文切换后CPU执行的是另一个用户进程。用户进程的正常控制流中插入了一段内核控制路径回顾:“进程”与“上下文切换”$./hellohello,world$“$”是shell命令行提示符,说明正在运行shell进程。上下文切换后,是另一个用户进程!OS通过处理器调度让处理器轮流执行多个进程。实现不同进程中指令交替执行的机制称为进程的上下文切换(contextswitching)处理器调度等事件会引起用户进程正常执行被打断,因而形成异常控制流。进程的上下文切换机制很好地解决了这类异常控制流,实现了从一个进程安全切换到另一个进程执行的过程。fork、execve等OS内核代码shell命令行解释器异常的分类“异常”按处理方式分为故障、自陷和终止三类故障(fault):执行指令引起的异常事件,如溢出、非法指令、缺页、访问越权等。自陷(Trap):预先安排的事件(“埋地雷”),如单步跟踪、断点、系统调用(执行访管指令)等。是一种自愿中断。 终止(Abort):硬故障事件,此时机器将“终止”,调出中断服务程序来重启操作系统。“断点”:异常处理结束后回到原来被“中断”的程序执行时的起始指令。思考2:哪些故障补救后可继续执行,哪些只好终止当前进程?缺页、TLB缺失等:补救后可继续,回到发生故障的指令重新执行。溢出、除数为0、非法指令、内存保护错等:终止当前进程。回到下条指令“断点”为发生故障指令的地址“断点”为自陷指令下条指令地址“断点”是什么?随便!思考1:自陷处理完成后回到哪条指令执行?异常举例—页故障 以下几种情况都会发生“页故障” 缺页:页表项有效位为0 地址越界:地址大于最大界限 访问越级或越权(保护违例): 越级:用户进程访问内核数据(CPL=3/DPL=0) 越权:读写权限不相符(如对只读段进行了写操作)“页故障”事件何时发现?如何发现?执行每条指令都要访存(取指令、取操作数、存结果)在保护模式下,每次访存都要进行逻辑地址向物理地址转换在地址转换过程中会发现是否发生了“页故障”!“页故障”事件是软件发现的还是硬件发现的?逻辑地址向物理地址的转换由硬件(MMU)实现,故“页故障”事件由硬件发现。所有异常和中断事件都由硬件检测发现!异常举例—页故障假设在IA-32/linux系统中一个C语言源程序P如下:1 inta[1000];2 intx;3 main()4 {5 a[10]=1;6 a[1000]=3;7 a[10000]=4;8 }假设编译、汇编和链接后,第5、6和7行源代码对应的指令序列如下:58048300:c7052890040801000000movl$0x1,0x804902868048309:c705a09f040803000000movl$0x3,0x8049fa078048313:c705402c050804000000movl$0x4,0x8052c40已知页大小为4KB,若在运行P对应的进程时,系统中无其他进程在运行,则:(1)对于上述三条指令的执行,在取指令时是否可能发生页故障?(2)在数据访问时分别会发生什么问题?(3)哪些问题是可恢复的?哪些问题是不可恢复的?正常的控制流为…、0x8048300、0x8048309、0x8048313、…可能的异常控制流是什么?异常举例—页故障三条指令在读指令时都不会发生缺页,Why?它们都位于起始地址为0x08048000(是一个4KB页面的起始位置)的同一个页面,执行这三条指令之前,该页已经调入内存。因为没有其他进程在系统中运行,所以不会因为执行其他进程而使得调入主存的页面被调出到磁盘。因而都不会在取指令时发生页故障。假设在IA-32/linux系统中一个C语言源程序P如下:1 inta[1000];2 intx;3 main()4 {5 a[10]=1;6 a[1000]=3;7 a[10000]=4;8 }假设编译、汇编和链接后,第5、6和7行源代码对应的指令序列如下:58048300:c7052890040801000000movl$0x1,0x804902868048309:c705a09f040803000000movl$0x3,0x8049fa078048313:c705402c050804000000movl$0x4,0x8052c40已知页大小为4KB,若在运行P对应的进程时,系统中无其他进程在运行,则:(1)对于上述三条指令的执行,在取指令时是否可能发生页故障?(2)在数据访问时分别会发生什么问题?(3)哪些问题是可恢复的?哪些问题是不可恢复的?异常举例—页故障第5行指令数据访问时是否发生页故障,Why?对a[10](地址0x8049028)的访问是对所在页面(首址为0x08049000)的第一次访问,故不在主存,缺页处理结束后,再回到这条movl指令重新执行,再访问数据就没有问题了。假设在IA-32/linux系统中一个C语言源程序P如下:1 inta[1000];2 intx;3 main()4 {5 a[10]=1;6 a[1000]=3;7 a[10000]=4;8 }假设编译、汇编和链接后,第5、6和7行源代码对应的指令序列如下:58048300:c7052890040801000000movl$0x1,0x804902868048309:c705a09f040803000000movl$0x3,0x8049fa078048313:c705402c050804000000movl$0x4,0x8052c40已知页大小为4KB,若在运行P对应的进程时,系统中无其他进程在运行,则:(1)对于上述三条指令的执行,在取指令时是否可能发生页故障?(2)在数据访问时分别会发生什么问题?(3)哪些问题是可恢复的?哪些问题是不可恢复的?异常举例—页故障假设在IA-32/linux系统中一个C语言源程序P如下:1 inta[1000];2 intx;3 main()4 {5 a[10]=1;6 a[1000]=3;7 a[10000]=4;8 }假设编译、汇编和链接后,第5、6和7行源代码对应的指令序列如下:58048300:c7052890040801000000movl$0x1,0x804902868048309:c705a09f040803000000movl$0x3,0x8049fa078048313:c705402c050804000000movl$0x4,0x8052c40已知页大小为4KB,若在运行P对应的进程时,系统中无其他进程在运行,则:(1)对于上述三条指令的执行,在取指令时是否可能发生页故障?(2)在数据访问时分别会发生什么问题?(3)哪些问题是可恢复的?哪些问题是不可恢复的?第6行指令数据访问时是否发生页故障,Why?对a[1000](地址0x8049fa0)的访问是对所在页面(首址为0x08049000)的第2次访问,故在主存,不会发生缺页。但a[1000]实际不存在,只不过编译器未检查数组边界,0x8049fa0处可能是x的地址,故该指令执行结果可能是x被赋值为3异常举例—页故障假设在IA-32/linux系统中一个C语言源程序P如下:1 inta[1000];2 intx;3 main()4 {5 a[10]=1;6 a[1000]=3;7 a[10000]=4;8 }假设编译、汇编和链接后,第5、6和7行源代码对应的指令序列如下:58048300:c7052890040801000000movl$0x1,0x804902868048309:c705a09f040803000000movl$0x3,0x8049fa078048313:c705402c050804000000movl$0x4,0x8052c40已知页大小为4KB,若在运行P对应的进程时,系统中无其他进程在运行,则:(1)对于上述三条指令的执行,在取指令时是否可能发生页故障?(2)在数据访问时分别会发生什么问题?(3)哪些问题是可恢复的?哪些问题是不可恢复的?第7行指令数据访问时是否发生页故障,Why?地址0x8052c40偏离数组首址0x8049000已达4×10000+4=40004个单元,即偏离了9个页面,很可能超出可读写区范围,故执行该指令时可能会发生保护违例。页故障处理程序发送一个“段错误”信号(SIGSEGV)给用户进程,用户进程接受到该信号后就调出一个信号处理程序执行,该信号处理程序根据信号类型,在屏幕上显示“段故障(segmentationfault)”信息,并终止用户进程。异常的分类“异常”按处理方式分为故障、自陷和终止三类故障(fault):执行指令引起的异常事件,如溢出、缺页、堆栈溢出、访问超时等。自陷(Trap):预先安排的事件(“埋地雷”),如单步跟踪、断点、系统调用(执行访管指令)等。是一种自愿中断。 终止(Abort):硬故障事件,此时机器将“终止”,调出中断服务程序来重启操作系统。 不同体系结构和教科书对“异常”和“中断”定义的内涵不同,在看书时要注意!思考2:哪些故障补救后可继续执行,哪些只好终止当前进程?缺页、TLB缺失等:补救后可继续,回到发生故障的指令重新执行。溢出、除数为0、非法操作、内存保护错等:终止当前进程。回到下条指令“断点”为发生故障指令的地址“断点”为自陷指令下条指令地址“断点”是什么?随便!思考1:自陷处理完成后回到哪条指令执行?陷阱(Trap)异常 陷阱也称自陷或陷入,执行陷阱指令(自陷指令)时,CPU调出特定程序进行相应处理,处理结束后返回到陷阱指令下一条指令执行。用户进程OS陷入OS内核具体的陷阱处理(如系统调用) 返回下条指令事件陷阱指令下条指令 陷阱的作用之一是在用户和内核之间提供一个像过程一样的接口,这个接口称为系统调用,用户程序利用这个接口可方便地使用操作系统内核提供的一些服务。操作系统给每个服务编一个号,称为系统调用号。例如,Linux系统调用fork、read和execve的调用号分别是1、3和11。 IA-32处理器中的int指令和sysenter指令、MIPS处理器中的syscall指令等都属于陷阱指令(相当于“地雷”)。 陷阱指令异常称为编程异常(programmedexception),这些指令包括INTn、int3、into(溢出检查)、bound(地址越界检查)等有条件“爆炸”Trap举例:OpeningFile 用户程序中调用函数open(filename,options) open函数执行陷阱指令(即系统调用指令“int”)0804d070<__libc_open>:...804d082: cd80int$0x80804d084: 5b pop%ebx...UserProcessOS陷入OS文件打开操作返回到pop指令执行int$0x80pop%ebxOpen系统调用(systemcall):OSmustfindorcreatefile,getitreadyforreadingorwriting,Returnsintegerfiledescriptor通过执行“int$0x80”指令,调出OS完成一个具体的“服务”(称为系统调用)这种“地雷”一定“爆炸”陷阱(Trap)异常 利用陷阱机制可实现程序调试功能,包括设置断点和单步跟踪 IA-32中,当CPU处于单步跟踪状态(TF=1且IF=1)时,每条指令都被设置成了陷阱指令,执行每条指令后,都会发生中断类型号为1的“调试”异常,从而转去执行“单步跟踪处理程序”。注意:当陷阱指令是转移指令时,不能返回到转移指令的下条指令执行,而是返回到转移目标指令执行。(在一定的条件下,每条指令都变成“地雷”) IA-32中,用于程序调试的“断点设置”陷阱指令为int3,对应机器码为CCH。若调试程序在被调试程序某处设置了断点,则调试程序就在该处“加”一条int3指令(该首字节)。执行到该指令时,会暂停被调试程序的运行,并发出“EXCEPTION_BREAKPOINT”异常,以调出调试程序执行,执行结束后回到被调试程序执行。(int3是一定爆炸的“地雷”)问题:你用过单步跟踪、断点设置等调试功能吗?你知道这些功能是如何实现的吗?通过“埋地雷”的方式实现IA-32的标志寄存器 6个条件标志 OF、SF、ZF、CF各是什么标志(条件码)? AF:辅助进位标志(BCD码运算时才有意义) PF:奇偶标志 3个控制标志 DF(DirectionFlag):方向标志(自动变址方向是增还是减) IF(InterruptFlag):中断允许标志(仅对外部可屏蔽中断有用) TF(TrapFlag):陷阱标志(是否是单步跟踪状态) ……异常的分类“异常”按处理方式分为故障、自陷和终止三类故障(fault):执行指令引起的异常事件,如溢出、缺页、堆栈溢出、访问超时等。自陷(Trap):预先安排的事件(“埋地雷”),如单步跟踪、断点、系统调用(执行访管指令)等。是一种自愿中断。 终止(Abort):硬故障事件,此时机器将“终止”,调出中断服务程序来重启操作系统。 不同体系结构和教科书对“异常”和“中断”定义的内涵不同,在看书时要注意!思考2:哪些故障补救后可继续执行,哪些只好终止当前进程?缺页、TLB缺失等:补救后可继续,回到发生故障的指令重新执行。溢出、除数为0、非法操作、内存保护错等:终止当前进程。回到下条指令“断点”为发生故障指令的地址“断点”为自陷指令下条指令地址“断点”是什么?随便!思考1:自陷处理完成后回到哪条指令执行?终止(Abort)异常 如果在执行指令过程中发生了严重错误,例如,控制器出现问题,访问DRAM或SRAM时发生校验错等,则程序将无法继续执行,只好终止发生问题的进程,在有些严重的情况下,甚至要重启系统。 这种异常是随机发生的,无法确定发生异常的是哪条指令。0xc00000096为出错ID中断的概念 外设通过中断请求信号线向CPU提出“中断”请求,不由指令引起,故中断也称为异步异常。 事件:Ctrl-C、DMA传送结束、网络数据到达、打印缺纸、…… 每执行完一条指令,CPU就查看中断请求引脚,若引脚的信号有效,则进行中断响应:将当前PC(断点)和当前机器状态保存到栈中,并“关中断”,然后,从数据总线读取中断类型号,根据中断类型号跳转到对应的中断服务程序执行。中断检测及响应过程由硬件完成。 中断服务程序执行具体的中断处理工作,中断处理完成后,再回到被打断程序的“断点”处继续执行。溢出、整除0、缺页等异常和外部中断都是由硬件检测并响应的!断点是什么?中断的分类 Intel将中断分成可屏蔽中断(maskableinterrupt)和不可屏蔽中断(nonmaskableinterrupt,NMI)。 可屏蔽中断:通过INTR向CPU请求,可通过设置屏蔽字来屏蔽请求,若中断请求被屏蔽,则不会被送到CPU。 不可屏蔽中断:非常紧急的硬件故障,如:电源掉电,硬件线路故障等。通过NMI向CPU请求。一旦产生,就被立即送CPU,以便快速处理。这种情况下,中断服务程序会尽快保存系统重要信息,然后在屏幕上显示相应的消息或直接重启系统。CPU中断控制器NMIINTR异常/中断响应过程检测到异常或中断时,CPU须进行以下基本处理:①关中断(“中断允许位”清0):使CPU处于“禁止中断”状态,以防止新中断破坏断点(PC)、程序状态(PSW)和现场(通用寄存器)。②保护断点和程序状态:将断点和程序状态保存到栈或特殊寄存器中PC→栈或EPC(专门存放断点的寄存器)PSWR→栈或EPSWR(专门保存程序状态的寄存器)PSW(ProgramStatusWord):程序状态字PSWR(PSW寄存器):如IA-32中的的EFLAGS寄存器③识别中断事件有软件识别和硬件识别(向量中断)两种不同的方式。IA-32中,响应异常时不关中断,只在响应中断时关中断异常/中断响应过程有两种不同的识别方式:软件识别和硬件识别(向量中断)。(1)软件识别(MIPS采用)设置一个异常状态寄存器(MIPS中为Cause寄存器),用于 记录 混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载 异常原因。操作系统使用一个统一的异常处理程序,该程序按优先级顺序查询异常状态寄存器,识别出异常事件。(例如:MIPS中位于内核地址0x80000180处有一个专门的异常处理程序,用于检测异常的具体原因,然后转到内核中相应的异常处理程序段中进行具体的处理)(2)硬件识别(向量中断)(IA-32采用)用专门的硬件查询电路按优先级顺序识别异常,得到“中断类型号”,根据此号,到中断向量表中读取对应的中断服务程序的入口地址。所有事件都被分配一个“中断类型号”,每个中断都有相应的“中断服务程序”,可根据中断类型号找到中断服务程序的入口地址。中断类型号相当于中断向量表的索引,表中存放中断服务程序首地址IA-32的向量中断方式 有256种不同类型的异常和中断 每个异常和中断都有唯一编号,称之为中断类型号(也称向量号)。如类型0为“除法错”,类型2为“NMI中断”,类型14为“缺页” 每个异常和中断有与其对应的异常处理程序或中断服务程序,其入口地址放在一个专门的中断向量表或中断描述符表中。 前32个类型(0~31)保留给CPU使用,剩余的由用户自行定义(这里的用户指机器硬件的用户,即操作系统) 通过执行INTn(指令第二字节给出中断类型号n,n=32~255)使CPU自动转到OS给出的中断服务程序执行 实模式下,用中断向量表描述 保护模式下,用中断描述符表描述回顾:中断的分类 Intel将中断分成可屏蔽中断(maskableinterrupt)和不可屏蔽中断(nonmaskableinterrupt,NMI)。 可屏蔽中断:通过INTR向CPU请求,可通过设置屏蔽字来屏蔽请求,若中断请求被屏蔽,则不会被送到CPU。 不可屏蔽中断:非常紧急的硬件故障,如:电源掉电,硬件线路故障等。通过NMI向CPU请求。一旦产生,就被立即送CPU,以便快速处理。这种情况下,中断服务程序会尽快保存系统重要信息,然后在屏幕上显示相应的消息或直接重启系统。CPU中断控制器NMIINTRIA-32的中断类型 用户自定义类型号为32~255,部分用于可屏蔽中断,部分用于软中断 可屏蔽中断通过CPU的INTR引脚向CPU发出中断请求 软中断指令INTn被设定为一种陷阱异常,例如,Linux通过int$0x80指令将128号设定为系统调用,而Windows通过int$0x2e指令将46号设定为系统调用。回顾:用“系统思维”分析问题代码段一:inta=0x80000000;intb=a/-1;printf("%d\n",b);运行结果为-2147483648 代码段二: inta=0x80000000; intb=-1; intc=a/b; printf("%d\n",c); 运行结果为“Floatingpointexception”,显然CPU检测到了溢出异常objdump反汇编代码,得知除以-1被优化成取负指令neg,故未发生除法溢出为什么两者结果不同!a/b用除法指令IDIV实现,但它不生成OF标志,那么如何判断溢出异常的呢?实际上是“除法错”异常#DE(类型0)Linux中,对#DE类型发SIGFPE信号实地址模式下的中断向量表实地址模式(RealMode)是Intel为80286及其之后的处理器提供的一种8086兼容模式。寻址空间1MB,指令地址=CS<<4+IP。中断向量表位于0000H~03FFH。共256组,每组占四个字节CS:IP。CS:IP例1:除法错的中断类型号为0,故其向量地址为:0x4=0例2:NMI的中断类型号为2,故其向量地址为:2x4=8000~003H004~007H008~00BH3FC~3FFH除法错单步NMI中断向量表中每一项是对应中断服务程序或异常处理程序的入口地址,被称为中断向量(InterruptVector)。CS:IPCS:IPCS:IPCS:IP实地址模式下没有分页管理机制!实地址模式下的中断向量表 开机后系统首先在实地址模式下工作(只有1MB的寻址空间) 开机过程中,需要先准备在实模式下的中断向量表和中断服务程序。通常,由固化在主板上一块ROM芯片中的BIOS程序完成 BIOS程序检测显卡、键盘、内存等,并在00000H~003FFH区建立中断向量表,在中断向量所指主存区建立相应的中断服务程序 BIOS利用INT指令执行特定的中断服务程序把OS从磁盘加载到内存中。例如,BIOS可通过执行int0x19指令来调用中断向量0x19对应的中断服务程序,将启动盘上的0号磁头对应盘面的0磁道1扇区中的引导程序装入内存 BIOS(BasicInput/OutputSystem)是基本输入/输出系统的简称,是针对具体主板 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 的,与安装的操作系统无关。 BIOS包含各种基本设备驱动程序,通过执行BIOS程序,基本设备驱动程序以中断服务程序的形式被加载到内存,以提供基本I/O系统调用。 一旦进入保护模式,就不再使用BIOS。保护模式下的中断描述符表 保护模式下,通过中断描述符表获异常处理或中断服务程序入口地址 中断描述符表(InterruptDescriptorTable,IDT)是OS内核中的一个表,共有256个表项,每个表项占8个字节,IDT共占用2KB IDTR中存放IDT在内存的首地址 每一个表项是一个中断门描述符、陷阱门描述符或任务门描述符P:Linux总把P置1。DPL:访问本段要求的最低特权级。主要用于防止恶意应用程序通过INTn指令模拟非法异常而进入内核态执行破坏性操作TYPE:标识门的类型。TYPE=1110B:中断门;TYPE=1111B:陷阱门;TYPE=0101B:任务门段选择符用来指示异常处理程序或中断服务程序所在段的段描述符在GDT中的位置,其RPL=0;偏移地址则给出异常处理程序或中断服务程序第一条指令所在偏移量。IA-32中异常和中断的处理 引导程序被读到内存后,开始执行引导程序,以装入操作系统内核,并对GDT、IDT等进行初始化,系统启动后,进入保护模式 IA-32中,每条指令执行后,下条指令的逻辑地址(虚拟地址)由CS和EIP指示 每条指令执行过程中,CPU会根据执行情况判定是否发生了某种内部异常事件,并在每条指令执行结束时判定是否发生了外部中断请求(由此可见,异常事件和中断请求的检测都是在某一条指令执行过程中进行的,显然由硬件完成) 在CPU根据CS和EIP取下条指令之前,会根据检测的结果判断是否进入中断响应阶段(异常和中断的响应也都是在某一条指令执行过程中或执行结束时进行的,显然也由硬件完成)实地址模式下:指令地址=CS<<4+IPIA-32中异常和中断响应过程(1)确定中断类型号i,从IDTR指向的IDT中取出第i个表项IDTi。(2)根据IDTi中段选择符,从GDTR指向的GDT中取出相应段描述符,得到对应异常或中断处理程序所在段的DPL、基地址等信息。Linux下中断门和陷阱门对应的即为内核代码段,所以DPL为0,基地址为0。(3)若CPL<DPL或编程异常IDTi的DPL<CPL,则发生13号异常。Linux下,前者不会发生。后者用于防止恶意程序模拟INTn陷入内核进行破坏性操作。(4)若CPL≠DPL,则从用户态换至内核态,以使用内核栈。切换栈的步骤:①读TR寄存器,以访问正在运行的用户进程的TSS段;②将TSS段中保存的内核栈的段选择符和栈指针分别装入寄存器SS和ESP,然后在内核栈中保存原来用户栈的SS和ESP。(5)若是故障,则将发生故障的指令的逻辑地址写入CS和EIP,以使处理后回到故障指令执行。其他情况下,CS和EIP不变,使处理后回到下条指令执行。(6)在当前栈中保存EFLAGS、CS和EIP寄存器的内容(断点和程序状态)。(7)若异常产生了一个硬件出错码,则将其保存在内核栈中。(8)将IDTi中的段选择符装入CS,IDTi中的偏移地址装入EIP,它们是异常处理程序或中断服务程序第一条指令的逻辑地址(Linux中段基址=0)。下个时钟周期开始,从CS:EIP所指处开始执行异常或中断处理程序!SKIP回顾:IA-32/Linux中的分段机制 为使能移植到绝大多数流行处理器平台,Linux简化了分段机制 RISC对分段支持非常有限,因此Linux仅使用IA-32的分页机制,而对于分段,则通过在初始化时将所有段描述符的基址设为0来简化 若把运行在用户态的所有Linux进程使用的代码段和数据段分别称为用户代码段和用户数据段;把运行在内核态的所有Linux进程使用的代码段和数据段分别称为内核代码段和内核数据段,则Linux初始化时,将上述4个段的段描述符中各字段设置成下表中的信息:初始化时,上述4个段描述符被存放在GDT中进程的地址空间用户级上下文TSS段内核中的TSS段记录了每个进程的状态信息,例如,每个进程对应的页表、task和mm等结构信息、内核栈的栈顶信息:SS:ESP等BACKIA-32中异常和中断返回过程中断或异常处理程序最后一条指令是IRET。CPU在执行IRET指令过程中完成以下工作:(1)从栈中弹出硬件出错码(保存过的话)、EIP、CS和EFLAGS(2)检查当前异常或中断处理程序的CPL是否等于CS中最低两位,若是则说明异常或中断响应前、后都处于同一个特权级,此时,IRET指令完成操作;否则,再继续完成下一步工作。(3)从内核栈中弹出SS和ESP,以恢复到异常或中断响应前的特权级进程所使用的栈。(4)检查DS、ES、FS和GS段寄存器的内容,若其中有某个寄存器的段选择符指向一个段描述符且其DPL小于CPL,则将该段寄存器清0。这是为了防止恶意应用程序(CPL=3)利用内核以前使用过的段寄存器(DPL=0)来访问内核地址空间。执行完IRET指令后,CPU回到原来发生异常或中断的进程继续执行Linux中的异常和中断处理 Linux利用陷阱门来处理异常,利用中断门来处理中断。 异常和中断对应处理程序都属于内核代码段,所以,所有中断门和陷阱门的段选择符(0x60)都指向GDT中的“内核代码段”描述符。 通过中断门进入到一个中断服务程序时,CPU会清除EFLAGS寄存器中的IF标志,即关中断;通过陷阱门进入一个异常处理程序时,CPU不会修改IF标志。也就是说,外部中断不支持嵌套处理,而内部异常则支持嵌套处理。 任务门描述符中不包含偏移地址,只包含TSS段选择符,这个段选择符指向GDT中的一个TSS段描述符,CPU根据TSS段中的相关信息装载SS和ESP等寄存器,从而执行相应的异常处理程序。 Linux中,将类型号为8的双重故障(#DF)用任务门实现,而且是唯一通过任务门实现的异常。 双重故障TSS段描述符在GDT中位于索引值为0x1f的表项处,即13位索引为0000000011111,且其TI=0(指向GDT),RPL=00(内核级代码),即任务门描述符中的段选择符为00F8H。Why?试想一下处理缺页时又有非法指令或栈溢出等!Linux中的中断门、陷阱门和任务门Linux中中断描述符表的初始化CPU负责对异常和中断的检测与响应,而操作系统则负责初始化IDT以及编制好异常处理程序或中断服务程序。Linux运用提供的三种门描述符 格式 pdf格式笔记格式下载页码格式下载公文格式下载简报格式下载 ,构造了以下5种类型的门描述符。(1)中断门:DPL=0,TYPE=1110B。激活所有中断(2)系统门:DPL=3,TYPE=1111B。激活4、5和128三个陷阱异常,分别对应指令into、bound和int$0x80三条指令。因DPL为3,CPL≤DPL,故在用户态下可使用这三条指令(3)系统中断门:DPL=3,TYPE=1110B。激活3号中断(即调试断点),对应指令int3。因DPL为3,CPL≤DPL,故用户态下可使用int3指令。(4)陷阱门:DPL=0,TYPE=1111B。激活所有内部异常,并阻止用户程序使用INTn(n≠128或3)指令模拟非法异常来陷入内核态运行。(5)任务门:DPL=0,TYPE=0101B。激活8号中断(双重故障)。Linux内核在启用异常和中断机制之前,先设置好IDT的每个表项,并把IDT首址存入IDTR。系统初始化时,Linux完成对GDT、GDTR、IDT和IDTR等的设置,以后一旦发生异常或中断,CPU就可通过异常和中断响应机制调出异常或中断处理程序执行。Linux中对异常的处理 异常处理程序发送相应的信号给发生异常的当前进程,或者进行故障恢复,然后返回到断点处执行。例如,若执行了非法操作,CPU就产生6号异常(#UD),在对应的异常处理程序中,向当前进程发送一个SIGILL信号,以 通知 关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知 当前
本文档为【计算机系统基础第七章异常控制流】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: ¥19.92 已有0 人下载
最新资料
资料动态
专题动态
个人认证用户
孟子73代
暂无简介~
格式:ppt
大小:1MB
软件:PowerPoint
页数:0
分类:工学
上传时间:2019-01-11
浏览量:18