华北电力大学 操作系统实验报告.docx
- 文档编号:10279447
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:33
- 大小:1,007.13KB
华北电力大学 操作系统实验报告.docx
《华北电力大学 操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《华北电力大学 操作系统实验报告.docx(33页珍藏版)》请在冰豆网上搜索。
华北电力大学操作系统实验报告
综合实验报告
(2013--2014年度第1学期)
名称:
操作系统综合实验
题目:
基于OSLab的操作系统综合实验
院系:
计算机系
班级:
网络
学号:
201
学生姓名:
指导教师:
王平,王晓辉
设计周数:
1
成绩:
日期:
2013年12月
实验一:
实验环境的使用
一、实验目的:
1、熟悉操作系统集成实验环境OSLab的基本使用方法。
2、练习编译、调试EOS操作系统内核以及EOS应用程序。
二、实验内容:
1、启动OSLab
2、学习OSLab的基本使用方法
3、EOS内核项目的生成和调试
4、EOS应用程序项目的生成和调试
5、退出OSLab
6、保存EOS内核项目
三、实验过程:
本实验实验过程主要按照eos操作系统实验教程上所对应的章节来进行。
实验结果:
(一)启动OSLab:
(无)
(二)学习OSLab的基本使用方法:
(1)、创建了第一个项目:
(2)、生成了第一个项目
(3)、添加了func文件后
经过一系列的调试,打印出了相关内容,按shift+F5结束调试。
(4)、查看变量的值:
有3种方法:
1、将鼠标移动到源代码编辑器中变量n的名称上,此时会弹出一个窗口显示出变量n当前的值(由于此时还没有给变量n赋值,所以是一个随机值)。
2、在源代码编辑器中变量n的名称上点击鼠标右键,在弹出的快捷菜单中选择“快速监视”,可以使用“快速监视”对话框查看变量n的值。
然后,可以点击“关闭”按钮关闭“快速监视”对话框。
3、在源代码编辑器中变量n的名称上点击鼠标右键,在弹出的快捷菜单中选择“添加监视”,变量n就被添加到了“监视”窗口中。
使用“监视”窗口可以随时查看变量的值和类型。
此时按F10进行一次单步调试,可以看到“监视”窗口中变量n的值会变为0
(1)、调用堆栈:
使用“调用堆栈”窗口可以在调试的过程中查看当前堆栈上的函数,还可以帮助理解函数的调用层次和调用过程。
EOS内核项目的生成和调试:
(2)、新建EOS内核项目
(3)、生成项目
(4)、调试项目
(5)、查看软盘镜像文件中的内容
(6)、查看EOSSDK(SoftwareDevelopmentKit)文件夹
EOS应用程序项目的生成和调试
新建EOS应用程序项目
生成项目:
按F7生成项目
调试项目:
按F5进行各种调试
查看软盘镜像文件中的内容:
使用FloppyImageEditor工具打开该项目中的Floppy.img文件,查看软盘镜像中的文件。
L
修改EOS应用程序项目名称
(三)退出
(四)保存
四、实验总结:
经过试验1,我理解了OSLab的基本操作方法和主要用途,这为以后的试验打下了基础。
实验二:
操作系统的启动
一、实验目的
跟踪调试EOS在PC机上从加电复位到成功启动的全过程,了解操作
统的启动过程。
查看EOS启动后的状态和行为,理解操作系统启动后的工作方式。
二、实验内容及其实验步骤
3.1准备实验
1.启动OSLab。
2.新建一个EOSKernel项目。
3.在“项目管理器”窗口中打开boot文件夹中的boot.asm和loader.asm两个汇编文件。
boot.asm是软盘引导扇区程序的源文件,loader.asm是loader程序的源文件。
简单阅读一下这两个文件中的NASM汇编代码和注释。
4.按F7生成项目。
5.生成完成后,使用Windows资源管理器打开项目文件夹中的Debug文件夹。
找到由boot.asm生成的软盘引导扇区程序boot.bin文件,该文件的大小一定为512字节(与软盘引导扇区的大小
一致)。
找到由loader.asm生成的loader程序loader.bin文件,记录下此文件的大小1566字节,在下面的实验中会用到。
找到由其它源文件生成的操作系统内核文件kernel.dll。
3.2调试EOS操作系统的启动过程
3.2.1使用Bochs做为远程目标机
3.2.2调试BIOS程序
启动调试后,Bochs在CPU要执行的第一条指令(即BIOS的第一条指令)处中断。
此时,Display窗口没有显示任何内容,Console窗口显示要执行的BIOS第一条指令的相关信息,并等待用户输入调试命
令,如图10-1:
从Console窗口显示的内容中,我们可以获得关于BIOS第一条指令的如下信息:
行首的[0xfffffff0]表示此条指令所在的物理地址。
l
f000:
fff0表示此条指令所在的逻辑地址(段地址:
偏移地址)。
l
jmpfarf000:
e05b是此条指令的反汇编代码。
l
行尾的ea5be000f0是此条指令的十六进制字节码,可以看出此条指令有5个字节。
接下来可以按照下面的步骤,查看CPU在没有执行任何指令之前主要寄存器中的数据,以及内存中的
数据:
1.在Console窗口中输入调试命令sreg后按回车,显示当前CPU中各个段寄存器的值,如图10-2。
其中CS寄存器信息行中的“s=0xf000”表示CS寄存器的值为0xf000。
2.输入调试命令r后按回车,显示当前CPU中各个通用寄存器的值,如图10-3。
其中“rip:
0x00000000:
0000fff0”表示IP寄存器的值为0xfff0。
3.输入调试命令xp/1024b0x0000,查看开始的1024个字节的物理内存。
在Console中输出的这
1K物理内存的值都为0,说明BIOS中断向量表还没有被加载到此处。
4.输入调试命令xp/512b0x7c00,查看软盘引导扇区应该被加载到的内存位置。
输出的内存值都
为0,说明软盘引导扇区还没有被加载到此处。
3.2.3调试软盘引导扇区程序
3.2.4调试加载程序
3.2.5调试内核
调试内核的步骤如下:
1.在OSLab的“项目管理器”窗口中打开ke文件夹中的start.c文件,此文件中只定义了一个函数,就是操作系统内核的入口点函数KiSystemStartup。
2.在KiSystemStartup函数中的代码行(第61行)KiInitializePic();添加一个断点。
3.现在可以在Console窗口中输入调试命令c继续调试,在刚刚添加的断点处中断。
4.在start.c源代码文件中的KiSystemStartup函数名上点击鼠标右键,在弹出的快捷菜单中选择“添加监视”,KiSystemStartup函数就被添加到了“监视”窗口中。
在“监视”窗口中可以看到此函数地址为{void(PVOID)}0x800*****
5.按F5继续执行EOS操作系统内核,在Display窗口中显示EOS操作系统已经启动,并且控制台EOS操作系统实验教程北京海西慧学科技有限公司126程序已经开始运行了。
3.2.6EOS启动后的状态和行为
查看EOS的版本号:
1.在控制台中输入命令“ver”后按回车。
2.输出EOS版本后的控制台如图10-4所示。
查看EOS启动后的进程和线程的信息:
1.在控制台中输入命令“pt”后按回车。
2.输出的进程和线程信息如图10-5所示。
3.2.6EOS启动后的状态和行为
三.实验总结
通过本实验了解操作系统的启动过程,理解操作系统启动后的工作方式。
实验三:
进程的创建:
一、实验目的:
1、练习使用EOSAPI函数CreateProcess创建一个进程,掌握创建进程的方法,理解进程和程序的区别。
2、调试跟踪CreateProcess函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。
二、实验内容:
1、准备实验:
新建一个EOSKernel项目,分别使用Debug配置和Release配置生成此项目。
新建一个EOS应用程序项目,使用在第EOSKernel生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。
2、练习使用控制台命令创建EOS应用程序的进程
3、练习通过编程的方式让应用程序创建另一个应用程序的进程
4、调试CreateProcess函数
5、调试PsCreateProcess函数
6、练习通过编程的方式创建应用程序的多个进程
三、实验过程:
1、准备实验:
(无)
2、练习使用控制台命令创建EOS应用程序的进程:
使用FloppyImageEditor工具将本实验文件夹内的Hello.exe文件添加到Floppy.img文件中。
启动调试,在EOS的控制台中输入命令“A:
\Hello.exe”后回车。
得到结果:
3、练习通过编程的方式让应用程序创建另一个应用程序的进程:
使用NewProc.c文件中的源代码替换之前创建的EOS应用程序项目中的EOSApp.c文件内的源代码。
启动调试,得到如下结果:
可以看到父进程(EOSApp.exe)首先开始执行并输出内容,父进程创建了子进程(Hello.exe)后,子进程开始执行并输出内容,待子进程结束后父进程再继续执行。
4、调试CreateProcess函数:
按F5启动调试EOS应用程序,在弹出异常对话框后点“是”,在main函数中调用CreateProcess函数的代码行添加一个断点。
5、调试PsCreateProcess函数:
在PsCreateProcess函数中找到调用PspCreateProcessEnvironment函数的代码行添加一个断点。
进入此中断,按F11进入PspCreateProcessEnvironment函数。
在调用ObCreateObject函数的代码行添加一个断点,进入此中断,将表达式*NewProcess添加到“监视”窗口中,监视其值得变化。
接下来调试初始化进程控制块中各个成员变量的过程:
1)首先创建进程的地址空间,即4G虚拟地址空间。
2)按F5继续调试,到此断点处中断。
3)按F10执行此行代码后中断。
4)在“监视”窗口中查看进程控制块的成员变量Pas的值已经不再是0。
说明已经初始化了进程的4G虚拟地址空间。
5)使用F10一步步调试PspCreateProcessEnvironment函数中后面的代码,在调试的过程中根据执行的源代码,查看“监视”窗口中*NewProcess表达式的值,。
6)当从PspCreateProcessEnvironment函数返回到PsCreateProcess函数后,停止按F10。
此时“监视”窗口中已经不能再显示表达式*NewProcess的值了,在PsCreateProcess函数中是使用ProcessObject指针指向进程控制块的,所以将表达式*ProcessObject添加到“监视”窗口中就可以继续观察新建进程控制块中的信息。
7)接下来继续使用F10一步步调试PsCreateProcess函数中的代码,同样要注意观察执行后的代码修改了进程控制块中的哪些成员变量。
8)按F5继续执行,EOS内核会为刚刚初始化完毕的进程控制块新建一个进程。
激活虚拟机窗口查看新建进程执行的结果。
9)在OSLab中选择“调试”菜单中的“停止调试”结束此次调试。
10)选择“调试”菜单中的“删除所有断点”。
结果:
代码:
/*
提供该示例代码是为了阐释一个概念,或者进行一个测试,并不代表着
最安全的编码实践,因此不应在应用程序或网站中使用该示例代码。
对
于超出本示例代码的预期用途以外的使用所造成的偶然或继发性损失,
北京海西慧学科技有限公司不承担任何责任。
*/
#include"EOSApp.h"
//
//main函数参数的意义:
//argc-argv数组的长度,大小至少为1,argc-1为命令行参数的数量。
//argv-字符串指针数组,数组长度为命令行参数个数+1。
其中argv[0]固定指向当前
//进程所执行的可执行文件的路径字符串,argv[1]及其后面的指针指向各个命令行
//参数。
//例如通过命令行内容"a:
\hello.exe-a-b"启动进程后,hello.exe的main函
//数的参数argc的值为3,argv[0]指向字符串"a:
\hello.exe",argv[1]指向
//参数字符串"-a",argv[2]指向参数字符串"-b"。
//
intmain(intargc,char*argv[])
{
//
//启动调试EOS应用程序前要特别注意下面的问题:
//
//1、如果要在调试应用程序时能够调试进入内核并显示对应的源码,
//必须使用EOS核心项目编译生成完全版本的SDK文件夹,然
//后使用此文件夹覆盖应用程序项目中的SDK文件夹,并且EOS
//核心项目在磁盘上的位置不能改变。
//
//2、在启动调试应用程序之前必须首先删除/禁用所有的断点,在断
//点中断(int3)被命中后才能重新添加/启用断点,否则启动
//调试会失败。
//
STARTUPINFOStartupInfo;
PROCESS_INFORMATIONProcInfoOne[5];
ULONGulExitCode;//子进程退出码
INTnResult=0;//main函数返回值。
0表示成功,非0表示失败。
#ifdef_DEBUG
__asm("int$3\nnop");
#endif
printf("Createtwoprocessesandwaitfortheprocessesexit...\n\n");
//
//使子进程和父进程使用相同的标准句柄。
//
StartupInfo.StdInput=GetStdHandle(STD_INPUT_HANDLE);
StartupInfo.StdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
StartupInfo.StdError=GetStdHandle(STD_ERROR_HANDLE);
//
//为一个应用程序同时创建两个子进程。
//
inti=0;
for(;i<5;i++)
{
if(CreateProcess("A:
\\Hello.exe",NULL,0,&StartupInfo,&ProcInfoOne[i])){
//
//创建子进程成功,等待子进程运行结束。
//
WaitForSingleObject(ProcInfoOne[i].ProcessHandle,INFINITE);
//WaitForSingleObject(ProcInfoTwo.ProcessHandle,INFINITE);
//
//得到并输出子进程的退出码。
//
GetExitCodeProcess(ProcInfoOne[i].ProcessHandle,&ulExitCode);
printf("\nTheprocessoneexitwith%d.\n",ulExitCode);
//GetExitCodeProcess(ProcInfoTwo.ProcessHandle,&ulExitCode);
//printf("\nTheprocesstwoexitwith%d.\n",ulExitCode);
//
//关闭不再使用的句柄。
//
CloseHandle(ProcInfoOne[i].ProcessHandle);
CloseHandle(ProcInfoOne[i].ThreadHandle);
//CloseHandle(ProcInfoTwo.ProcessHandle);
//CloseHandle(ProcInfoTwo.ThreadHandle);
}else{
printf("CreateProcessFailed,Errorcode:
0x%X.\n",GetLastError());
nResult=1;
}
}
returnnResult;
}
实验四:
线程的状态和转换
一、实验目的:
1、调试线程在各种状态间的转换过程,熟悉线程的状态和转换。
2、通过为线程增加挂起状态,加深对线程状态的理解。
二、实验内容及步骤:
1、准备实验:
新建一个EOSKernel项目。
2、调试线程状态的转换过程:
对第一步的项目启动调试,待EOS启动完毕,在EOS控制台中输入命令“loop”后按回车。
得到结果:
结束调试。
1.控制台派遣线程被唤醒,由阻塞状态进入就绪状态。
2.loop线程由运行状态进入就绪状态。
3.控制台派遣线程由就绪状态进入运行状态。
4.待控制台派遣线程处理完毕由于空格键被按下而产生的键盘事件后,派遣线程会由运行状态重新进入阻塞状态,开始等待下一个键盘事件到来。
5.loop线程由就绪状态进入运行状态,继续执行死循环。
按F5继续执行,在PspSelectNextThread函数中的断点处中断。
。
按F5继续执行,在PspUnreadyThread函数中的断点处中断。
在快速监视对话框中查看“*Thread”表达式的值。
关闭快速监视对话框后,在“调用堆栈”窗口中激活PspSelectNextThread函数对应的堆栈项,在“调用堆栈”窗口中激活PspUnreadyThread函数对应的堆栈项,然后按F10单步调试,直到返回PspSelectNextThread函数并将线程状态修改为Running。
按F5继续执行,在PspWait函数中的断点处中断。
3、为线程增加挂起状态:
删除之前添加的所有断点。
按F5启动调试。
待EOS启动完毕,在EOS控制台中输入命令“loop”后按回车。
此时可以看到loop线程的执行计数在不停增长,说明loop线程正在执行。
记录下loop线程的ID。
按Ctrl+F2切换到控制台2,输入命令“suspend31”(如果loop线程的ID是31)后按回车。
命令执行成功的结果如图12-2所示。
按Ctrl+1切换回控制台1,可以看到由于loop线程已经成功被挂起,其执行计数已经停止增长了。
此时占用处理器的是EOS中的空闲线程。
Resume原语可以将一个被Suspend原语挂起的线程(处于静止就绪状态)恢复为就绪状态。
但是PsResumThread函数中的这部分代码(第119行),完成这部分代码。
代码:
/*
提供该示例代码是为了阐释一个概念,或者进行一个测试,并不代表着
最安全的编码实践,因此不应在应用程序或网站中使用该示例代码。
*/
STATUS
PsResumThread(
INHANDLEhThread
)
/*++
功能描述:
恢复指定的线程。
参数:
hThread-需要被恢复的线程的句柄。
返回值:
如果成功则返回STATUS_SUCCESS。
--*/
{
STATUSStatus;
BOOLIntState;
PTHREADThread;
//
//根据线程句柄获得线程对象的指针
//
Status=ObRefObjectByHandle(hThread,PspThreadType,(PVOID*)&Thread);
if(EOS_SUCCESS(Status)){
IntState=KeEnableInterrupts(FALSE);//关中断
if(Zero==Thread->State){
//
//将线程从挂起线程队列中移除。
//
ListRemoveEntry(&Thread->StateListEntry);
//
//将挂起的线程恢复为就绪状态。
//线程由静止就绪状态(StaticReady)进入活动就绪状态(ActiveReady)。
//
PspReadyThread(Thread);
//
//执行线程调度,让刚刚恢复的线程有机会执行(如果真的能够调度到它的话)。
//
PspThreadSchedule();
Status=STATUS_SUCCESS;
}else{
Status=STATUS_NOT_SUPPORTED;
}
KeEnableInterrupts(IntState);//开中断
ObDerefObject(Thread);
}
returnStatus;
}
测试方法:
待读者完成Resume原语后,可以先使用suspend命令挂起loop线程,然后在控制台2中输入命令“Resume31”(如果loop线程的ID是31)后按回车。
思考题:
思考一下,在本实验中,当loop线程处于运行状态时,EOS中还有哪些线程,它们分别处于什么状态。
可以使用控制台命令pt查看线程的状态。
三、实验总结:
明白了loop指令的用法以及resume原语的结构。
实验五:
进程的同步
一、实验目的:
1、使用EOS的信号量,编程解决生产者—消费者问题,理解进程同步的意义。
2、调试跟踪EOS信号量的工作过程,理解进程同步的原理。
3、修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。
二、实验内容和步骤:
1、准备实验:
新建一个EOSKernel项目。
生成EOSKernel项目,从而在该项目文件中生成SDK文件夹。
新建一个EOS应用程序项目。
使用在第3步生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。
2、使用EOS的信号量解决生产者-消费者问题:
在本实验文件夹中,提供了使用EOS的信号量解决生产者-消费者问题的参考源代码文件pc.c,仔细阅读此文件中的源代码和注释。
使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码。
按F5启动调试。
立即激活虚拟机窗口查看生产者-消费者同步执行的过程。
结果:
3、调试EOS信号量的工作过程:
启动调试,在main函数中创建Empty信号量的代码行添加一个断点。
按F5继续调试,到此断点处中断。
按F11调试进入CreateSema
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 华北电力大学 操作系统实验报告 华北电力 大学 操作系统 实验 报告