为什么网站建设,云南省建设交易中心网站,国外免费服务器平台,网站界面用什么做的操作系统实验二
2.1 实验目的
通过调试一个简单的多任务内核实例#xff0c;使大家可以熟练的掌握调试系统内核的方法#xff1b;掌握Bochs虚拟机的调试技巧#xff1b;通过调试和记录#xff0c;理解操作系统及应用程序在内存中是如何进行分配与管理的#xff1b;
2.2…操作系统实验二
2.1 实验目的
通过调试一个简单的多任务内核实例使大家可以熟练的掌握调试系统内核的方法掌握Bochs虚拟机的调试技巧通过调试和记录理解操作系统及应用程序在内存中是如何进行分配与管理的
2.2 实验内容 通过调试一个简单的多任务内核实例使大家可以熟练的掌握调试系统内核的方法。 这个内核示例中包含两个特权级 3 的用户任务和一个系统调用中断过程。我们首先说明这个简单内核的基本结构和加载运行的基本原理然后描述它是如何被加载进机器 RAM 内存中以及两个任务是如何进行切换运行的。 2.2.1 掌握Bochs虚拟机的调试技巧 设置断点 (b): 可以在指定的内存地址处设置断点当程序执行到该地址时会中断执行方便用户进行调试。 显示断点状态 (blist): 可以查看当前所有断点的状态包括断点地址和是否启用。 读/写断点 (unwatch/watch): 可以设置或清除读或写的断点当指定内存地址被读取或写入时会触发断点中断。 显示寄存器状态 (trace-reg on): 在单步调试时会显示每个寄存器的状态帮助用户了解程序执行的过程。 打印当前堆栈 (print-stack): 可以打印当前的堆栈信息帮助用户跟踪函数调用和返回。 继续向下执行 ( c): 用于继续执行程序直到遇到下一个断点或程序结束。 单步执行 (s): 逐步执行程序一次执行一条指令方便用户逐行跟踪代码执行流程。 查看寄存器信息 (info cpu/r/sreg/creg): 可以查看CPU寄存器、段寄存器和控制寄存器的信息帮助用户了解当前的CPU状态。 查看内存内容 (xp /nuf): 可以查看指定内存地址处的内容用户可以指定显示的单元数量、单元大小和显示格式。支持十六进制、十进制、无符号十进制、八进制和二进制等不同的显示格式。 反汇编指定范围的内存 (u): 可以对指定范围的内存进行反汇编帮助用户查看内存中的指令内容。
2.3. 实验报告
1.当执行完 system_interrupt 函数执行 153 行 iret 时记录栈的变化情况。 若从task1中调用int 0x80 进入 system_interrupt执行iret之前栈底地址为0x10e0即目前使用krn_stk1 栈中的内容 地址值意义0x10CC0x10ff代码指针即eip0x10D00x000f当前局部空间代码段选择符(即cs)0x10D40x0202标志寄存器值(即eflags)0x10D80x1308堆栈指针(即esp)0x10DC0x0017当前局部空间数据段堆栈段选择符(即ds)0x10e00x17b8栈底 若从task1中调用int 0x80 进入 system_interrupt执行iret之后栈底指针为0x1308即目前使用usr_stk1。同时栈底指针与执行iret前栈内0x10D8处的值相等证明此处存储堆栈指针。 栈中的内容 地址值意义0x13080x0000栈底 若从task0中调用int 0x80 进入 system_interrupt执行iret之前栈底指针为0x0E60即目前使用krn_stk0 栈中的内容 地址值意义0x0E4C0x10eb代码指针即eip0x0E500x000f当前局部空间代码段选择符(即cs)0x0E540x0246标志寄存器值(即eflags)0x0E580x0bd8堆栈指针(即esp)0x0E5C0x0017当前局部空间数据段堆栈段选择符(即ds)0x0E600x0000栈底 若从task0中调用int 0x80 进入 system_interrupt执行iret之后栈底指针为0x0BD8即目前使用init_stack。同时栈底指针与执行iret前栈内0x0E58处的值相等证明此处存储堆栈指针。 栈中的内容 地址值意义0x0BD80x0bd8栈底
2.当进入和退出 system_interrupt 时都发生了模式切换请总结模式切换时特权级是如何改变的栈切换吗如何进行切换的 特权级的切换 通过调用中断修改程序运行时的cs。在进入中断前程序当前的特权级为3即用户模式。而触发int 0x80中断后程序会进入内核模式特权级变为0。在返回中断前特权级又从0变为3从而完成特权级的切换。栈的切换 在进入中断时程序会自动将当前的一些寄存器的值压入栈内以确保能够正确地返回原程序。然后在执行iret指令前程序会将之前压入栈内的信息弹出覆盖掉现有的cs使程序的特权级从0变为3。同时堆栈指针即esp也会发生变化当前使用的栈会从一个内核栈krn_stk0或krn_stk1变成用户栈usr_stk1。 因此通过int指令和iret指令完成的模式切换和特权级的切换。此外这种切换也是为了确保程序的正确执行和系统的稳定运行。 3.当时钟中断发生进入到 timer_interrupt 程序请详细记录从任务 0 切换到任务 1 的过程。
**将1存入currnt **这个操作通常是为了标记当前正在执行的任务以便在后续的处理中能够正确地切换到任务 1。通过ljmp指令从任务0切换至任务1 在 timer_interrupt 程序内使用 ljmp 指令进行任务切换。ljmp 是一个汇编指令它用于在任务之间进行切换。在进行切换之前需要先将当前任务的各寄存器状态和值保存到 tss0 内。这个操作是为了保存当前任务的上下文以便在需要时可以正确地恢复。 imer_interrupt 处理程序内执行ljmp指令从任务0切换至任务1之前tss0的状态。 timer_interrupt 处理程序内执行ljmp指令从任务0切换至任务1之后tss0的状态。 查找得到tss1的地址并加载各寄存器的值 在切换到任务 1 之前需要通过 $TSS1_SEL 选择符从 gdt 中查找得到 tss1 的地址。然后从 tss1 中获取任务 1 的各寄存器值并将这些值加载进各寄存器中。这个操作是为了恢复任务 1 的上下文。 timer_interrupt 处理程序内执行ljmp指令从任务0切换至任务1之前tss1以及当前各个寄存器的状态。 timer_interrupt 处理程序内执行ljmp指令从任务0切换至任务1之后tss1以及当前各个寄存器的状态。 **执行任务1 **最后根据新加载进来的 cs:eip 以及各寄存器的状态和值执行任务 1。cs:eip 是代码段寄存器和偏移量寄存器它们用于确定下一条要执行的指令。这个步骤是真正执行任务 1 的开始。
4.又过了 10ms 从任务1切换回到任务 0 整个流程是怎样的 TSS 是如何变化的各个寄存器的值是如何变化的
将0存入currnt 使下次执行时钟中断处理函数时执行ljmp时选择的是$TSS1_SEL。通过 ljmp 指令从任务0切换至任务1 确保再从任务0切换回任务1时可以正常进行将当前各寄存器的状态和值存入tss1内。 在 timer_interrupt 处理程序内执行ljmp指令从任务1切换至任务0之前tss1的状态。注0xe78至0xedf为tss1 在 timer_interrupt 处理程序内执行ljmp指令从任务1切换至任务0之后tss1的状态。 将任务0的各寄存器状态和值从 tss0 中加载到各寄存器中 通过 $TSS0_SEL 选择符从gdt中查找得到tss0的地址进而在tss0内得到各寄存器的值将其加载进各寄存器中。 在 timer_interrupt 处理程序内执行ljmp指令从任务1切换至任务0之前tss0以及当前各个寄存器的状态。注0xbf8至0xc5f为tss0 在 timer_interrupt 处理程序内执行ljmp指令从任务1切换至任务0之后tss0以及当前各个寄存器的状态。 执行任务0 按照新加载进来的cs:eip以及各寄存器值和状态执行任务0。
5.请详细总结任务切换的过程。
在时钟中断处理函数中首先根据current的值判断执行ljmp时应该使用哪个tss的选择符作为参数。current的值通常指向当前正在执行的任务的tss。在执行ljmp指令之前需要将当前任务的各寄存器状态和值保存到当前的tss内。这个操作是为了保存当前任务的上下文以便在需要时可以正确地恢复。执行ljmp指令进行任务切换。这个指令会根据参数中的tss选择符去gdt表内查找对应的tss地址。然后通过这个地址获取到新的tss内容并将这些内容加载到各寄存器中。此时已经恢复到了上次进行任务切换时的状态并开始执行导致切换的那条指令的下一条指令。 任务切换过程是通过保存和恢复任务的上下文来实现的。在保存上下文时需要将各寄存器的状态和值存储到tss中。在恢复上下文时需要从tss中获取各寄存器的值并将其加载到相应的寄存器中。这样就可以实现在一个任务执行过程中能够在不同任务之间进行切换。