您好,欢迎来到好土汽车网。
搜索
您的当前位置:首页华北电力大学操作系统实验报告

华北电力大学操作系统实验报告

来源:好土汽车网
华 北 电 力 大 学 实 验 报 告

华北电力大学

实 验 报 告

实验名称 操作系统综合实验

课程名称 操作系统

学生姓名: 号: 成 绩:

指导教师:王德文/姜丽梅 实验日期:第 页 共 页

2015年11月4日| |

| |

专业班级:网络 学

华 北 电 力 大 学 实 验 报 告

实验一 实验环境的使用 一、实验目的 1. 熟悉操作系统集成实验环境 OS Lab 的基本使用方法。 2. 练习编译、调试 EOS 操作系统内核以及 EOS 应用程序。 二、实验内容 1. 启动OS Lab; 2. 学习OS Lab的基本使用方法:练习使用OS Lab编写一个Windows控制台应用程序,熟悉OS Lab的基本使用方法(主要包括新建项目、生成项目、调试项目等); 3. EOS内核项目的生成和调试:对EOS内核项目的各种操作(包括新建、生成和各种调试功能等)与对Windows控制台项目的操作是完全一致的; 4. EOS应用程序项目的生成和调试; 5. 退出OS Lab。 三、实验内容问题及解答 1. 练习使用单步调试功能(逐过程、逐语句),体会在哪些情况下应该使用“逐过程”调试,在哪些情况下应该使用“逐语句”调试。练习使用各种调试工具(包括“监视”窗口、“调用堆栈”窗口等)。 答:逐语句,就是每次执行一行语句,如果碰到函数调用,它就会进入到函数里面。 而逐过程,碰到函数时,不进入函数,把函数调用当成一条语句执行。因此,在需要进入函数体时用逐语句调试,而不需要进入函数体时用逐过程调试。 四、实验过程 1. 新建Windows控制台应用程序 生成项目: 执行项目: 调试项目: 2. 使用断点终端执行: 修改EOS应用程序项目名称 : 查看EOS SDK(Software Development Kit)文件夹: 五、实验心得 这次是验证性试验,具体步骤和操作方法都是与实验教程参考书上一致,实验很顺利,第 页 共 页

华 北 电 力 大 学 实 验 报 告

实验过程没有遇到困难。通过这次实验,我掌握了OS Lab启动和退出操作;练习使用OS Lab编写一个Windows控制台应用程序,熟悉OS Lab的基本使用方法新建项目、生成项目、调试项目等。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

实验2 操作系统的启动 一、实验目的 1. 跟踪调试EOS在PC机上从加电复位到成功启动的全过程,了解操作系统的启动过程。 2. 查看EOS启动后的状态和行为,理解操作系统启动后的工作方式。 二、使用仪器 二、实验内容 1. 准备实验。 2. 调试EOS操作系统的启动过程。 3. 调试加载程序。Loader程序的主要任务是将操作系统内核(kernel.dll文件)加载到内存中,然后让CPU进入保护模式并且启用分页机制,最后进入操作系统内核开始执行(跳转到kernel.dll的入口点执行)。 4. 调试内核。 5. EOS启动后的状态和行为。查看EOS的版本号: 1)在控制台中输入命令“ver”后按回车。 2)输出EOS版本后的控制台如下图所示。 6. 查看有应用程序运行时进程和线程的信息: 1)待 EOS启动完毕,在EOS控制台中输入命令“hello”后按回车。此时Hello.exe应用程序就开始执行。 2)迅速按Ctrl+F2切换到控制台2,并输入命令“pt”后按回车。输出的进程和线程信息如下图所示 三、实验内容问题及解答 1. 为什么EOS操作系统从软盘启动时要使用boot.bin和loader.bin两个程序?使用一个可以吗?它们各自的主要功能是什么?如果将loader.bin的功能移动到boot.bin文件中,则boot.bin文件的大小是否仍然能保持小于512字节? 答:在IDE环境启动执行EOS操作系统时,会将boot.bin、loader.bin和kernel.dll三个二进制写入软盘镜像文件中,然后让虚拟机来执行软盘中的EOS操作系统。仅使用其中一个是不能运行的。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

实验3 进程的创建 一、实验目的 1. 练习使用EOS API函数CreateProcess创建一个进程,掌握创建进程的方法,理解进程和程序的区别。 2. 调试跟踪CreateProcess函数的执行过程,了解进程的创建过程,理解进程是资源分配的单位。 二.实验内容 1. 准备实验。启动OS Lab。 2. 练习使用控制台命令创建EOS应用程序的进程。使用控制台命令创建EOS应用程序的进程如图: 3. 练习通过编程的方式让应用程序创建另一个应用程序的进程。应用程序创建另一个应用程序的进程的执行结果如图: 第 页 共 页

华 北 电 力 大 学 实 验 报 告

4. 调试CreateProcess函数。 5. 调试PsCreateProcess函数”。 6. 练习通过编程的方式创建应用程序的多个进程 三.实验内容问题及解答 1. 在源代码文件NewTwoProc.c提供的源代码基础上进行修改, 要求使用hello.exe同时创建10个进程。提示:可以使用 PROCESS_INFORMATION 类型定义一个有10个元素的数组,每一个元素对应一个进程。使用一个循环创建10个子进程,然后再使用一个循环等待10个子进程结束,得到退出码后关闭句柄。 答:修改代码为: STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcInfo[10]; ULONG ulExitCode; INT nResult=0;。 int i,j;//#ifdef_DEBUG__asm(\"int $3\\n nop\");#endif printf(\"Create10p//rocessesand wait for the processes exit...\\n\\n\"); StartupInfo.StdInput = GetStdHandle(STD_INPUT_HANDLE); StartupInfo.StdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 第 页 共 页

华 北 电 力 大 学 实 验 报 告

StartupInfo.StdError = GetStdHandle(STD_ERROR_HANDLE); for(i =0; i < 10; i++){ if(CreateProcess(\"A:\\\\Hello.exe\ else { for(j = 0; j < i; j++){ WaitForSingleObject(ProcInfo[j].ProcessHandle, INFINITE); GetExitCodeProcess(ProcInfo[j].ProcessHandle, printf(\"\\nThe process %d exit with %d.\\n\ CloseHandle(ProcInfo[j].ProcessHandle); CloseHandle(ProcInfo[j].ThreadHandle); } printf(\"CreateProcess Failed,Error code:0x%X.\\n\ GetLastError()); nResult = 1; return nResult; } for(i=0;i<10;i++){ WaitForSingleObject(ProcInfo[i].ProcessHandle, INFINITE); GetExitCodeProcess(ProcInfo[i].ProcessHandle, &ulExitCode); } for(i=0i<10;i++){ printf(\"\\nThe process %d exit with %d.\\n\ CloseHandle(ProcInfo[i].ProcessHandle); CloseHandle(ProcInfo[i].ThreadHandle); } return nResult; &ulExitCode); } 四.实验心得 本实验主要的问题就是用hello.exe同时创建10个进程:因为编程基础不好,刚开始的程序很难通过编译.最后使用PROCESS_INFORMATION类型定义一个有10个元素的数组,每一个元素对应一个进程。使用一个循环创建10个子进程,然后再使用一个循环等待10个子进程结束,得到退出码后关闭句柄。并对细节做了部分修正才成功。 实验4线程的状态和转换 第 页 共 页

华 北 电 力 大 学 实 验 报 告

一、实验目的和要求 1. 调试线程在各种状态间的转换过程,熟悉线程的状态和转换。 2. 通过为线程增加挂起状态,加深对线程状态的理解。 二、实验内容及步骤 1. 准备实验。启动OS Lab。 2. 调试线程状态的转换过程。 3. 线程由阻塞状态进入就绪状态。 4. 线程由运行状态进入就绪状态。 5. 线程由就绪状态进入运行状态。 6. 线程由运行状态进入阻塞状态。 7. 为线程增加挂起状态。 8. 完成Resume原语后,可以先使用suspend命令挂起loop线程,然后在控制台2中输入命令“Resume 31”(如果loop线程的ID是31)后按回车。命令执行成功的结果如下图所示。如果切换回控制台1后,发现loop线程的执行计数恢复增长就说明Resume原语可以正常工作。 三、实验内容问题及解答 1. 思考一下,在本实验中,当loop线程处于运行状态时,EOS中还有哪些线程,它们分别处于什么状态。可以使用控制台命令pt查看线程的状态。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

2. 当loop线程在控制台1中执行,并且在控制台2中执行suspend命令时,为什么控制台1中的loop线程处于就绪状态而不是运行状态? 答:当在控制台2 中执行suspend命令时,实质上是优先级为24的控制台2线程抢占了处理器,也就是控制台2线程处于运行状态,所以此时loop线程处于就绪状态了。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

实验5 进程的同步 一、实验目的和要求 1. 使用EOS的信号量,编程解决生产者—消费者问题,理解进程同步的意义。2. 通过为线程增加挂起状态,加深对线程状态的理解。 2. 调试跟踪EOS信号量的工作过程,理解进程同步的原理。 3. 修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。 二、实验内容及步骤 1. 实验准备 1)启动OS Lab。 2)新建一个EOS Kernel项目。 3)生成EOS Kernel项目,从而在该项目文件夹中生成SDK文件夹。 4)新建一个EOS应用程序项目。 5)使用在第3步生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。 2. 使用EOS的信号量解决生产者-消费者问题 1)使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码。 2)按F7生成修改后的EOS应用程序项目。 3)按F5启动调试。OS Lab会首先弹出一个调试异常对话框。 4)在调试异常对话框中选择“否”,继续执行。 5)立即激活虚拟机窗口查看生产者-消费者同步执行的过程,如图1。 6)待应用程序执行完毕后,结束此次调试。 图 1 3. 调试EOS信号量的工作过程。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

1)创建信号量: 信号量结构体(SEMAPHORE)中的各个成员变量是由API函数CreateSemaphore的对应参数初始化的,查看main函数中创建Empty和Full信号量使用的参数有哪些不同,又有哪些相同,思考其中的原因。 2)等待、释放信号量 a.等待信号量(不阻塞): 生产者和消费者刚开始执行时,用来放产品的缓冲区都是空的,所以生产者在第一次调用WaitForSingleObject函数等待Empty信号量时,应该不需要阻塞就可以立即返回。 b.释放信号量(不唤醒): 生产者线程通过等待Empty信号量使空缓冲区数量减少了1,通过释放Full信号量使满缓冲区数量增加了1,这样就表示生产者线程生产了一个产品并占用了一个缓冲区。 c.等待信号量(阻塞): 由于开始时生产者线程生产产品的速度较快,而消费者线程消费产品的速度较慢,所以当缓冲池中所有的缓冲区都被产品占用时,生产者在生产新的产品时就会被阻塞. d.释放信号量(唤醒): 只有当消费者线程从缓冲池中消费了一个产品,从而产生一个空缓冲区后,生产者线程才会被唤醒并继续生产14号产品. 4. 修改EOS的信号量算法 1)要求:在目前EOS Kernel项目的ps/semaphore.c文件中,PsWaitForSemaphore函数的Milliseconds参数只能是INFINITE,PsReleaseSemaphore函数的ReleaseCount参数只能是1。现在要求同时修改PsWaitForSemaphore函数和PsReleaseSemaphore函数中的代码,使这两个参数能够真正起到作用,使信号量对象支持等待超时唤醒功能和批量释放功能。 2)测试: a. 使用修改完毕的EOS Kernel项目生成完全版本的SDK文件夹,并覆盖之前的生产者-消费者应用程序项目的SDK文件夹。 b. 按F5调试执行原有的生产者-消费者应用程序项目,结果必须仍然与图1一致。如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,并重复步骤a。 三、实验内容问题及解答 1. 思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?可以参考本书第2章中的第2.6节。 答:在执行释放信号量和等待信号量时,是不允许CPU响应外部中断的,否则,会产生不可预料的结果。 2. 绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。 实验六 时间片轮转调度 第 页 共 页

华 北 电 力 大 学 实 验 报 告

一、实验目的及要求 1.调试EOS的线程调度程序,熟悉基于优先级的抢先式调度。 2.为EOS添加时间片轮转调度,了解其它常用的调度算法。 二、实验内容及步骤 1. 准备实验 2. 阅读控制台命令“rr”相关的源代码 3. 调试线程调度程序 a)调试当前线程不被抢先的情况 b)调试当前线程被抢先的情况 4. 为EOS添加时间片轮转调度 a)要求:修改ps/sched.c文件中的PspRoundRobin函数(第337行),在其中实现时间片轮转调度算法。 b)测试: 三、实验内容问题及解答 1. 结合线程调度执行的时机,说明在ThreadFunction函数中,为什么可以使用“关中断”和“开中断”的方法来保护控制台这种临界资源。一般情况下,应该使用互斥信号量(MUTEX)来保护临界资源,但是在ThreadFunction函数中却不能使用互斥信号量,第 页 共 页

华 北 电 力 大 学 实 验 报 告

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

华 北 电 力 大 学 实 验 报 告

1. 学习i386处理器的二级页表硬件机制,理解分页存储器管理原理。 2. 查看EOS应用程序进程和系统进程的二级页表映射信息,理解页目录和页表的管理方式。 3. 编程修改页目录和页表的映射关系,理解分页地址变换原理。 二、实验内容及步骤 1. 准备实验。 2. 查看EOS应用程序进程的页目录和页表。 3. 查看应用程序进程和系统进程并发时的页目录和页表。 4. 查看应用程序进程并发时的页目录和页表。 5. 在二级页表中映射新申请的物理页。 三、实验代码 设计代码: PRIVATE VOID ConsoleCmdMemoryMap(IN HANDLE StdHandle){ BOOL IntState; 第 页 共 页

华 北 电 力 大 学 实 验 报 告

ULONG PfnOfPageDirectory; ULONG PageTotal = 0; ULONG IndexOfDirEntry; ULONG IndexOfTableEntry; PMMPTE_HARDWARE pPde; PMMPTE_HARDWARE pPte; ULONG_PTR PageTableBase; ULONG_PTR VirtualBase; const char* OutputFormat = NULL; ASSERT(PspCurrentProcess == PspSystemProcess); IntState = KeEnableInterrupts(FALSE); // 关中断 ULONG PfnArray[2]; MiAllocateZeroedPages(2, PfnArray); OutputFormat = \"New page frame number: 0x%X, 0x%X\\n\"; fprintf(StdHandle, OutputFormat, PfnArray[0], PfnArray[1]); KdbPrint(OutputFormat, PfnArray[0], PfnArray[1]); IndexOfDirEntry = (0xE0000000 >> 22); // 虚拟地址的高 10 位是 PDE 标号 ((PMMPTE_HARDWARE)0xC0300000)[IndexOfDirEntry].PageFrameNumber = ((PMMPTE_HARDWARE)0xC0300000)[IndexOfDirEntry].Valid = 1; ((PMMPTE_HARDWARE)0xC0300000)[IndexOfDirEntry].Writable = 1; MiFlushEntireTlb(); // 刷新快表 PageTableBase = 0xC0000000 + IndexOfDirEntry * PAGE_SIZE; IndexOfTableEntry = (0xE0000000 >> 12) & 0x3FF;((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].PageFrameNumber = ((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].Valid = 1; ((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].Writable = 1; MiFlushEntireTlb(); // 刷新快表 IndexOfTableEntry = (0xE0001000 >> 12) & 0x3FF; ((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].PageFrameNumber = ((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].Valid = 1; ((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].Writable = 1;MiFlushEntireTlb(); // 刷新快表 第 页 共 页

PfnArray[0]; // 有效 // 可写 PfnArray[1]; PfnArray[1]; 华 北 电 力 大 学 实 验 报 告

OutputFormat = \"Read Memory 0xE0001000: %d\\n\"; fprintf(StdHandle, OutputFormat, *((PINT)0xE0001000)); KdbPrint(OutputFormat, *((PINT)0xE0001000)); *((PINT)0xE0000000) = 100; // 写共享内存 fprintf(StdHandle, OutputFormat, *((PINT)0xE0001000)); KdbPrint(OutputFormat, *((PINT)0xE0001000)); OutputFormat = \"\\nCR3->0x%X\\n\"; PfnOfPageDirectory = (ULONG)(PspSystemProcess->Pas->PfnOfPageDirectory); fprintf(StdHandle, OutputFormat, PfnOfPageDirectory); KdbPrint(OutputFormat, PfnOfPageDirectory); for(IndexOfDirEntry = 0; IndexOfDirEntry < PTE_PER_TABLE; IndexOfDirEntry++){ pPde = (PMMPTE_HARDWARE)((ULONG_PTR)PDE_BASE + IndexOfDirEntry * PTE_SIZE); if(!pPde->Valid) continue; OutputFormat = \"PDE: 0x%X (0x%X)->0x%X\\n\"; VirtualBase = (IndexOfDirEntry << PDI_SHIFT); fprintf(StdHandle, OutputFormat, IndexOfDirEntry, VirtualBase, KdbPrint(OutputFormat, IndexOfDirEntry, VirtualBase, PageTableBase = (ULONG_PTR)PTE_BASE + IndexOfDirEntry * PAGE_SIZE; for(IndexOfTableEntry = 0; IndexOfTableEntry < PTE_PER_TABLE; { pPte = (PMMPTE_HARDWARE)(PageTableBase + IndexOfTableEntry * if(!pPte->Valid) continue; OutputFormat = \"\\PTE: 0x%X (0x%X)->0x%X\\n\"; VirtualBase = (IndexOfDirEntry << PDI_SHIFT) | (IndexOfTableEntry << fprintf(StdHandle, OutputFormat, IndexOfTableEntry, VirtualBase, KdbPrint(OutputFormat, IndexOfTableEntry, VirtualBase, pPde->PageFrameNumber); pPde->PageFrameNumber); IndexOfTableEntry++) PTE_SIZE); PTI_SHIFT); pPte->PageFrameNumber); pPte->PageFrameNumber); 第 页 共 页

华 北 电 力 大 学 实 验 报 告

} }} OutputFormat = \"\\nPhysical Page Total: %d\\n\"; fprintf(StdHandle, OutputFormat, PageTotal); KdbPrint(OutputFormat, PageTotal); OutputFormat = \"Physical Memory Total: %d\\n\\n\"; fprintf(StdHandle, OutputFormat, PageTotal * PAGE_SIZE); KdbPrint(OutputFormat, PageTotal * PAGE_SIZE); OutputFormat = \"\\nNonused Page Count: %d\\n\"; fprintf(StdHandle, OutputFormat, MiGetAnyPageCount()); KdbPrint(OutputFormat, MiGetAnyPageCount()); IndexOfDirEntry = (0xE0000000 >> 22); // 虚拟地址的高 10 位是 PDE 标号 PageTableBase = 0xC0000000 + IndexOfDirEntry * PAGE_SIZE; IndexOfTableEntry = (0xE0000000 >> 12) & 0x3FF;IndexOfTableEntry = (0xE0001000 >> 12) & 0x3FF;((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].Valid = 0; ((PMMPTE_HARDWARE)PageTableBase)[IndexOfTableEntry].Valid = 0; ((PMMPTE_HARDWARE)0xC0300000)[IndexOfDirEntry].Valid = 0; MiFlushEntireTlb(); MiFreePages(2, PfnArray); OutputFormat = \"\\nNonused Page Count: %d\\n\"; fprintf(StdHandle, OutputFormat, MiGetAnyPageCount()); KdbPrint(OutputFormat, MiGetAnyPageCount()); KeEnableInterrupts(IntState); // 开中断 四、实验问题内容及解答 1. 观察之前输出的页目录和页表的映射关系,可以看到页目录的第0x300个PDE映射的页框号就是页目录本身,说明页目录被复用为了页表。而恰恰就是这种映射关系决定了4K的页目录映射在虚拟地址空间的0xC0300000-0xC0300FFF,4M的页表映射在xC0000000-0xC03FFFFF。现在,假设修改了页目录,使其第0x100个PDE映射的页框号是页目录本身,此时页目录和页表会映射在4G虚拟地址空间的什么位置呢?说明计算方法。 答:页目录:PDE标号0x100做为虚拟地址的高10位,PTE标号0x100做为虚拟地址的12-22位,得到虚拟地址0x 40100000。页表:PDE标号0x100做为虚拟地址的高10位,PTE标号0x0做为虚拟地址的12-22位,得到虚拟地址0x 40000000。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

五、实验心得与体会 通过操作系统试验,了解了操作系统的启动过程和运行方式,加深了对计算机操作系统的理解。 实验10 磁盘调度算法 一、 实验目的 1. 通过学习EOS实现磁盘调度算法的机制,掌握磁盘调度算法执行的条件和时机。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

2. 观察EOS实现的FCFS、SSTF和SCAN磁盘调度算法,了解常用的磁盘调度算法。 3. 编写CSCAN和N-Step-SCAN磁盘调度算法,加深对各种扫描算法的理解。 二、实验内容 二、实验内容及步骤 1. 准备实验 1)新建一个EOS Kernel项目。 2. 验证先来先服务(FCFS)磁盘调度算法 1)打开ke文件夹中的sysproc.c文件。 2)打开io/block.c文件。 3)按F7生成,然后按F5调试。 4)在控制台中输入命令“ds”后按回车。 5)将输出复制到一个文本文件中,然后结束此次调试。 3. 验证最短寻道时间优先(SSTF)磁盘调度算法 1)打开sstf.c文件使用sstf.c文件中IopDiskSchedule函数的函数体,替换block.c文件中IopDiskSchedule函数的函数体。 2)按F7生成,然后按F5调试。3. 在控制台中输入命令“ds”后按回 车。 3)将输出复制到一个文本文件中,结束此次调试。 4. 验证SSTF算法造成的线程“饥饿”现象 1)修改sysproc.c文件ConsoleCmdDiskSchedule函数中的源代码,仍然使磁头初始停留在磁道10,而让其它线程依次访问磁道78、 21、9、8、11、41、10、67、12、10。 2)按F7生成,然后按F5调试。 3)在控制台中输入命令“ds”后按回车。将输出复制到一个文本文 件中,结束此次调试。 5. 验证扫描(SCAN)磁盘调度算法 1)打开文件夹中的scan.c文件, 使用scan.c文件中IopDiskSchedule函数的函数体,替换block.c文件中IopDiskSchedule函数的函数体。 2)按F7生成,按F5调试。 3)在控制台中输入命令“ds”后按回车。将输出保存到一个文本 文件中。最后将ConsoleCmdDiskSchedule函数中线程访问的磁 道号恢复到本实验3.2中的样子。 6. 改写SCAN算法 使用本实验3.2中的数据进行测试,确保调度的结果与图18-5中显示 的一致,也可以多准备几组测试数据,保证改写的SCAN算法是正确的。 测试成功后,将改写的SCAN算法源代码备份。 7. 编写循环扫描(CSCAN)磁盘调度算法 第 页 共 页

华 北 电 力 大 学 实 验 报 告

使用本实验3.2中的数据进行测试,确保调度的结果与图18-7一致。 在控制台中多次输入“ds”命令,查看磁盘调度算法执行的情况。然后 将输出复制到一个文本文件中,将编写的CSCAN算法备份。 8. 验证SSTF、SCAN及CSCAN算法中的“磁臂粘着”现象 1)修改sysproc.c文件ConsoleCmdDiskSchedule函数中的源代码 2)分别使用SSTF、SCAN和CSCAN算法调度这组数据。 3)将“输出”窗口中的内容复制到一个文本文件中。 9. 编写N-Step-SCAN磁盘调度算法 三、实验问题解答 1. 在执行SCAN、N-Step-SCAN磁盘调度算法时,如果在EOS控制台中多次输入“ds”命令,调度的顺序会发生变化,说明造成这种现象的原因(提示:注意这两种算法使用的全局变量)。尝试修改源代码,使这两种算法在多次执行时,都能确保调度的顺序一致(提示:可以参考io/block.c文件中IopReceiveRequest函数和IopProcessNextRequest函数判断磁盘调度算法开始工作和结束工作的方法)。 答:SCAN算法使用了全局变量ScanInside记录磁头移动的方向,每次执行“ds” 时,磁头的移动方向都可能不一样,所在磁道也可能不一样,所以在每次 执行时距离最短的线程也不同,所以调度的顺序会发生变化,例如在第一 次执行“ds”命令时,ScanInside初始化为true则开始磁头是从外向内移 动的,结束时磁头变为从内向外移动,所以在下次执行“ds”命令时,开始磁头就继续从内向外移动了。要解决这个问题,可以IopProcessNextRequest函数中,每次检测到磁盘调度算法结束工作时,将这些全局变量恢复为默认值。 第 页 共 页

华 北 电 力 大 学 实 验 报 告

第 页 共 页

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- howto234.com 版权所有 湘ICP备2022005869号-3

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务