操作系统实验报告(2)

2018-11-27 09:37

1 、准备实验

2 、使用EOS的信号量解决生产者-消费者问题 3 、调试EOS信号量的工作过程 4、 修改EOS的信号量算法 if (Semaphore->Count>0){ Semaphore->Count--; flag=STATUS_SUCCESS;

}//如果信号量大于零,说明尚有资源,可以为线程分配 else

flag=PspWait(&Semaphore->WaitListHead, Milliseconds); KeEnableInterrupts(IntState); // 原子操作完成,恢复中断。 return flag;

}//否则,说明资源数量不够,不能再为线程分配资源,因此要使线程等待

if (Semaphore->Count + ReleaseCount > Semaphore->MaximumCount) {Status = STATUS_SEMAPHORE_LIMIT_EXCEEDED;} Else{

//记录当前的信号量的值//

if(NULL!=PreviousCount){*PreviousCount=Semaphore->Count;} int mm=Semaphore->Count;

//目前仅实现了标准记录型信号量,每执行一次信号量的释放操作 只能使信号量的值增加1.//

while ((!ListIsEmpty(&Semaphore->WaitListHead))&&(ReleaseCount)){ PspWakeThread(&Semaphore->WaitListHead, STATUS_SUCCESS); PspThreadSchedule(); ReleaseCount--; }

Semaphore->Count=mm+ReleaseCount; //可能有线程被唤醒,执行线程调度。// Status=STATUS_SUCCESS:} 三、问题答案及参考代码

1.思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?

答:在执行释放信号量和等待信号量时,是不允许CPU响应外部中断的,否则,会产生不可预料的结果。

4.根据本实验3.3.2节中设置断点和调试的方法,自己设计一个类似的调 试方案来验证消费者线程在消费24号产品时会被阻塞, 直到生产者线程生产了24 号产品后,消费者线程才被唤醒并继续执行的过程。

答:调试方案如下: ① 删除所有的断点。 ② 按F5启动调试。OS Lab会首先弹出一个调试异常对话框。 ③ 在调试异常对话框中选择“是”,调试会中断。 ④ 在Consumer函数中等待Full信号量的代码行(第173行) WaitForSingleObject(FullSemaphoreHandle, INFINITE); 添加一个断点。 ⑤ 在“断点”窗口(按Alt+F9打开)中此断点的名称上点击右键。 ⑥ 在弹出的快捷菜单中选择“条件”。 ⑦ 在“断点条件”对话框(按F1获得帮助)的表达式编辑框中,输入表达式“i == 24”。 ⑧ 点击“断点条件”对话框中的“确定”按钮。 ⑨ 按F5继续调试。只有当消费者线程尝试消费24号产品时才会在该条件断 点处中断。

实验6 时间片轮转调度

一、实验目的

调试EOS的线程调度程序,熟悉基于优先级的抢先式调度。 为EOS添加时间片轮转调度,了解其它常用的调度算法。 二、实验内容 1 、准备实验

2、 阅读控制台命令“rr”相关的源代码 3、调试线程调度程序

4 、为EOS添加时间片轮转调度 VOID

PspRoundRobin(VOID) {

if(NULL!=PspCurrentThread&&Running==PspCurrentThread->State) {

PspCurrentThread->RemainderTicks--; if(0==PspCurrentThread->RemainderTicks){

PspCurrentThread->RemainderTicks=TICKS_OF_TIME_SLICE; if(BIT_TEST(PspReadyBitmap, PspCurrentThread->Priority)) {PspReadyThread(PspCurrentThread);}}

二、 问题答案及参考代码

1. 结合线程调度执行的时机,说明在ThreadFunction函数中,为什么可以使用“关中断”和“开中断”的方法来保护控制台这种临界资源。一般情况下,应该使用互斥信号量(MUTEX)来保护临界资源,但是在ThreadFunction函数中却不能使用互斥信号量,而只能使用“关中断”和“开中断”的方法,结合线程调度的对象说明这样做的原因。

答:关中断后CPU就不会响应任何由外部设备发出的硬中断(包括定时计数器中断和键盘中断等)了,也就不会发生线程调度了,从而保证各个线程可以互斥的访问控制台。这里绝对不能使用互斥信号量(mutex)保护临界资源的原因:如果使用互斥信号量,则那些由于访问临界区而被阻塞的线程,就会被放入互斥信号量的等待队列,就不会在相应优先级的就绪列中了,而时间轮转调度算法是对就绪队列的线程进行轮转调度,而不是对这些被阻塞的线程进行调度,也就无法进行实验了。使用“关中断”和“开中断”进行同步就不会改变线程的状态,可以保证那些没有获得处理器的线程都在处于就绪队列中。

3.使用低优先级线程也能获得执行机会的调度算法:在ke/sysproc.c文件中的ConsoleCmdRoundRobin函数调用Sleep函数语句的后面添加下面的语言,即可以演优先级线程抢占处理器后,低优先级线程无法运行的情况,待高优先级线程结束后,低优先级线程才能够继续运行。

HANDLE ThreadHandle;

THREAD_PARAMETER ThreadParameter; _asm(“cli”);

ThreadParameter.Y=20;

ThreadParameter.StdHandle=StdHandle; ThreadParameter=(HANDLE)CreateThread{

0,ThreadFunction,(PVOID)&ThreadParameter,0,NULL); PsSetThreadPriority(ThreeadHandle,9); _asm(“sti”); Sleep(10*1000);

TerminateThread(ThreadHandle,0); CloseHandle(ThreadHandle); Sleep(10*1000);

解决该问题的最简单的方法是实现动态优先级算法。动态优先级是指在创建进程时所赋予的优先级,可以随线程的推进而改变,以便获得良好的调度性能。例如,可用规定,在就绪队列中的线程,随着其等待时间的增长,其优先级以速率X增加,并且正在执行的线程,其优先级以速率y下降。这样,在各个线程具有不同优先级的情况下,对于优先级低的线程,在等待足够的时间后,其优先级便可能升为最高,从而获得被执行的机会。此时,在基于优先级的抢占式调度算法、时间片轮转调度算法和动态优先级算法的共同作用下,可防止一个高优先级的长作业长期的垄断处理器。

4.EOS内核时间片大小取60ms(和Windows操作系统完全相同),在线程比较多时,就可以观察出线程轮流执行的情况(因为此时一次轮转需要60ms,20个线程轮流执行一次需要60×20=1200ms,也就是需要1秒多的时间,所以EOS的控制台上可以清楚地观察到线程轮流执行的情况)。但是在Windows、Linux等操作系统启动后,正常情况下都有上百个线程在并发执行,为什么觉察不到它们被轮流执行, 并且每个程序都运行的很顺利呢?

答:在Windows、linux等操作系统中,虽然都提供了时间片轮转调度算法却很少真正被派上用场,下面解释原因,在Windows任务管理器中,即使系统中已经运行了数百个线程,

但CPU的利用率仍然很低,甚至为0.因为这些线程在大部分时间都处于阻塞状态,阻塞的原因是各种各样的,最主要的原因是等待I/O完成或者等待命令消息的到达。例如,在编辑Word文档时,每敲击一次键盘,Word就会立即作出反应,并且文档中插入字符。此时会感觉Word运行的非常流畅。事实上,并非如此,Word主线程大部分时间都处于阻塞等待状态,等待用户敲击键盘。在用户没有敲击键盘或没有使用鼠标点击时,Word主线程处于阻塞状态,它将让出处理器给其它需要的线程。当用户敲击一个按键后,Word主线程将会立刻被操作系统唤醒,此时Word开始处理请求。Word在处理输入请求时所用的CPU时间是非常短的(因为CPU非常快),是微秒级的,远远低于时间片轮转调度的时间片大小(Windows下是60毫秒),处理完毕后Word又立刻进入阻塞状态,等待用户下一次敲击键盘。或者拿音乐播放器来分析,表面上感觉播放器在不停地播放音乐,但是CPU的利用率仍然会很低。这是由于播放器将一段声音编码交给声卡,由声卡来播放,在声卡播放完这段声音之前,播放器都是处于阻塞等待状态的。当声卡播放完片段后,播放器将被唤醒,然后它将下一个声音片段交给声卡继续播放。掌握了上面的知识后,就可以很容易解释为什么这么多线程同时在运行而一点都感觉不到轮替现象。

实验7 物理存储器与进程逻辑地址空间的管理

一、实验目的

通过查看物理存储器的使用情况,并练习分配和回收物理内存,从而掌握物理存储器的管理方法。

通过查看进程逻辑地址空间的使用情况,并练习分配和回收虚拟内存,从而掌握进程逻辑地址空间的管理方法。 二、实验内容

1 、准备实验

2 、阅读控制台命令“pm”相关的源代码,并查看其执行的结果(pm命令的执行结果) 3 、分配物理页和释放物理页(配物理页或者释放物理页后物理存储器的变化情况) 4、阅读控制台命令“vm”相关的源代码,并查看其执行的结果 使用“vm”命令查看系统进程虚拟地址描述符的结果

5 、在系统进程中分配虚拟页和释放虚拟页 6 、在应用程序进程中分配虚拟页和释放虚拟页 三、问题答案及参考代码 INT *d;

if(d=VirtualAlloc(0,sizeof(int),MEM_RESERVE|MEM_COMMIT)){// 调用API函数VirtualAlloc,分配一个整型变量所需的空间,并使用一个整型变量的指针指向这个空间 printf(\ printf(\ *d = 0xFFFFFFFF;// 修改整型变量的值为0xFFFFFFFF

printf(\ printf(\

Sleep(10000);// 调用API函数Sleep,等待10秒钟。

if(VirtualFree(d,0,MEM_RELEASE))// 调用API函数VirtualFree,释放之前分配的整型变量的空间

printf(\ else

printf(\ printf(\ for(;;); } else {

printf(\

return -1;//若不能成功分配,打印出error ,返回-1. }

printf(\return 0;

1. 在本实验3.3中,如果分配了物理页后,没有回收,会对EOS操作系统造成什么样的影响?目前EOS操作系统内核函数MiAllocateAnyPages能处理所有物理页被分配完毕的情况吗?例如在没有可分配的物理页的情况下调用该内核函数,是否会返回失败?如果内核函数MiAllocateAnyPages还不能处理这种极端情况,尝试修改代码解决这个问题。

答:如果分配了物理页后没有回收,EOS 操作系统将不能再使用未回收的物理页,如果分配的物理页都没有进行回收可能会造成EOS没有可用的物理页,从而导致EOS停止运行。目前EOS操作系统内核函数MiAllocateAnyPages还没有处理没有物理页可分配的情况。 2. 在本实验3.3中,在分配物理页时是调用的内核函数MiAllocateAnyPages,该函数会优先分配空闲页,尝试修改代码,调用内核函数MiAllocateZeroedPages优先分配零页,并调试分配零页的情况。尝试从性能的角度分析内核函数MiAllocateAnyPages和MiAllocateZeroedPages。尝试从安全性的角度分析分配零页的必要性。

答:从性能的角度来分析,调用MIAllocateAnyPages函数分配物理页在某些情况下比调用MIAllocateZeroedPages.函数要快速。

从安全行的角度来分析,分配零页更加安全。例如,一个物理页被操作系统存储过重要


操作系统实验报告(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:理第二章地球上的大气22气压带和风带教案1新人教版必修110241701

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: