《操作系统实训报告.doc》由会员分享,可在线阅读,更多相关《操作系统实训报告.doc(42页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、广西工学院鹿山学院操作系统实训报告系 别: 计算机软件工程 专业班级: 082班 姓 名: 高祥 学 号: 指导教师: 胡艳华 二 一年 11 月 28 日任务一分析操作系统所面临的操作需求【实训目的】使学生理解操作系统所面临的操作需求,掌握操作系统中的进程管理、存储管理、设备管理和文件管理等功能。【实训内容】1.分析操作系统所面临的操作需求;2.熟悉实训环境;3.资料搜集与整理,进行实训的前期准备。【实训步骤】1、 分析与设计(详细分析设计,并给出流程图)【思考题】1.操作系统中各模块有怎样的功能?操作系统中的各个模块都有不同的功能:进程管理模块用于分配和控制处理机;设备管理模块主要负责对I
2、/O设备的分配与操纵;文件管理主要负责文件的存取、共享和保护;存储管理主要负责的分配与回收。2.它们之间有怎样的联系?它们之间相互联系,关系密切,无论是设备管理、文件管理,还是储存管理都离不开进程的管理。文件一般都需要存储,而文件的存储需要文件管理进行存储,也需要储存管理来对文件存储分配空间等等。3.针对某一特定的应用环境,如何完善操作系统的功能?要想完善操作系统的功能,必须要合理安排各个功能模块,并利用有效的算法对各个功能进行管理和处理。任务二 进程管理【实训目的】掌握临界区的概念及临界区的设计原则;掌握信号量的概念、PV操作的含义以及应用PV操作实现进程的同步与互斥;分析进程争用资源的现象
3、,学习解决进程互斥的方法;掌握进程的状态及状态转换;掌握常用的进程调度算法。【实训内容】1.分析进程的同步与互斥现象,编程实现经典的进程同步问题生产者消费者问题的模拟;2.编写允许进程并行执行的进程调度程序,在常用的进程(作业)调度算法:先来先服务算法、短作业优先算法、最高响应比优先算法、高优先权优先算法等调度算法中选择一种调度算法进行简单模拟,并输出平均周转时间和平均带权周转时间。【实训步骤】一:生产者消费者问题的模拟1.分析与设计(详细分析设计,并给出流程图)2.程序代码#include #include const unsigned short SIZE_OF_BUFFER = 10;
4、/缓冲区长度 unsigned short ProductID = 0; /产品号 unsigned short ConsumeID = 0; /将被消耗的产品号 unsigned short in = 0; /产品进缓冲区时的缓冲区下标 unsigned short out = 0; /产品出缓冲区时的缓冲区下标 int g_bufferSIZE_OF_BUFFER; /缓冲区是个循环队列 bool g_continue = true; /控制程序结束 HANDLE g_hMutex; /用于线程间的互斥 HANDLE g_hFullSemaphore; /当缓冲区满时迫使生产者等待 HAN
5、DLE g_hEmptySemaphore; /当缓冲区空时迫使消费者等待 DWORD WINAPI Producer(LPVOID); /生产者线程 DWORD WINAPI Consumer(LPVOID); /消费者线程 int main() /创建各个互斥信号 g_hMutex = CreateMutex(NULL,FALSE,NULL); g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL); g_hEmptySemaphore = CreateSemaphore(NULL,0,
6、SIZE_OF_BUFFER-1,NULL); /调整下面的数值,可以发现,当生产者个数多于消费者个数时, /生产速度快,生产者经常等待消费者;反之,消费者经常等待 const unsigned short PRODUCERS_COUNT = 3; /生产者的个数 const unsigned short CONSUMERS_COUNT = 1; /消费者的个数 /总的线程数 const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT; HANDLE hThreadsPRODUCERS_COUNT; /各线程的han
7、dle DWORD producerIDCONSUMERS_COUNT; /生产者线程的标识符 DWORD consumerIDTHREADS_COUNT; /消费者线程的标识符 /创建生产者线程 for (int i=0;iPRODUCERS_COUNT;+i) hThreadsi=CreateThread(NULL,0,Producer,NULL,0,&producerIDi); if (hThreadsi=NULL) return -1; /创建消费者线程 for ( i=0;iCONSUMERS_COUNT;+i) hThreadsPRODUCERS_COUNT+i=CreateThr
8、ead(NULL,0,Consumer,NULL,0,&consumerIDi); if (hThreadsi=NULL) return -1; while(g_continue) if(getchar() /按回车后终止程序运行 g_continue = false; return 0; /生产一个产品。简单模拟了一下,仅输出新产品的ID号 void Produce() std:cerr 生产一个产品 +ProductID . ; std:cerr 成功 std:endl; /把新生产的产品放入缓冲区 void Append() std:cerr 把新生产的产品放入缓冲区 . ; g_buf
9、ferin = ProductID; in = (in+1)%SIZE_OF_BUFFER; std:cerr 成功 std:endl; /输出缓冲区当前的状态 for (int i=0;iSIZE_OF_BUFFER;+i) std:cout i : g_bufferi; if (i=in) std:cout - 生产; if (i=out) std:cout - 消费; std:cout std:endl; /从缓冲区中取出一个产品 void Take() std:cerr 从缓冲区中取出一个产品 . ; ConsumeID = g_bufferout; out = (out+1)%SIZ
10、E_OF_BUFFER; std:cerr 成功 std:endl; /输出缓冲区当前的状态 for (int i=0;iSIZE_OF_BUFFER;+i) std:cout i : g_bufferi; if (i=in) std:cout - 生产; if (i=out) std:cout - 消费; std:cout std:endl; /消耗一个产品 void Consume() std:cerr 消耗一个产品 ConsumeID . ; std:cerr 成功 std:endl; /生产者 DWORD WINAPI Producer(LPVOID lpPara) while(g_c
11、ontinue) WaitForSingleObject(g_hFullSemaphore,INFINITE); WaitForSingleObject(g_hMutex,INFINITE); Produce(); Append(); Sleep(1500); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hEmptySemaphore,1,NULL); return 0; /消费者 DWORD WINAPI Consumer(LPVOID lpPara) while(g_continue) WaitForSingleObject(g_hEmptySem
12、aphore,INFINITE); WaitForSingleObject(g_hMutex,INFINITE); Take(); Consume(); Sleep(1500); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hFullSemaphore,1,NULL); return 0; 3.运行并测试程序,并给出程序运行界面。二:先来先服务算法1. 分析与设计(详细分析设计,并给出流程图)开始初始化pcb,输入进程信息各进程按先来先到的顺序进入就绪队列结束运行运行进程所需CPU时间撤消该进程就绪队列空?N2.2.程序代码#include struc
13、t fcfs char name10; /进程名称int prio; /priority进程优先数float arrivetime; /到达时间float servicetime; /运行时间float starttime; /开始时间float finishtime; /完成时间float zztime; /周转时间float dqzztime; /带权周转时间; fcfs a100; void input(fcfs *p,int N) int i; printf(输入进程名称 & 到达时间 & 运行时间 & 进程优先数:nfor exmple: a 0 100 1n); for(i=0;i
14、=N-1;i+) printf(输入 %dth 进程信息:n,i+1); scanf(%s%f%f%d,&pi.name,&pi.arrivetime,&pi.servicetime,&pi.prio); void Print(fcfs *p,float arrivetime,float servicetime,float starttime,float finishtime,float zztime,float dqzztime,int prio,int N) int k; printf(run order:); printf(%s,p0.name); for(k=1;k%s,pk.name
15、); printf(n进程信息:n); printf(nnametarrivetservicetstarttfinishtzztdqzztprion); for(k=0;k=N-1;k+) printf(%st%-.2ft%-.2ft%-.2ft%-.2ft%-.2ft%-.2ft%dn,pk.name ,pk.arrivetime,pk.servicetime,pk.starttime,pk.finishtime,pk .zztime,pk.dqzztime,pk.prio); /pai xu void sort(fcfs *p,int N) for(int i=0;i=N-1;i+) fo
16、r(int j=0;j=i;j+) if(pi.arrivetimepj.arrivetime) fcfs temp; temp=pi; pi=pj; pj=temp; /yun xing jieduan void deal(fcfs *p, float arrivetime,float servicetime,float starttime,float finishtime,float &zztime,float &dqzztime,int prio,int N) int k; for(k=0;kpk-1.finishtime) pk.starttime=pk.arrivetime; pk.
17、finishtime=pk.arrivetime+pk.servicetime; else pk.starttime=pk-1.finishtime; pk.finishtime=pk-1.finishtime+pk.servicetime; for(k=0;k=N-1;k+) pk.zztime=pk.finishtime-pk.arrivetime; pk.dqzztime=pk.zztime/pk.servicetime; void FCFS(fcfs *p,int N) float arrivetime=0,servicetime=0,starttime=0,finishtime=0,
18、zztime=0,dqzztime =0,prio = 0; sort(p,N); deal(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,prio,N) ; Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,prio,N ); void main() int N; printf(-先来先服务调度算法-n); printf(输入进程数:n); scanf(%d,&N); input(a,N); FCFS(a,N); 3.运行并测试程
19、序,并给出程序运行界面。【思考题】针对某一具体应用环境,如何选择合适的调度算法?在批处理系统中,为了照顾为数众多的短作业,应采用短作业优先调度的调度算法;在分时系统中,为了保证系统具有合理的响应时间,应采用轮转法进行调度。非抢占式调度算法,有利于长作业,不利于短作业。【心得体会】通过这次实验了解到生产者-消费者问题是一个经典的进程同步问题,以及在其中使用信号量机制,生产者与消费者问题要求我们设计在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费,而消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那
20、么生产者线程必须等待消费者线程释放出一个空缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。最简单的调度算法就是先来先服务,也可以称为先进先出(First In First Out)或严格排队方式。对于进程调度算法来说,先来先服务调度算法就是从就绪队列中选择一个最先进入队列的进程,将CPU分配于它,让其运行。该进程一直运行下去直到完成或由于某事件而被阻塞入放弃CPU。这样,当一个进程进入就绪队列时,它的PCB就链入了该就绪队列的末尾,排队等待分配CPU。一般来说,先来先服务调度算法对于长任务来说比较短任务要好一些。 FCFS算法不考虑作业运行时
21、间的长短,仅按作业进入输入井时间的先后进行调度,因此对所有的作业是公平合理的。 这次生产者和消费者问题、以及先来先服务调度算法的程序设计,不但加深了我对操作系统中多线程机制的理解和认识,更让我认识到知识的掌握,仅靠学习理论知识是远远不够的,要与实际动手操作相结合才能更好的理解和分析问题。任务三 存储管理【实训目的】掌握物理内存和虚拟内存的基本概念;掌握重定位的基本概念及其要点,理解逻辑地址与绝对地址;掌握各种存储管理的实现方法,包括基本原理、地址变换和缺页中断、主存空间的分配及分配算法;掌握常用淘汰算法。【实训内容】编写一个模拟的动态页式存储管理程序,实现对动态页式存储的淘汰算法的模拟(在先进
22、先出淘汰算法、最近最少使用淘汰算法、最不经常使用淘汰算法三种算法中选择一种进行模拟)并计算各个算法的缺页率;并且页面淘汰算法在淘汰一页时,只将该页在页表中抹去,而不再判断它是否被改写过,也不将它写回到辅存【实训步骤】1.分析与设计(详细分析设计,并给出流程图)2.程序代码#include#include#define m 5 /m表示页数#define n 3 /n表示物理块数float interrupt=0 ;/产生缺页中断的次数int k=0; /指向最先进入内存的页,即被淘汰的页int PageTablem; /定义页表,总共m页,数组中数值是状态位 =1表示该页在内存中,=0表示不在
23、内存中,默认处置为0int Blockn; /定义物理块,总共n个,数组中数值表示对应物理块中装入的页的编号int process20; /进程访问序列int number=1; /用于标志访问次数void Visit(int); /访问函数/主函数void main (void) int input; cout某进程共有m页,请输入进程访问序列(范围:1-minput; for(int length=0;input!=0;length+) /将输入序列存入process数组,长度为length processlength=input; cininput; for(int j=0;jlengt
24、h;j+) Visit(processj); /依次访问页processj cout共length次访问,产生interrupt次缺页中断,缺页率为 interrupt/lengthn;/访问函数void Visit(int x) int i,j; coutsetw(2)number: 访问页x ; /第number次访问,访问页x for(i=0;in;i+) if(Blocki=0) /访问页x时没有命中,且内存未装满,产生缺页中断,直接调入访问页 interrupt+; /缺页中断次数加1 PageTablex-1=1; /修改状态位 Blocki=x; /页x调入物理块 cout缺页中
25、断 内存未满 调入页x 物理块内的页为 ; for(j=0;j=i;j+)coutBlockj ; /输出物理块内的页号 coutn; break; if(PageTablex-1=1) /访问页x时命中 cout命中 物理块内的页为 ; for(j=0;jn & Blockj!=0;j+)coutBlockj ; /输出物理块内的页号 coutn; break; if(i=n) /访问页x时内存已装满,且没有命中,产生缺页中断,调入该页至内存,淘汰最先进入的页 cout缺页中断 淘汰页Blockk 调入页x 物理块内的页为 ; interrupt+; /缺页中断次数加1 PageTableB
26、lockk-1=0; /页Blockk被淘汰,状态位修改为 0 Blockk=x; /页x调入物理块 PageTablex-1=1; /页x状态位修改为 1 k=(k+1)%n; /修改下次被淘汰页指针 for(j=0;jn;j+)coutBlockj ; /输出物理块内的页号 coutNeedi,n,则报错返回。 (2)如果RequestnAvailable,则进程i进入等待资源状态,返回。 (3)假设进程i的申请已获批准,于是修改系统状态: Available=Available-Request Allocation=Allocation+Request Need=Need-Request
27、(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。 1.2、安全性检查: (1)设置两个工作向量Work=Available;FinishM=False(2)从进程集合中找到一个满足下述条件的进程, Finish i=False Need=Work 如找到,执行(3);否则,执行(4) (3)设进程获得资源,可顺利执行,直至完成,从而释放资源。 Work=Work+Allocation Finish=True GO TO 2 (4)如所有的进程FinishM=true,则表示安全;否则系统不安全1.3、 设计银行家算法的数据结构和基本定义:#defin
28、e M 5 /总进程数#define N 3 /总资源数struct bank /定义结构体int AvailableN; /可利用资源向量 int MaxMN; /最大需求矩阵 int AllocationMN; /分配矩阵 int NeedMN; ; /需求矩阵void Initilize(bank &); /初始化int Safe_test(bank); /检查安全性void Resoure_allocate(bank &); /系统对进程资源申请的处理 void main(void);/主函数14、 分析银行家算法的实现过程,流程图如下图6所示:图6 银行算法的实现流程2、程序代码:#
29、include string.h#include #include #define M 5 /总进程数#define N 3 /总资源数struct bank /定义结构体 int AvailableN; /可利用资源向量 int MaxMN; /最大需求矩阵 int AllocationMN; /分配矩阵 int NeedMN; /需求矩阵;void Initilize(bank &); /初始化int Safe_test(bank); /检查安全性void Resoure_allocate(bank &); /系统对进程资源申请的处理void main(void) bank current
30、; /定义变量 Initilize(current); /初始化 Safe_test(current); /检查安全性 while(1) /循环执行进程申请资源和系统对申请的处理 Resoure_allocate(current); void Initilize(bank &x) /初始化 int i,j; printf(初始化过程,输入相关数据:n); printf(输入最大需求矩阵Max:n); for(i=0;iM;i+) /设置最大需求矩阵 for(j=0;jN;j+) scanf(%d,&x.Maxij); printf(输入分配矩阵Allocation:n); for(i=0;iM
31、;i+) /设置分配矩阵 for(j=0;jN;j+) scanf(%d,&x.Allocationij); for(i=0;iM;i+) /设置需求矩阵 for(j=0;jN;j+) x.Needij=x.Maxij-x.Allocationij; printf(输入可利用资源向量:n); for(i=0;iN;i+) /设置可利用资源向量 scanf(%d,&x.Availablei); int Safe_test(bank x)/检查安全性 int i,j; int safeprocessM; /安全序列向量 int workN; /空闲资源矩阵 int FinishM; /进程完成标志矩阵 for(i=0;iN;i+) /开始时可利用资源向量就是空闲资源矩阵 worki=x.Availablei; for(i=0;iM;i+) /初始化标志矩阵为false Finishi=false; int k= 0; /安全序列排列号 for(i=0;iM;i+) /每次都从第一个进程开始做循环 if(Finishi=false) for(j=0;jworkj) /判断当前进程需求矩阵能否得到满足 break; /不满足则跳出 i
限制150内