Hello, ICS2025.
《计算机系统基础》第7章 理论习题选解
习题解答仅供参考,如有问题或获取Markdown版本,请移步github仓库或联系转工管群ISGSNSG。
第3题
根据《计算机系统基础》7.1.2节内容,不同进程的逻辑控制流在时间上有交错或重叠的情况称为并发,两个同时执行的进程的逻辑控制流称为并行。并行是并发执行的一个特例,并行执行的两个进程一定只能同时运行在不同的处理器或处理器的不同核上;而并发执行与处理器核数没有关系。 据此,本题中进程对P1-P2存在并发运行;进程对P1-P3存在并发运行;进程对P1-P4存在并发运行;进程对P2-P3存在并发运行;进程对P3-P4存在并发运行。
第4题
(1)根据《计算机系统基础》6.5.3节内容,在分页式虚拟存储系统中虚拟存储管理采用“请求分页”思想,每次访问指令或数据仅将当前需要的页从硬盘调入主存某页框中,而进程中其他不活跃页面保留在磁盘。当需要访问的虚拟页不在内存中时发生缺页异常,此时磁盘将缺失页面装入主存。 本题中,我们关心取指令操作,这一操作访问的是指令的地址,第1行对应的虚拟地址为0x80482c0,页大小\(4KB = 2^{12}B\),则7条指令均位于虚页号为0x8048的虚拟页中且首条指令不位于页的起始地址,在执行前序指令时认为该页已被装入主存,不会发生缺页异常。 (2)执行第1、2条指令时较可能发生缺页异常,属于可恢复的问题。执行第6条指令时不会发生缺页异常,尽管b[2500]与b[1000]不在同一个虚拟页中,但是第2条指令执行时将虚页号为0x804a的虚拟页装入了内存(注意到b[2500]和k在一个地址)。执行第7条指令时很可能发生页故障,因为可能涉及非法地址访问/访问越权(超出可读写数据区范围),这个问题是不可恢复的,也即会看到我在PA和lab中经常遇到的、“喜闻乐见”的(这里引用lab3的失败提示)
Welcome to the buffer overflow attack lab.Reading from your solution file ...Task failed.
Program received signal SIGSEGV, Segmentation fault.
Program terminated with signal SIGABRT, Aborted.
The program no longer exists.
用户进程 movw $0x4e20, 0x804de20
|
缺页异常(页故障)
|
操作系统页故障处理程序 检测到地址越界/访问越权
|
Program received signal SIGSEGV, Segmentation fault.
unsigned short k未被初始化,可能会报warning,以及考虑到其为C语言中未初始化的全局变量,可能会发生“除0”故障,不可恢复。
第5题
(1)根据《计算机系统基础》6.5.4节的内容,执行内核程序时处理器所处的模式称为管理模式、内核模式、超级用户模式或管理程序状态,简称管态、管理态、内核态或核心态;执行用户程序时处理器所处的模式称为用户模式、用户状态或目标程序状态,简称目态或用户态。
系统执行该段代码时系统处于用户态,因为其在执行用户程序;下一时钟周期处于内核态。
(2)根据《计算机系统基础》7.2.2节的内容,Intel将内部异常分为三类:故障(fault)、陷阱(trap)、终止(abort)。其中陷阱与“故障”等其他异常事件不同,是预先安排的一种“异常”事件;当执行到陷阱指令时,CPU调出特定程序进行相应处理,处理结束后返回下一条指令执行,为用户程序和内核之间提供接口,称为系统调用。
据此,判断第5行指令int $0x80属于陷阱指令,使用系统门描述符激活异常处理程序,P = 1, DPL = 3, TYPE = 1111B。根据《计算机系统基础》6.6.1节内容,
通过Linux中设置的4个段描述符部分字段的内容可知基地址0x0,限界0xFFFFF,G = 1,S = 1, TYPE = 1010, DPL = 0, D = 1, P = 1。
(3)根据《计算机系统基础》第7.3.3节内容,我们描述如下:
①确定检测到的异常/中断类型号i,从IDTR指向的iDT中取出第i个表顶IDTi。此处i = 0x80(128)
②根据IDT中的段选择符,从GDTR指向的GDT中取出相应的段描述符,得到对应异常处理程序或中断服务程序所在段的DPL、基地址等信息。
③将当前特权级CPL(CS寄在器最低两位,00为内核特权级,11为用户特权级)与段描述符中的DPL比较。若CPL小于DPL,则产生13号异常(#GP)。这里没有发生#GP异常。
④检查是否发生了特权级变化,即判断CPL是否与相应段描述符中的DPL不同。如果是的话,就需要从用户态切换至内核态,以使用内核对应的栈。Linux中,若CPL=DPL,则发生异常或中断的指令也在内核态执行;若CPL>DPL,则从用户态转到内核态执行,因此,应从用户栈切换到内核栈。这里需要从用户态切换至内核态执行,具体地:读TR寄存器,以访问正在运行进程的TSS段;将TSS段中保存的内核栈的段选择符和栈指针分别装人寄存器SS和ESP,然后在内核栈中保存原来的用户栈的SS和ESP。
⑤将下一条指令的逻辑地址写入CS和EIP,以保证故障处理后能回到发生故障的指令执行。
⑥在当前栈中保存EFLAGs,CS和EIP寄存器的内容。若是中断门,则将EFLAGS寄存器中的IF清0,这里不会这么做,因为本处使用系统门描述符激活异常处理程序。
⑦如果异常产生了一个硬件出错码,则将其保存在内核栈中;这里没有产生硬件出错码。
⑧将IDTi中的段选择符装入CS, IDTi中的偏移地址装入EIP,它们是异常处理程序或中断服务程序第一条指令的逻辑地址。
这样,从下一个时钟开始,就执行异常处理程序或中断服务程序的第一条指令。在异常处理程序或中断服务程序中,处理完异常或中断后,通过执行最后一条指令IRET回到原被中断的进程继续执行。
执行IRET指令过程中完成以下工作:
①从内核栈中弹出EIP、 CS和EFLAGs,恢复断点和程序状态。
②检查当前异常或中断处理程序的CPL是否等于CS中最低两位,若是,则说明异常或中断响应前后处于同一个特权级,IRET指令完成操作;否则,再继续完成下一步工作。这里CPL不等于CS中最低两位,异常或中断响应前后不处于同一个特权级(正如第1问所指出的),因此还需要继续执行。
③从内核栈中弹出SS和ESP,以恢复到异常或中断响应前的特权级进程所使用的栈。
④检查DS、ES、FS和 GS段寄存器的内容,若其中有某个寄存器的段选择符指向一个段精述符且其DPL小于CPL,则将该段寄存器清0。这是为了防止恶意应用程序(CPL=3)利用内核以前使用过的段寄存器(DPL=0)来访问内核地址空间。
2025.1.4