操作系统实验报告 附思考题解读Word下载.docx
- 文档编号:22417868
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:34
- 大小:1.35MB
操作系统实验报告 附思考题解读Word下载.docx
《操作系统实验报告 附思考题解读Word下载.docx》由会员分享,可在线阅读,更多相关《操作系统实验报告 附思考题解读Word下载.docx(34页珍藏版)》请在冰豆网上搜索。
快速监视
添加监视
2.2.4调用堆栈
调用堆栈显示内容
进入Func函数
双击main函数所在的行表示此函数是当前调用堆栈中的活动函数。
3新建EOS内核项目
4EOS应用程序项目的生成和调试
4.1新建EOS应用程序项目
4.2调试项目
添加断点后单步调试结果显示
4.3查看软盘镜像文件中的内容
4.4修改EOS应用程序项目名称
5退出OSLab
6保存EOS内核项目
三、综合实验总结或结论
思考与练习:
1.在哪些情况下应该使用“逐过程”调试,在哪些情况下应该使用“逐语句”调试。
答:
逐语句为每执行一行语句,如果碰到函数调用它就会进入到函数里面。
而逐过程碰到函数时不进入函数,把函数调用当成一条语句去执行。
2.生成EOSSDK文件夹的目的和作用。
明白文件夹的组织结构和各个文件的来源和作用。
查看EOS应用程序包含了SDK文件夹中的哪些头文件,是如何包含的?
(1)EOS
SDK为应用程序调用系统API提供服务,可作为用户编程中使用的工具包集合。
(2)其主要包括INC头文件LIB文件夹、导入库文件和BIN文件夹、动态链接库、可执行程序、二进制文件。
(3)包含的头文件有:
eos.h负责导出API函数,eosdef.h声明负责导出函数类型的定义,error.h负责导出错误码。
(4)EOS应用程序在项目的头文件中只是包含了eos.h文件,在eos.h文件中又包含了eosdef.h和error.h文件。
实验2操作系统的启动
跟踪调试EOS在PC机上从加电复位到成功启动全过程,了解操作系统的启动过程。
查看EOS启动后的状态和行为,理解操作系统启动后的工作方式。
1.准备实验
新建一个EOSKernel项目。
打开boot.asm和loader.asm两个汇编文件。
生成项目。
找到loader.bin文件,记录下此文件的大小1566字节。
2调试EOS操作系统的启动过程
2.1使用Bochs做为远程目标机
找到“远程目标机”属性,将此属性值修改为“BochsDebug”
2.2调试BIOS程序
2.2.1在Console窗口中输入调试命令sreg后按回车,其中CS寄存器信息行中的“s=0xf000”表示CS寄存器的值为0xf000。
2.2.2输入调试命令r后按回车,显示当前CPU中各个通用寄存器的值。
其中“rip:
0x00000000:
0000fff0”表示IP寄存器的值为0xfff0。
2.2.3输入调试命令xp/1024b0x0000,查看开始的1024个字节的物理内存。
在Console中输出的这1K物理内存的值都为0,说明BIOS中断向量表还没有被加载到此处。
2.2.4输入调试命令xp/512b0x7c00,查看软盘引导扇区应该被加载到的内存位置。
输出的内存值都为0,说明软盘引导扇区还没有被加载到此处。
可以验证BIOS第一条指令所在逻辑地址中的段地址和CS寄存器值是一致的,偏移地址和IP寄存器值是一致的。
由于内存还没有被使用,所以其中的值都为0。
2.3调试软盘引导扇区程序
2.3.1.输入调试命令vb0x0000:
0x7c00,添加断点
2.3.2.输入调试命令c继续执行
2.3.3.输入调试命令sreg验证CS寄存器(0x0000)的值。
2.3.4.输入调试命令r验证IP寄存器(0x7c00)的值。
2.3.5输入调试命令xp/1024b0x0000验证此时BIOS中断向量表已经被载入。
2.3.6.输入调试命令xp/512b0x7c00显示软盘引导扇区程序的所有字节码。
2.3.7输入调试命令xp/512b0x0600验证图3-2中第一个用户可用区域是空白的。
2.3.8输入调试命令xp/512b0x7e00验证图3-2中第二个用户可用区域是空白的。
2.3.9自己设计两个查看内存的调试命令,验证这两个用户可用区域的高地址端是空白的。
(1)xp/512b0x7f00
(2)xp/512b0x0700
2.3.10输入调试命令xp/512b0xa0000验证图3-2中上位内存已经被系统占用。
2.3.11自己设计一个查看内存的调试命令,验证上位内存的高地址端已经被系统占用。
xp/512b0xb0000
2.3.12输入调试命令xp/8b0x1000查看内存0x1000处的数据,验证此块内存的前三个字节和loader.lst文件中的第一条指令的字节码是相同的。
2.3.13根据之前记录的loader.bin文件的大小,自己设计一个查看内存的调试命令
loader.bin文件的大小为1566个字节,转换为十六进制的61E,所以程序最后八个字节在物理内存的0x1616到0x161D的位置,所以调试命令为xp/8b0x1616。
经检验,loader.bin程序结束位置字节码与反汇编命令相同。
注:
查看loader.bin文件的大小应在“属性”对话框中看。
2.4调试加载程序
使用查看虚拟内存的调试命令x/1wx0x80001117查看内存中保存的32位函数入口地址,在Console窗口中会输出:
0x0000000080001117<
bogus+0>
:
0x800*****
2.5调试内核
在“监视”窗口中可以看到KiSystemStartup函数地址为
{void(PVOID)}0x800*****KiSystemStartup>
2.6EOS启动后的状态和行为
1.为什么EOS操作系统从软盘启动时要使用boot.bin和loader.bin两个程序?
使用一个可以吗?
它们各自的主要功能是什么?
如果将loader.bin的功能移动到boot.bin文件中,则boot.bin文件的大小是否仍然能保持小于512字节?
在IDE环境启动执行EOS操作系统时,会将boot.bin,loader.bin,kernal.dll三个二进制写入软件镜像文件中,然后让虚拟机来执行软盘中的EOS操作系统,使用其中一个是不能运行的。
2.为什么软盘引导扇区程序选择将loader.bin加载到第一个可用区域的0x1000处呢?
这样做有什么好处?
这样做会对loader.bin文件的大小有哪些限制。
用户只用两个可用区域,加载位置非此即彼。
第一个可用用户区是低地址区,且空间大小比较小,适合容纳小文件,所以我们选择将占用空loder.bin加载到第一用户区。
优点:
低地址开始,便于搜索查找小文件占用小空间,节约资源。
限制:
loder.bin文件必须小于1c00k。
实验3进程的创建
练习使用EOSAPI函数CreateProcess创建一个进程,掌握创建进程的方法,理解进程和程序的区别。
调试跟踪CreateProcess函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。
1准备实验
2练习使用控制台命令创建EOS应用程序的进程
Hello.exe应用程序输出结果
3练习通过编程的方式让应用程序创建另一个应用程序的进程
可知子进程结束后,父进程继续执行
4调试CreateProcess函数
在“反汇编”窗口的左侧显示的虚拟地址中看到所有指令的虚拟地址都大于0x80000000,说明内核(kernel.dll)处于高2G的虚拟地址空间中。
查看main函数的指令所在的虚拟地址都是小于0x80000000,说明应用程序(eosapp.exe)处于低2G的虚拟地址空间中。
5调试PsCreateProcess函数
进程执行的结果:
绘制一幅进程创建过程的流程图。
6练习通过编程的方式创建应用程序的多个进程
多个进程并发执行的结果
有结果显示可知有两个进程在执行
1.在源代码文件NewTwoProc.c提供的源代码基础上进行修改,要求使用hello.exe同时创建10个进程。
修改结果如下图所示:
部分修改代码如下图所示:
(“……”部分为相似的4-9进程代码)
if(CreateProcess("
A:
\\Hello.exe"
NULL,0,&
StartupInfo,&
ProcInfoOne)
&
&
CreateProcess("
ProcInfoTwo)
ProcInfo3)……
&
ProcInfo10)){
WaitForSingleObject(ProcInfoOne.ProcessHandle,INFINITE);
WaitForSingleObject(ProcInfoTwo.ProcessHandle,INFINITE);
WaitForSingleObject(ProcInfo3.ProcessHandle,INFINITE);
……
WaitForSingleObject(ProcInfo10.ProcessHandle,INFINITE);
GetExitCodeProcess(ProcInfoOne.ProcessHandle,&
ulExitCode);
GetExitCodeProcess(ProcInfo3.ProcessHandle,&
printf("
\nTheprocess3exitwith%d.\n"
ulExitCode);
GetExitCodeProcess(ProcInfo10.ProcessHandle,&
\nTheprocess10exitwith%d.\n"
CloseHandle(ProcInfoOne.ProcessHandle);
CloseHandle(ProcInfoTwo.ThreadHandle);
CloseHandle(ProcInfo3.ProcessHandle);
CloseHandle(ProcInfo3.ThreadHandle);
CloseHandle(ProcInfo10.ProcessHandle);
CloseHandle(ProcInfo10.ThreadHandle);
2.在PsCreateProcess函数中调用了PspCreateProcessEnvironment函数后又先后调用了PspLoadProcessImage和PspCreateThread函数,学习这些函数的主要功能。
能够交换这些函数被调用的顺序吗?
PspCreateProcessEnvironment
创建了进程控制块,地址空间和分配了句柄表,PspLoadProcessImage将进程的可执行映象加载的到了进程的地址空间中,PspCreateThread创建了进程的主线程。
这三个函数知道自己从哪里开始执行,执行哪些指令,因此不能交换它们的顺序。
实验4线程的状态和转换
调试线程在各种状态间的转换过程,熟悉线程的状态和转换。
通过为线程增加挂起状态,加深对线程状态的理解。
2调试线程状态的转换过程
2.1线程由阻塞状态进入就绪状态
“*Thread”State域的值为3(Waiting)
,双向链表项StateListEntry
的Next和Prev指针的值都不为0
,说明这个线程还处于阻塞状态,并在某个同步对象的等待队列中;
StartAddr域的值为IopConsoleDispatchThread
,说明这个线程就是控制台派遣线程。
在“调用堆栈”窗口中双击PspUnwaitThread函数对应的堆栈项,按F10调试,此时State域的值为0(Zero)
,双向链表项StateListEntry的Next和Prev指针的值都为0
,说明这个线程已经处于游离状态。
按F5继续执行,在PspReadyThread函数中的断点处中断。
按F10单步调试直到此函数的最后。
此时State域的值为1(Ready)
,双向链表项StateListEntry的Next和Prev指针的值都不为0
,说明这个线程已经处于就绪状态,并已经被放入优先级为24的就绪队列中。
2.2线程由运行状态进入就绪状态
2.3线程由就绪状态进入运行状态
2.4线程由运行状态进入阻塞状态
3为线程增加挂起状态
1.思考一下,在本实验中,当loop线程处于运行状态时,EOS中还有哪些线程,它们分别处于什么状态。
可以使用控制台命令pt查看线程的状态。
有一个优先级为0的空闲线程处于就绪状态,8个优先级为24的控制台线程处于阻塞状态,1个优先级的24的控制台派遣线程处于阻塞状态。
2.当loop线程在控制台1中执行,并且在控制台2中执行suspend命令时,为什么控制台1中的loop线程处于就绪状态而不是运行状态?
在控制台2中执行suspend命令时,优先级为24的控制台2线程抢占处理器,即控制台2线程处于运行状态,因此此时loop处于就绪状态。
3.总结一下在图5-3中显示的转换过程,哪些需要使用线程控制块中的上下文,哪些不需要使用,并说明原因。
就绪→运行,运行→就绪,运行→阻塞需要使用TCB因为这些过程有线程调进或调出处理机的过程,新建→就绪,阻塞→就绪不需要使用TCB上下文,因为没有占用处理机资源。
4.请读者找出这些转换过程的原语操作(关中断和开中断)是在哪些代码中完成的。
IntState=KeEnableInterrupts(FALSE);
//关中断
KeEnableInterrupts(IntState);
//开中断
实验5进程的同步
1、综合实验的目的与要求
使用EOS的信号量,编程解决生产者—消费者问题,理解进程同步的意义。
调试跟踪EOS信号量的工作过程,理解进程同步的原理。
修改EOS的信号量算法,使之支持等待超时唤醒功能,加深理解进程同步的原理。
2、实验正文
2使用EOS的信号量解决生产者-消费者问题
3调试EOS信号量的工作过程
3.1创建信号量
PsInitializeSemaphore函数中用来初始化信号量结构体成
员的值,应该和传入CreateSemaphore函数的参数值是一致的。
单步调试PsInitializeSemaphore函数执行的过程,函数的调用层次:
先
再
3.2等待、释放信号量
3.2.1等待信号量(不阻塞)
完成PsWaitForSemaphore函数中所有操作。
Empty的计数减少了1(由10变为了9)
3.2.2释放信号量(不唤醒)
完成PsReleaseSemaphore函数中的所有操作。
Full计数增加了1(由0变为了1)。
3.2.3等待信号量(阻塞)
在“调用堆栈”窗口中双击Producer函数所在的堆栈帧,绿色箭头指向等待Empty信号量的代码行,查看Producer函数中变量i的值为14,表示生产者线程正在尝试生产14号产品。
在“调用堆栈”窗口中双击PsWaitForSemaphore函数的堆栈帧,查看Empty信号量计数(Semaphore->
Count)的值为-1.
3.2.4释放信号量(唤醒)
Consumer函数中变量i的值为4,说明已经消费了4号产品。
查看PsReleaseSemaphore函数中Empty信号量计数(Semaphore->
Count)的值为-1,和生产者线程被阻塞时的值是一致的。
单步调试PsReleaseSemaphore函数,Empty计数的值已经由-1增加为了0
4修改EOS的信号量算法
(1)修改PsWaitForSemaphore函数:
if
(Semaphore->
Count
>
0){
Semaphore->
Count--;
flag=STATUS_SUCCESS;
}
else{
flag=PspWait(&
Semaphore->
WaitListHead,
Milliseconds);
return
flag;
(2)修改PsReleaseSemaphore函数:
while
((!
ListIsEmpty(&
WaitListHead))&
(ReleaseCount)){
PspWakeThread(&
STATUS_SUCCESS);
PspThreadSchedule();
ReleaseCount--;
}
Count=Semaphore->
Count+ReleaseCount;
Status
=
STATUS_SUCCESS;
KeEnableInterrupts(IntState);
return
Status;
测试结果:
根据文档中的测试方法可看到结果中有两个消费者
1.思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?
EOS内核中维护了大量内核数据,正是这些数据描述了EOS操作系统的状态如果有一组相互关联的内核数据共同描述了这个操作系统的某个状态,那么在修改这样一组内核数据时就必须保证一致性。
这就要求修改这部分数据的代码在执行过程中不能被打断,这种操作叫做“原语操作”。
2.根据本实验3.3.2节中设置断点和调试的方法,自己设计一个类似的调试方案来验证消费者线程在消费24号产品时会被阻塞,直到生产者线程生产了24号产品后,消费者线程才被唤醒并继续执行的过程。
生产到23号产品后,进程阻塞。
实验6时间片轮转调度
1、综合实验的目的与要求
调试EOS的线程调度程序,熟悉基于优先级的抢先式调度。
为EOS添加时间片轮转调度,了解其它常用的调度算法。
2阅读控制台命令“rr”相关的源代码
3调试线程调度程序
3.1调试当前线程不被抢先的情况
查看ThreadFunction函数中变量pThreadParameter->
Y的值应该为0,说明正在调试的是第0个新建的线程。
按2次F5的循环输出的内容:
以二进制格式查看就绪位图的值
BitScanReverse函数会从就绪位图中扫描最高优先级,并保存在变量HighestPriority中。
查看变量HighestPriority的值为8。
3.2调试当前线程被抢先的情况
激活虚拟机窗口,可以看到第0个新建的线程正在执行。
在“监视”窗口中查看就绪位图的值为1000000000000000100000001,说明此时在优先级为24的就绪队列中存在就绪线程。
在“监视”窗口中添加表达式“ListGetCount(&
PspReadyListHeads[24])”,其值为1,说明优先级为24的就绪队列中只有一个就绪线程。
扫描就绪位图后获得的最高优先级的值HighestPriority也就应该是24。
显示0x18=24
继续调试优先级24的线程已经进入了“运行”状态。
4为EOS添加时间片轮转调度
修改部分代码:
VOID
PspRoundRobin(
){
if(NULL!
=PspCurrentThread&
Running==PspCurrentThread->
State)
{
PspCurrentThread->
RemainderTicks--;
(0
==
RemainderTicks)
PspCurrentThread->
RemainderTicks
TICKS_OF_TIME_SLICE;
if(BIT_TEST(PspReadyBitmap,
Priority))
PspReadyThread(PspCurrentThread);
}}
测试:
能看到20个线程轮流执行的效果
5修改线程时间片的大小
执行的效果:
参数=20参数=100
时间片过大,算法便退化成为先进先出算法。
1.结合线程调度执行的时机,说明在ThreadFunction函数中,为什么可以使用“关中断”和“开中断”方法来保护控制台这种临界资源。
结合线程调度的对象说明这样做的原因。
EOS会设置CPU停止响应外部设备产生的硬中断,也就不会在由硬中断触
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统实验报告 附思考题解读 操作系统 实验 报告 思考题 解读
![提示](https://static.bdocx.com/images/bang_tan.gif)