合肥工业大学操作系统实验报告_第1页
合肥工业大学操作系统实验报告_第2页
合肥工业大学操作系统实验报告_第3页
合肥工业大学操作系统实验报告_第4页
合肥工业大学操作系统实验报告_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、合肥工业大学计算机与信息学院实验报告课 程: 计算机操作系统专业班级: 计算机科学与技术2班学 号: 姓 名: 实验1 实验环境的使用1.熟悉操作系统集成实验环境OS Lab的基本使用方法。 2.练习编译、调试EOS操作系统内核以及EOS应用程序。1启动OS Lab2. 学习OS Lab的基本使用方法 2.4.1 使用断点中断执行3. EOS内核项目的生成和调试3.5查看EOS SDK(Software Development Kit)文件夹4. EOS应用程序项目的生成和调试5 退出OS Lab6 保存EOS内核项目本实验主要是熟悉EOS操作系统的基本操作,练习了:(1)新Windows控制

2、台应用程序项,1.“文件”菜单中选择“新建”,然后单击“项目”。2. 在“新建项目”对话框中,选择项目模板“控制台应用程序 (c)”。3. 在“名称”中输入新项目使用的文件夹名称“oslab”。4. 在“位置”中输入新项目保存在磁盘上的位置“C:test”。新建完毕后, OS Lab 会自动打开这个新建的项目。(2)在“生成”菜单中选择“生成项目”。结果如图(3)执行项目:选择“调试”菜单中的“开始执行”(4)调试项目:1. 右键点击“项目管理器”窗口中的“源文件”文件夹节点,在弹出的快捷菜单中选择“添加”中的“添加新文件”。 2. 在弹出的“添加新文件”对话框中选择“C 源文件”模板。 3.

3、 在“名称”中输入文件名称“func”。 4. 点击“添加”按钮,添加并自动打开文件func.c,此时的“项目管理器”窗口会如图: (5). 在 func.c 文件中添加函数: int Func (int n) n = n + 1; return n; (6). 点击源代码编辑器上方的console.c标签,切换到console.c文件。将 main 函数修改为: int main (int argc, char* argv) int Func (int n); / 声明Func函数 int n = 0; n = Func(10); printf (Hello World!n); return

4、 0; 代码修改完毕后按F7实验结果为输出:Hello World!(7). 在main函数中定义变量n的代码行 int n = 0; 上点击鼠标右键,在弹出的快捷菜单中选择“插入/删除断点”,会在此行左侧的空白处显示一个红色圆点,表示已经成功在此行代码添加了一个断点练习使用“逐过程”, “逐语句”,“跳出”功能(8).在源代码编辑器中变量n的名称上点击鼠标右键,在弹出的快捷菜单中选择“快速监视”,进行单步测试,观察n结果依次为0,11(9)调用堆栈,选择“调试”菜单“窗口”中的“调用堆栈”,激活“调用堆栈”窗口。可以看到当前“调用堆栈”窗口中只有一个main函数(显示的内容还包括了参数值和函

5、数地址)。 按F11(“逐语句”功能的快捷键)调试,直到进入Func函数 ,其中当前正在调试的Func函数在栈顶位置,main函数在栈底位置。说明是在main函数中调用了Func函数。 (10)查看软盘镜像文件中的内容,在“项目管理器”今天第一次进行操作系统这门课的实验,这也是将抽象的理论知识应用到实践的一个很好的机会,同时,我们也学习了使用OS Lab的这个实验环境,OS Lab的操作界面和Microsoft Visual Studio 2010很像,所以使用起来很快就能上手,对于实验内容,今天主要练习了:新建Windows控制台应用程序项目、生成项目、执行项目、调试项目以及EOS应用程序项

6、目的生成和调试;设置间断点,并且在它的基础上进行了单步操作;详细观察了通过“快速监视“标记的数的值的变化过程等基本操作,这也为以后实验的顺利进行打下了良好的基础。实验截图实验2 操作系统的启动1.跟踪调试EOS在PC机上从加电复位到成功启动的全过程,了解操作系统的启动过程。 2.查看EOS启动后的状态和行为,理解操作系统启动后的工作方式。 1 准备实验2 调试EOS操作系统的启动过程2.1 使用Bochs做为远程目标机2.2 调试BIOS程序2.3 调试软盘引导扇区程序2.4 调试加载程序2.5 调试内核2.6 EOS启动后的状态和行为1.新建一个EOS Kernel项目。 (1)在“项目管理

7、器”窗口中,右键点击项目节点,在弹出的快捷菜单中选择“属性”。 (2) 在弹出的“属性页”对话框右侧的属性列表中找到“远程目标机”属性,将此属性值修改为“Bochs Debug” (3)点击“确定”按钮关闭“属性页”对话框。接下来就可以使用Bochs模拟器调试BIOS程序和软盘引导扇区程序了。 3.按F5启动调试,此时会弹出两个Bochs窗口。标题为“Bochs for windows - Display”的窗口相当于计算机的显示器,显示操作系统的输出。标题为“Bochs for windows - Console”的窗口是Bochs的控制台,用来输入调试命令,输出各种调试信息。4.启动调试后

8、,Bochs在CPU要执行的第一条指令(即BIOS的第一条指令)处中断。 此时,Display窗口没有显示任何内容,Console窗口显示要执行的BIOS第一条指令的相关信息,并等待用户输入调试命令5.然后查看CPU在没有执行任何指令之前主要寄存器中的数据,以及内存中的数据(1)在Console窗口中输入调试命令sreg后按回车,显示当前CPU中各个段寄存器的值(2)输入调试命令r后按回车,显示当前CPU中各个通用寄存器的值(3)输入调试命令xp /1024b 0 x0000,查看开始的1024个字节的物理内存。在Console中输出的这1K物理内存的值都为0,说明BIOS中断向量表还没有被加

9、载到此处。 (4)输入调试命令xp /512b 0 x7c00,查看软盘引导扇区应该被加载到的内存位置。输出的内存值都为0,说明软盘引导扇区还没有被加载到此处。 (1) 在控制台中输入命令“ver”后按回车。结果如图 (2)查看EOS启动后的进程和线程的信息: 在控制台中输入命令“pt”后按回车。输出的进程和线程信息如图所示今天的实验在实验一的基础上学习了EOS操作系统的启动、跟踪调试以及EOS在PC机上从加电复位到成功启动的全过程,这让我们对EOS这个平台有了初步的掌握,同时我们也练习了查看了EOS启动后的状态和行为,学会了查看CPU主要寄存器中以及内存中的数据的方法。五.实验截图实验3进程

10、的创建一,实验目的:1,练习使用 EOS API 函数 CreateProcess 创建一个进程, 掌握创建进程的方法, 理解进程和程序的区别。2,调试跟踪 CreateProcess 函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。二,预备知识:阅读本书第 5.1 节,重点理解程序和进程的关系,熟悉进程控制块结构体以及进程创建的过程。仔细学习CreateProcess函数和其它与创建进程相关的函数的说明, 注意理解这些函数的参数和返回值的意义。三,主要实验内容及步骤:1, 准备实验;2, 练习使用控制台命令创建EOS 应用程序的进程:练习使用控制台命令创建 EOS 应用程序进程

11、的具体步骤如下:(1) 在 EOS 应用程序项目的“项目管理器”窗口中双击 Floppy.img 文件,使用 FloppyImageEditor工具打开此软盘镜像文件。(2)将本实验文件夹中的 Hello.exe 文件拖动到 FloppyImageEditor 工具窗口的文件列表中释放,Hello.exe 文件即被添加到软盘镜像文件中。Hello.exe 一个 EOS 应用程序,其源代码可以参见本实验文件夹中的 Hello.c 源文件。(3)在 FloppyImageEditor 中选择“文件”菜单中的“保存”后关闭 FloppyImageEditor。(4)按 F7 生成 EOS 应用项目。

12、(5)按 F5 启动调试。OS Lab 会弹出一个调试异常对话框,并中断应用程序的执行。(6) 在调试异常对话框中选择“否”,忽略异常继续执行应用程序。(7) 激活虚拟机窗口,待该应用程序执行完毕后,在 EOS 的控制台中输入命令“”后回车。(8) Hello.exe 应用程序开始执行,观察其输出如图 11-1。(9)待 Hello.exe 执行完毕后可以重复第 7 步,或者结束此次调试。3. 练习通过编程的方式让应用程序创建另一个应用程序的进程使用 OS Lab 打开本实验文件夹中的 NewProc.c 文件(将此文件拖动到 OS Lab 窗口中释放即可) 按照下面的步骤查看应用程序创建另一

13、个应用程序的进程的执行结果:(1) 使用NewProc.c文件中的源代码替换之前创建的EOS应用程序项目中的EOSApp.c文件内的源代码。(2)按 F7 生成修改后的 EOS 应用程序项目。(3) 按 F5 启动调试。OS Lab 会首先弹出一个调试异常对话框。(4) 在调试异常对话框中选择“否”,继续执行。(5)激活虚拟机窗口查看应用程序输出的内容, 如图 11-2。 结合图 11-1, 可以看到父进程 (EOSApp.exe)首先开始执行并输出内容,父进程创建了子进程(Hello.exe)后,子进程开始执行并输出内容,待子进程结束后父进程再继续执行。(6)结束此次调试。4.调试 Crea

14、teProcess 函数按照下面的步骤调试 CreateProcess 函数创建进程的过程:(1) 按 F5 启动调试 EOS 应用程序,OS Lab 会首先弹出一个调试异常对话框。(2) 选择“是”调试异常,调试会中断。(3)在 main 函数中调用 CreateProcess 函数的代码行(第 57 行)添加一个断点。(4)按 F5 继续调试,在断点处中断。(5)按 F11 调试进入 CreateProcess 函数。此时已经开始进入 EOS 内核进行调试。.5, 调试PsCreateProcess 函数 创建进程最主要的操作就是创建进程控制块(PCB),并初始化其中的各种信息(也就是为进

15、程分配各种资源) 。所以在 PsCreateProcess 函数中首先调用了 PspCreateProcessEnvironment 函数来创建进程控制块。调试 PspCreateProcessEnvironment 函数的步骤如下:文件的第 163 行) ,并在此行添加一个断点。(2) 按 F5 继续调试,到此断点处中断。(3) 按 F11 调试进入 PspCreateProcessEnvironment 函数。由于 PspCreateProcessEnvironment 函数的主要功能是创建进程控制块并初始化其中的部分信息,所以在此函数的开始,定义了一个进程控制块的指针变量 NewProc

16、ess。在此函数中查找到创建进程控制块的代码行(create.c 文件的第 418 行)Status = ObCreateObject( PspProcessType,NULL,sizeof(PROCESS) + ImageNameSize + CmdLineSize,0,(PVOID*)&NewProcess );这里的 ObCreateObject 函数会在由 EOS 内核管理的内存中创建了一个新的进程控制块(也就是分配了一块内存) ,并由 NewProcess 返回进程控制块的指针(也就是所分配内存的起始地址) 。按照下面的步骤调试进程控制块的创建过程:(1)在调用 ObCreateOb

17、ject 函数的代码行(create.c 文件的第 418 行)添加一个断点。(2)按 F5 继续调试,到此断点处中断。(3) 按 F10 执行此函数后中断。(4) 此时为了查看进程控制块中的信息,将表达式*NewProcess 添加到“监视”窗口中。(5) 将鼠标移动到“监视”窗口中此表达式的“值”属性上,会弹出一个临时窗口,在临时窗口中会按照进程控制块的结构显示各个成员变量的值(可以参考 PROCESS 结构体的定义) 。由于只是新建了进程控制块,还没有初始化其中成员变量,所以值都为 0。接下来调试初始化进程控制块中各个成员变量的过程:(1)首先创建进程的地址空间,即 4G 虚拟地址空间。

18、在代码行(create.c 文件的第 437 行)NewProcess-Pas = MmCreateProcessAddressSpace();添加一个断点。(2) 按 F5 继续调试,到此断点处中断。(3)按 F10 执行此行代码后中断。(4)在“监视”窗口中查看进程控制块的成员变量 Pas 的值已经不再是 0。说明已经初始化了进程的4G 虚拟地址空间。(5)使用 F10 一步步调试 PspCreateProcessEnvironment 函数中后面的代码,在调试的过程中根据执行的源代码,查看“监视”窗口中*NewProcess 表达式的值,观察进程控制块中哪些成员变量是被哪些代码初始化的,

19、哪些成员变量还没有被初始化。(6)当从 PspCreateProcessEnvironment 函数返回到 PsCreateProcess 函数后, 停止按 F10。 此时 “监视”窗口中已经不能再显示表达式*NewProcess 的值了,在 PsCreateProcess 函数中是使用ProcessObject 指针指向进程控制块的,所以将表达式*ProcessObject 添加到“监视”窗口中就可以继续观察新建进程控制块中的信息。(7)接下来继续使用 F10 一步步调试 PsCreateProcess 函数中的代码,同样要注意观察执行后的代码修改了进程控制块中的哪些成员变量。当调试到 Ps

20、CreateProcess 函数的最后一行代码时,查看进程控制块中的信息, 此时所有的成员变量都已经被初始化了 (注意观察成员 ImageName 的值) 。(8)按 F5 继续执行,EOS 内核会为刚刚初始化完毕的进程控制块新建一个进程。激活虚拟机窗口查看新建进程执行的结果。(9)在 OS Lab 中选择“调试”菜单中的“停止调试”结束此次调试。(10)选择“调试”菜单中的“删除所有断点” 。6, 练习通过编程的方式创建应用程序的多个进程.四实验收获及感悟:通过本次实验熟悉了进程的创建,对进程更加的了解。也让我更加熟悉OS Lab这个软件,对于EOS操作系统的理解也更加深刻。实验截图实验4:

21、线程的状态和转换一,实验目的:1,调试线程在各种状态间的转换过程,熟悉线程的状态和转换。2,通过为线程增加挂起状态,加深对线程状态的理解。二,预备知识:阅读本书第 5.2.3 节,了解线程都有哪些状态以及 EOS 是如何定义这些状态的。了解线程是如何在这些状态之间进行转换的,特别是要阅读一下 EOS 中用于线程转换的相关函数的源代码。阅读本书第 5.2.4节, 了解 EOS 为线程添加的挂起状态, 以及 Suspend 和 Resume 原语操作。 线程状态的转换和线程的同步、线程的调度是不可分割的,所以建议读者简单学习一下第 5.3 和 5.4 节中的内容。此外,由于本实验需要观察“控制台派

22、遣线程”在不同状态间的转换过程,所以读者也需要对该线程有一个简单的了解。控制台派遣线程做为一个系统线程(优先级为 24) ,在 EOS 启动后就会被创建,但是该线程绝大部分时间都处于阻塞状态,只有当发生键盘事件(例如键被按下)时才会被唤醒,当该线程将键盘事件派遣到当前活动的控制台后,该线程就会重新回到阻塞状态等待下一个键盘事件到来。该线程的线程函数是文件 io/console.c 中的 IopConsoleDispatchThread 函数(第 567 行) 。三,主要实验内容及步骤:1,准备实验;2,调试线程状态的转换过程;在本练习中,会在与线程状态转换相关的函数中添加若干个断点,并引导读者

23、单步调试这些函数,使读者对 EOS 中的下列线程状态转换过程有一个全面的认识: 线程由阻塞状态进入就绪状态。 线程由运行状态进入就绪状态。 线程由就绪状态进入运行状态。 线程由运行状态进入阻塞状态。为了完成这个练习,EOS 准备了一个控制台命令“loop” ,这个命令的命令函数是 ke/sysproc.c 文件中的 ConsoleCmdLoop 函数(第 797 行) ,在此函数中使用 LoopThreadFunction 函数(第 755 行)创建了一个优先级为 8 的线程(后面简称为“loop 线程” ) ,该线程会在控制台中不停的(死循环)输出该线程的ID 和执行计数,执行计数会不停的增

24、长以表示该线程在不停的运行。可以按照下面的步骤查看一下 loop命令执行的效果:(1) 按 F7 生成在本实验 3.1 中创建的 EOS Kernel 项目。(2) 按 F5 启动调试。(3) 待 EOS 启动完毕,在 EOS 控制台中输入命令“loop”后按回车。(4) 结束此次调试。接下来按照下面的步骤调试线程状态转换的过程:(1) 在 ke/sysproc.c 文件的 LoopThreadFunction 函数中,开始死循环的代码行(第 787 行)添加一个断点。(2)按 F5 启动调试。(3) 待 EOS 启动完毕,在 EOS 控制台中输入命令“loop”后按回车。EOS 会在断点处中

25、断执行,表明 loop 线程已经开始死循环了。此时,EOS 中所有的系统线程要么处于就绪状态(其优先级一定小于 8,例如系统空闲线程) ,要么就处于阻塞状态(例如控制台派遣线程或控制台线程) ,所以,只有优先级为 8 的 loop 线程能够在处理器上执行。接下来按照下面的步骤对断点进行一些调整:(1)删除所有断点。(2)打开 ps/sched.c 文件,在与线程状态转换相关的函数中添加断点,这样,一旦有线程的状态发生改变,EOS 会中断执行,就可以观察线程状态转换的详细过程了。需要添加的断点有: 在 PspReadyThread 函数体中添加一个断点(第 130 行) 。 在 PspUnrea

26、dyThread 函数体中添加一个断点(第 158 行) 。 在 PspWait 函数体中添加一个断点(第 223 行) 。 在 PspUnwaitThread 函数体中添加一个断点(第 282 行) 。 在 PspSelectNextThread 函数体中添加一个断点(第 395 行) 。(3)按 F5 继续执行,然后激活虚拟机窗口。此时在虚拟机窗口中会看到 loop 线程在不停执行,而之前添加的断点都没有被命中,说明此时还没有任何线程的状态发生改变。在开始观察线程状态转换过程之前还有必要做一个说明。在后面的练习中,会在 loop 线程执行的过程中按一次空格键,这会导致 EOS 依次执行下面

27、的操作:(1)控制台派遣线程被唤醒,由阻塞状态进入就绪状态。(2)loop 线程由运行状态进入就绪状态。(3) 控制台派遣线程由就绪状态进入运行状态。(4) 待控制台派遣线程处理完毕由于空格键被按下而产生的键盘事件后,派遣线程会由运行状态重新进入阻塞状态,开始等待下一个键盘事件到来。loop 线程由就绪状态进入运行状态,继续执行死循环2.1,线程由阻塞状态进入就绪状态按照下面的步骤调试线程状态转换的过程:1. 在虚拟机窗口中按下一次空格键。2. 此时 EOS 会在 PspUnwaitThread 函数中的断点处中断。在“调试”菜单中选择“快速监视” ,在快速监视对话框的表达式编辑框中输入表达式

28、“*Thread” ,然后点击“重新计算”按钮,即可查看线程控制块(TCB)中的信息。其中 State 域的值为 3(Waiting) ,双向链表项 StateListEntry的 Next 和 Prev 指针的值都不为 0,说明这个线程还处于阻塞状态,并在某个同步对象的等待队列中;StartAddr 域的值为 IopConsoleDispatchThread,说明这个线程就是控制台派遣线程。3. 关闭快速监视对话框,激活“调用堆栈”窗口。根据当前的调用堆栈,可以看到是由键盘中断服务程序(KdbIsr)进入的。当按下空格键后,就会发生键盘中断,从而触发键盘中断服务程序。在该服务程序的最后中会唤

29、醒控制台派遣线程,将键盘事件派遣到活动的控制台。4. 在“调用堆栈”窗口中双击 PspWakeThread 函数对应的堆栈项。可以看到在此函数中连续调用了PspUnwaitThread 函数和 PspReadyThread 函数, 从而使处于阻塞状态的控制台派遣线程进入就绪状态。5. 在“调用堆栈”窗口中双击 PspUnwaitThread 函数对应的堆栈项,先来看看此函数是如何改变线程状态的。按 F10 单步调试直到此函数的最后,然后再从快速监视对话框中观察“*Thread”表达式的值。此时 State 域的值为 0(Zero) ,双向链表项 StateListEntry 的 Next 和

30、Prev 指针的值都为 0,说明这个线程已经处于游离状态,并已不在任何线程状态的队列中。仔细阅读PspUnwaitThread 函数中的源代码,理解这些源代码是如何改变线程状态的。6. 按 F5 继续执行,在 PspReadyThread 函数中的断点处中断。按 F10 单步调试直到此函数的最后,然后再从快速监视对话框中观察“*Thread”表达式的值。此时 State 域的值为 1(Ready) ,双向链表项 StateListEntry 的 Next 和 Prev 指针的值都不为 0,说明这个线程已经处于就绪状态,并已经被放入优先级为 24 的就绪队列中。仔细阅读 PspReadyThre

31、ad 函数中的源代码,理解这些源代码是如何改变线程状态的。通过以上的调试,可以将线程由阻塞状态进入就绪状态的步骤总结如下:(1) 将线程从等待队列中移除。(2) 将线程的状态由 Waiting 修改为 Zero。(3) 将线程插入其优先级对应的就绪队列的队尾。(4) 将线程的状态由 Zero 修改为 Ready。至此,控制台派遣线程已经进入就绪状态了,因为其优先级(24)比当前处于运行状态的 loop 线程的优先级(8)要高,根据 EOS 已实现的基于优先级的抢先式调度算法,loop 线程会进入就绪状态,控制台派遣线程会抢占处理器从而进入运行状态。接下来调试这两个转换过程。2.2,线程由运行状

32、态进入就绪状态按照下面的步骤调试线程状态转换的过程:1. 按 F5 继续执行,在 PspSelectNextThread 函数中的断点处中断。在快速监视对话框中查看“*PspCurrentThread”表达式的值,观察当前占用处理器的线程的情况。其中 State 域的值为 2(Running) ,双向链表项 StateListEntry 的 Next 和 Prev 指针的值都为 0,说明这个线程仍然处于运行状态,由于只能有一个处于运行状态的线程,所以这个线程不在任何线程状态的队列中;StartAddr 域的值为 LoopThreadFunction,说明这个线程就是 loop 线程。注意,在本

33、次断点被命中之前,loop 线程就已经被中断执行了,并且其上下文已经保存在线程控制块中。2. 按 F10 单步调试,直到对当前线程的操作完成(也就是花括号中的操作完成) 。再从快速监视对话框中查看“*PspCurrentThread”表达式的值。其中 State 域的值为 1(Ready) ,双向链表项StateListEntry 的 Next 和 Prev 指针的值都不为 0,说明 loop 线程已经进入了就绪状态,并已经被放入优先级为 8 的就绪队列中。 仔细阅读 PspSelectNextThread 函数这个花括号中的源代码,理解这些源代码是如何改变线程状态的,并与 PspReadyT

34、hread 函数中的源代码进行比较,说明这两段源代码的异同,体会为什么在这里不能直接调用 PspReadyThread 函数。通过以上的调试,可以将线程由运行状态进入就绪状态的步骤总结如下:(1) 线程中断运行,将线程中断运行时的上下文保存到线程控制块中。(2) 如果处于运行状态的线程被更高优先级的线程抢先,就需要将该线程插入其优先级对应的就绪队列的队首。 (注意,如果处于运行状态的线程主动让出处理器,例如时间片用完,就需要将程插入其优先级对应的就绪队列的队尾。 )(3) 将线程的状态由 Running 修改为 Ready。至此, loop 线程已经进入就绪状态了, 接下来调试控制台派遣线程会

35、得到处理器进入运行状态的过程。2.3: 线程由就绪状态进入运行状态按照下面的步骤调试线程状态转换的过程:1. 按 F5 继续执行, 在 PspUnreadyThread 函数中的断点处中断。 在快速监视对话框中查看 “*Thread”表达式的值。其中 State 域的值为 1(Ready) ,双向链表项 StateListEntry 的 Next 和 Prev 指针的值都不为 0,说明这个线程处于就绪状态,并在优先级为 24 的就绪队列中;StartAddr 域的值为 IopConsoleDispatchThread, 说明这个线程就是控制台派遣线程。 仔细阅读 PspUnreadyThrea

36、d函数中的源代码,理解这些源代码是如何改变线程状态的。2. 关闭快速监视对话框后,在“调用堆栈”窗口中激活 PspSelectNextThread 函数对应的堆栈项,可以看到在 PspSelectNextThread 函数中已经将 PspCurrentThread 全局指针指向了控制台派遣线程,并在调用 PspUnreadyThread 函数后,将当前线程的状态改成了 Running。3. 在“调用堆栈”窗口中激活 PspUnreadyThread 函数对应的堆栈项,然后按 F10 单步调试,直到返回 PspSelectNextThread 函数并将线程状态修改为 Running。再从快速监视

37、对话框中查看“*PspCurrentThread”表达式的值,观察当前占用处理器的线程的情况。其中 State 域的值为 2(Running) ,双向链表项 StateListEntry 的 Next 和 Prev 指针的值都为 0,说明控制台派遣线程已经处于运行状态了。接下来,会将该线程的上下文从线程控制块(TCB)复制到处理器的各个寄存器中,处理器就可以从该线程上次停止运行的位置继续运行了。通过以上的调试,可以将线程由就绪状态进入运行状态的步骤总结如下:(1) 将线程从其优先级对应的就绪队列中移除。(2) 将线程的状态由 Ready 修改为 Zero。(3) 将线程的状态由 Zero 修改

38、为 Running。(4) 将线程的上下文从线程控制块(TCB)复制到处理器的各个寄存器中,让线程从上次停止运行的位置继续运行。至此,控制台派遣线程已经开始运行了。因为此时没有比控制台派遣线程优先级更高的线程来抢占处理器,所以控制台派遣线程可以一直运行,直到将此次由于空格键被按下而产生的键盘事件处理完毕,然后控制台派遣线程会由运行状态重新进入阻塞状态,开始等待下一个键盘事件到来。2.4,线程由运行状态进入阻塞状态:按照下面的步骤调试线程状态转换的过程:1. 按 F5 继续执行, 在 PspWait 函数中的断点处中断。 在快速监视对话框中查看 “*PspCurrentThread”表达式的值,

39、观察当前占用处理器的线程的情况。其中 State 域的值为 2(Running) ,双向链表项 StateListEntry 的 Next 和 Prev 指针的值都为 0, 说明这个线程仍然处于运行状态; StartAddr域的值为 IopConsoleDispatchThread,说明这个线程就是控制台派遣线程。2. 按 F10 单步调试,直到左侧的黄色箭头指向代码第 248 行。再从快速监视对话框中查看“*PspCurrentThread”表达式的值。其中 State 域的值为 3(Waiting) ,双向链表项StateListEntry 的 Next 和 Prev 指针的值都不为 0,

40、说明控制台派遣线程已经处于阻塞状态了,并在某个同步对象的等待队列中。第 248 行代码可以触发线程调度功能,会中断执行当前已经处于阻塞状态的控制台派遣线程,并将处理器上下文保存到该线程的线程控制块中。通过以上的调试,可以将线程由运行状态进入阻塞状态的步骤总结如下:(1) 将线程插入等待队列的队尾。(2) 将线程的状态由 Running 修改为 Waiting。(3) 将线程中断执行,并将处理器上下文保存到该线程的线程控制块中。至此,控制台派遣线程已经进入阻塞状态了。因为此时 loop 线程是就绪队列中优先级最高的线程,线程调度功能会选择让 loop 线程继续执行。按照下面的步骤调试线程状态转换

41、的过程:1. 按 F5 继续执行,与本实验 3.2.3 节中的情况相同,只不过这次变为 loop 线程由就绪状态进入运行状态。2. 再按 F5 继续执行,EOS 不会再被断点中断。激活虚拟机窗口,可以看到 loop 线程又开始不停的执行死循环了。3. 可以再次按空格键,将以上的调试步骤重复一遍。这次调试的速度可以快一些,仔细体会线程状态转换的过程。3,为线程增加挂起状态: OS 已经实现了一个 suspend 命令,其命令函数为 ConsoleCmdSuspendThread(在 ke/sysproc.c 文件的第 843 行) 。在这个命令中调用了 Suspend 原语(在 ps/psspn

42、d.c 文件第 27 行的 PsSuspendThread 函数中实现) 。Suspend 原语可以将一个处于就绪状态的线程挂起。以 loop 线程为例,当使用 suspend 命令将其挂起时,loop 线程的执行计数就会停止增长。按照下面的步骤观察 loop 线程被挂起的情况:1. 删除之前添加的所有断点。2. 按 F5 启动调试。3. 待 EOS 启动完毕,在 EOS 控制台中输入命令“loop”后按回车。此时可以看到 loop 线程的执行计数在不停增长,说明 loop 线程正在执行。记录下 loop 线程的 ID。4. 按 Ctrl+F2 切换到控制台 2,输入命令“suspend 31

43、” (如果 loop 线程的 ID 是 31)后按回车。5. 按 Ctrl+1 切换回控制台 1,可以看到由于 loop 线程已经成功被挂起,其执行计数已经停止增长了。此时占用处理器的是 EOS 中的空闲线程。 四,实验收获及感悟: 通过本次实验,我学会了调试线程在各种状态间的转化过程,熟悉了线程的状态和转换,在实验中我通过为线程增加挂起状态,加深了对线程状态的理解。实验截图:实验5 进程的同步1.使用EOS的信号量,编程解决生产者消费者问题,理解进程同步的意义。 2.调试跟踪EOS信号量的工作过程,理解进程同步的原理。 3.修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理

44、解进程同步的原理。 1 准备实验2 使用EOS的信号量解决生产者消费者问题3 调试EOS信号量的工作过程3.1 创建信号量3.2 等待、释放信号量3.2.1 等待信号量(不阻塞)3.2.2 释放信号量(不唤醒)3.2.3 等待信号量(阻塞)3.2.4 释放信号量(唤醒)4 修改EOS的信号量算法1.按照下面的步骤查看生产者消费者同步执行的过程:(1)使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码。 (2)按F7生成修改后的EOS应用程序项目。 (3)按F5启动调试。OS Lab会首先弹出一个调试异常对话框。 (4)在调试异常对话框中选择“否”,继续

45、执行。 (5)立即激活虚拟机窗口查看生产者消费者同步执行的过程 (6)待应用程序执行完毕后,结束此次调试。 2. 等待、释放信号量(1)等待信号量(不阻塞) 生产者和消费者刚开始执行时,用来放产品的缓冲区都是空的,所以生产者在第一次调用WaitForSingleObject函数等待Empty信号量时,应该不需要阻塞就可以立即返回。(2)释放信号量(不唤醒)生产者线程通过等待Empty信号量使空缓冲区数量减少了1,通过释放Full信号量使满缓冲区数量增加了1,这样就表示生产者线程生产了一个产品并占用了一个缓冲区。(3)等待信号量(阻塞) 由于开始时生产者线程生产产品的速度较快,而消费者线程消费产

46、品的速度较慢,所以当缓冲池中所有的缓冲区都被产品占用时,生产者在生产新的产品时就会被阻塞(4)释放信号量(唤醒) 只有当消费者线程从缓冲池中消费了一个产品,从而产生一个空缓冲区后,生产者线程才会被唤醒并继续生产14号产品。今天的实验的内容是进程的同步,这也是进程这一概念提出后面临的一个非常大的问题,因为当进程在竞争临界资源时,由于进程的异步性,便会给系统造成混乱,所以能不能让诸多进程之间有效的共享资源和相互合作,就变成了一个很重要的问题。今天的实验也让我们直接的观察到了EOS操作系统如何通过信号量机制解决进程同步问题,并对程序进行修改,这对我们今后的学习有很大的帮助,但对于解决大量同步操作带来

47、的系统死锁问题,我还是欠缺实践和认识。五.实验截图实验7:物理存储器与进程逻辑空间的管理一,实验目的:1,通过查看物理存储器的使用情况,并练习分配和回收物理内存,从而掌握物理存储器的管理方法。2,通过查看进程逻辑地址空间的使用情况,并练习分配和回收虚拟内存,从而掌握进程逻辑地址空间的管理方法。二,预备知识:阅读本书第 6 章。重点阅读第 6.3 节和第 6.6 节,了解物理存储器的管理方式和进程逻辑地址空间的管理方式。三,主要实验内容及步骤:1,准备实验;2,阅读控制台命令“ pm ”相关的源代码,并查看其执行的结果;3,分配物理页和释放物理页: 接下来,在 pm 命令函数中添加分配物理页和释

48、放物理页的代码,单步调试管理物理页的方法。按照下面的步骤修改 pm 命令的源代码:1. 使用 OS Lab 打开本实验文件夹中的 pm.c 文件(将文件拖动到 OS Lab 窗口中释放即可打开) 。此文件中有一个修改后的 ConsoleCmdPhysicalMemory 函数,主要是在原有代码的后面增加了分配物理页和释放物理页的代码。2. 使用 pm.c 文件中 ConsoleCmdPhysicalMemory 函数的函数体替换 ke/sysproc.c 文件中ConsoleCmdPhysicalMemory 函数的函数体。3. 按 F7 生成修改后的 EOS Kernel 项目。4. 按 F

49、5 启动调试。5. 待 EOS 启动完毕,在 EOS 控制台中输入命令“pm”后按回车。按照下面的步骤调试分配物理页和释放物理页的过程:1. 结束之前的调试。2. 在 ke/sysproc.c 文件的 ConsoleCmdPhysicalMemory 函数中,在调用 MiAllocateAnyPages 函数的代码行(第 1103 行)添加一个断点,在调用 MiFreePages 函数的代码行(第 1115 行)添加一个断点。3. 按 F5 启动调试。4. 待 EOS 启动完毕,在 EOS 控制台中输入命令“pm”后按回车。5. pm 命令开始执行后,会在调用 MiAllocateAnyPag

50、es 函数的代码行处中断,按 F11 调试进入MiAllocateAnyPages 函数。6. 按 F10 单步调试 MiAllocateAnyPages 函数的执行过程,尝试回答下面的问题:(1) 本次分配的物理页的数量是多少?分配的物理页的页框号是多少?(2) 物理页是从空闲页链表中分配的?还是从零页链表中分配的?(3) 哪一行语句减少了空闲页的数量?哪一行语句将刚刚分配的物理页由空闲状态修改为忙状态?(4) 绘制 MiAllocateAnyPages 函数的流程图。继续调试释放物理页的过程:1. 按 F5 继续执行,会在调用 MiFreePages 函数的代码行处中断,按 F11 调试进

51、入 MiFreePages 函数。2. 按 F10 单步调试 MiFreePages 函数的执行过程,尝试回答下面的问题:(1) 本次释放的物理页的数量是多少?释放的物理页的页框号是多少?释放的物理页是之前分配的物理页吗?(2) 释放的物理页是被放入了空闲页链表中?还是零页链表中?(3) 绘制 MiFreePages 函数的流程图。结束此次调试。 继续修改 pm 命令的源代码, 尝试在调用 MiAllocateAnyPages 函数时分配多个物理页,然后在调用 MiFreePages 函数时将分配的多个物理页释放,并练习调试这两个函数在分配多个物理页和释放多个物理页时执行的过程4,阅读控制台命

52、令“ vm相关的源代码,并查看其执行结果;5,在系统进程中分配虚拟页和释放虚拟页: 接下来, 在 vm 命令函数中添加分配虚拟页和释放虚拟页的代码, 单步调试管理虚拟页的方法。 首先,按照下面的步骤修改 vm 命令的源代码:1. 使用 OS Lab 打开本实验文件夹中的 vm.c 文件(将文件拖动到 OS Lab 窗口中释放即可打开) 。此文件中有一个修改后的 ConsoleCmdVM 函数,主要是在原有代码的后面增加了分配虚拟页和释放物理页的代码。2. 使用 vm.c 文件中 ConsoleCmdVM 函数的函数体替换 ke/sysproc.c 文件中 ConsoleCmdVM 函数的函数体

53、。3. 按 F7 生成修改后的 EOS Kernel 项目。4. 按 F5 启动调试。5. 待 EOS 启动完毕,在 EOS 控制台中输入命令“vm 1”后按回车。命令执行的结果会同时转储在“输出”窗口中。尝试说明分配虚拟页或者释放虚拟页后虚拟地址描述符以及物理存储器的变化情况。6,在应用程序进程中,分配虚拟页和释放虚拟页;四,实验收获及感悟: 通过本次实验,让我学会了通过查看物理存储器的使用情况,并练习分配和回收物理内存,从而掌握物理存储器的管理方法。以及通过查看进程逻辑地址空间的使用情况,并练习分配和回收虚拟内存,从而掌握进程逻辑地址空间的管理方法。五:实验截图:实验8:分页存储器的管理一

54、,实验目的:1,学习 i386 处理器的二级页表硬件机制,理解分页存储器管理原理2,查看 EOS 应用程序进程和系统进程的二级页表映射信息,理解页目录和页表的管理方式。3,编程修改页目录和页表的映射关系,理解分页地址变换原理。二,预备知识:阅读本书第 6 章。了解 i386 处理器的二级页表硬件机制,EOS 操作系统的分页存储器管理方式,以及进程地址空间的内存分布。三,主要实验内容及步骤:1,准备实验;2,查看 EOS应用程序进程的页目录和页表;使用 OS Lab 打开本实验文件夹中的 memory.c 和 getcr3.asm 文件(将文件拖动到 OS Lab 窗口中释放即可打开) 。仔细阅

55、读这两个文件中的源代码和注释,main 函数的流程图可以参见图 16-1。按照下面的步骤查看 EOS 应用程序进程的页目录和页表:1. 使用 memory.c 文件中的源代码替换之前创建的 EOS 应用程序项目中 EOSApp.c 文件中的源代码。2. 右键点击“项目管理器”窗口中的“源文件”文件夹节点,在弹出的快捷菜单中选择“添加”中的“添加新文件”。3. 在弹出的“添加新文件”对话框中选择“asm 源文件”模板。4. 在“名称”中输入文件名称“func”。5. 点击“添加”按钮添加并自动打开文件 func.asm。6. 将 getcr3.asm 文件中的源代码复制到 func.asm 文件

56、中。7. 按 F7 生成修改后的 EOS 应用程序项目。8. 按 F5 启动调试。9. 应用程序执行的过程中,会将该进程的二级页表映射信息输出到虚拟机窗口和 OS Lab“输出”窗口中,输出内容如图 16-2(a) 。10. 将“输出”窗口中的内容复制到一个文本文件中。3,查看应用程序进程和系统进程并发时的页目录和页表需要对 EOS 应用程序进行一些修改:1. 结束之前的调试。2. 取消 EOSApp.c 第 121 行语句的注释(该行语句会等待 10 秒) 。3. 按 F7 生成修改后的 EOS 应用程序项目。4. 按 F5 启动调试。5. 在“Console-1”中会自动执行 EOSApp

57、.exe,创建该应用程序进程。利用其等待 10 秒的时间,按 Ctrl+F2 切换到“Console-2” 。6. 在“Console-2”中输入命令“mm”后按回车,会将系统进程的二级页表映射信息输出到虚拟机窗口和 OS Lab 的“输出”窗口,输出内容如图 16-2(b) 。注意,在图 16-2(b)中添加了一些空行,方便与图 16-2(a)比较。 “Console-1”中的应用程序在等待 10 秒后,又会输出和图 16-2(a)一致的内容。7. 将“输出”窗口中的内容复制到一个文本文件中。控制台命令“mm”对应的源代码在 EOS 内核项目 ke/sysproc.c 文件的 Console

58、CmdMemoryMap 函数中(第 382 行) 。阅读这部分源代码后会发现,其与 EOSApp.c 文件中的源代码基本类似。结合图 16-2(a)和(b)回答下面的问题: EOS 启动后系统进程是一直运行的, 所以当创建应用程序进程后, 系统中就同时存在了两个进程,这两个进程是否有各自的页目录?在页目录映射的页表中,哪些是独占的,哪些是共享的?分析其中的原因。 统计当应用程序进程和系统进程并发时,总共有多少物理页被占用?应用程序结束后,在“Console-1”中再次输入命令“mm” ,查看在没有应用程序进程时,系统进程的页目录和页表。将“输出”窗口中的内容复制到一个文本文件中。将输出的内容

59、与图 16-2(b)比较,思考为什么系统进程(即内核地址空间)占用的物理页会减少?(提示:创建应用程序进程时,EOS 内核要为其创建 PCB,应用程序结束时,内核要释放 PCB 占用的内存。 )4, 查看应用程序进程并发时的页目录和页表需要对 EOS 应用程序进行一些修改:1. 结束之前的调试。2. 取消 EOSApp.c 第 201 行语句的注释(该行语句会等待 10 秒) 。3. 按 F7 生成修改后的 EOS 应用程序项目。4. 按 F5 启动调试。5. 在“Console-1”中会自动执行 EOSApp.exe,创建该应用程序进程。利用其等待 10 秒的时间,按Ctrl+F2 切换到“Console-2” 。6. 在“Console-2”中输入“eosapp”后按回车,再执行一个 EOSApp.exe。7. 由 EOSApp.exe 创建的两个并发进程会先后在各自的控制台和 OS Lab“输出”窗口中,输出各自的二级页表映射信息。输出的内容如图 16-3。8. 将“输出”窗口中的内容复制到一个文本文件中。5,在二级页表中映射新申请的物理页下面通过编程的方式,从 EOS 操作系统内核中申请两个未用的物理页,将第一个物理页当作页表,映射基址为 0 xE0000000 的 4M 虚拟地址空间,然后将第二个物理页分别映射到基址为 0 xE0000000 和

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论