资源描述
操作系统实验报告 学生学院_ 计算机学院_专业班级_10级计算机科学与技术5班学 号_3210006071_学生姓名_陈丹飞_指导教师_孙为军_ 2013年 1 月 10 日目录1 实验一 进程调度12 实验二 作业调度3 实验三 可变式分区分配4 实验四 简单文件系统试验一 进程调度一、实验目的:编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。 二、实验内容:以两种典型算法为例说明实现的算法(一)、最高优先数优先的调度算法1、实验原理进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。 进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。 进程的运行时间以时间片为单位进行计算。 每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。 就绪进程获得CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。 如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。 重复以上过程,直到所有进程都完成为止。2、源代码:#include stdio.h #include #include #define getpch(type) (type*)malloc(sizeof(type) #define NULL 0 struct pcb /* 定义进程控制块PCB */ char name10; /*定义进程名称*/ char state; /*进程状态*/ int super; /*优先数*/ int ntime; /*需要运行的时间*/ int rtime; /*已占用的CPU时间*/ struct pcb* link; *ready=NULL,*p; typedef struct pcb PCB; /*pcb表*/ sort() /* 建立对进程进行优先级排列函数*/ PCB *first, *second; int insert=0; if(ready=NULL)|(p-super)(ready-super) /*优先级最大者,插入队首*/ p-link=ready; ready=p; else /* 进程比较优先级,插入适当的位置中*/ first=ready; second=first-link; while(second!=NULL) if(p-super)(second-super) /*若插入进程比当前进程优先数大,*/ /*插入到当前进程前面*/ p-link=second; first-link=p; second=NULL; insert=1; else /* 插入进程优先数最低,则插入到队尾*/ first=first-link; second=second-link; if(insert=0) first-link=p; input() /* 建立进程控制块函数*/ int i,num; clrscr(); /*清屏*/ printf(n 请输入进程号?); scanf(%d,&num); for(i=0;iname); printf(n 输入进程优先数:); scanf(%d,&p-super); printf(n 输入进程运行时间:); scanf(%d,&p-ntime); printf(n); p-rtime=0;p-state=w; p-link=NULL; sort(); /* 调用sort函数*/ int space() int l=0; PCB* pr=ready; while(pr!=NULL) l+; pr=pr-link; return(l); disp(PCB * pr) /*建立进程显示函数,用于显示当前进程*/ printf(n qname t state t super t ndtime t runtime n); printf(|%st,pr-name); printf(|%ct,pr-state); printf(|%dt,pr-super); printf(|%dt,pr-ntime); printf(|%dt,pr-rtime); printf(n); check() /* 建立进程查看函数,检查等待队列的进程是否进入就绪队列*/ PCB* pr; printf(n * 当前正在运行的进程是:%s,p-name); /*显示当前运行进程*/ disp(p); pr=ready; printf(n *当前就绪队列状态为:n); /*显示就绪队列状态*/ while(pr!=NULL) disp(pr); pr=pr-link; destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/ printf(n 进程 %s 已完成.n,p-name); free(p); running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/ (p-rtime)+; if(p-rtime=p-ntime) destroy(); /* 调用destroy函数*/ else (p-super)-; p-state=w; sort(); /*调用sort函数*/ main() /*主函数*/ int len, h=0; char ch; input(); len=space(); while(len!=0)&(ready!=NULL) ch=getchar(); h+; printf(n The execute number:%d n,h); p=ready; ready=p-link; p-link=NULL; p-state=R; check(); running(); printf(n 按任一键继续.); ch=getchar(); printf(nn 进程已经完成.n); ch=getchar(); 3、运行结果:请输入进程号?5进程号No.0:输入进程名:A输入进程优先数:2输入进程运行时间:1进程号No.1:输入进程名:B输入进程优先数:3输入进程运行时间:1进程号No.2:输入进程名:C输入进程优先数:1输入进程运行时间:1进程号No.3:输入进程名:D输入进程优先数:4输入进程运行时间:1进程号No.4:输入进程名:E输入进程优先数:5输入进程运行时间:1The execute number:1*当前正在运行的进程是:EQnamestatesuperndtimeruntimeER510*当前就绪队列状态为:QnamestatesuperndtimeruntimeDw410Bw310Aw210Cw110进程E已完成按任一键继续The execute number:2*当前正在运行的进程是:DQnamestatesuperndtimeruntimeDR410*当前就绪队列状态为:QnamestatesuperndtimeruntimeBw310Aw210Cw110进程D已完成按任一键继续The execute number:3*当前正在运行的进程是:BQnamestatesuperndtimeruntimeBR310*当前就绪队列状态为:QnamestatesuperndtimeruntimeAw210Cw110进程B已完成按任一键继续The execute number:4*当前正在运行的进程是:AQnamestatesuperndtimeruntimeAR210*当前就绪队列状态为:QnamestatesuperndtimeruntimeCw110进程A已完成按任一键继续The execute number:5*当前正在运行的进程是:cQnamestatesuperndtimeruntimecR110*当前就绪队列状态为:进程C已完成按任一键继续进程已经完成(二)、简单轮转法1、实验原理在分时系统中,都毫无例外采用时间片轮转法。在一种简单的轮转法中,系统将所有就绪进程按FIFO规则排成一个队列,把CPU分配给队首进程,并规定它执行一给定的时间如100ms,称此时间间隔为时间片。当时间片完成时,系统产生一个时钟中断,剥夺该进程的执行,将它送至就绪队列的末尾,并把处理机分配给就绪队列的新队首进程,同样也让它执行一个时间片。这样,就绪队列中的所有进程均可获得一个时间片的处理机而运行。就绪队列中的进程在依次执行时,可能发生以下三种情况:(1)进程未用完一个时间片就结束,这时系统应提前调度;(2)进程在执行过程中提出I/O请求而阻塞,系统应将它放入相应的阻塞队列并引起调度;(3)进程完成一个时间片后尚未完成,系统应将它重新放到就绪队列的末尾,等待下次执行。由于在分时系统中,键盘命令的执行时间较短,大多能在一个时间片内执行完毕,因此分时系统的实际响应时间将比Nq(N是同时性用户数,q是时间片大小)小。2、源代码:#include/*定义一个pcb的结构体*/struct pcb char name; /*进程名*/int time; /*进程执行时间*/; void main() int n,i,j,flag=1; struct pcb a100; /*最多可以有100个进程*/printf(输入进程个数:); scanf(%d,&n); getchar();/*接收回车*/ for(i=0;i0) /*若进程数为空,结束程序*/ if(ai.time!=0) /*就绪队列是否为空*/ printf(%c,ai.name); /*进程执行一次,打印出该进程*/ai.time-; /*使该进程占用的时间片减1*/ for(j=0;jn;j+) if(aj.time) /*若进程所占用的时间片不为0,仍执行下一进程*/ flag=1; break; else /*若进程所占用的时间片为0,说明已经完成,跳过执行下一进程*/flag=0; i=(+i)%n; /*继续执行下一个进程,i1*/ printf(n);3、运行结果:输入进程个数:5输入进程的名字:A输入占用的时间片:2输入进程的名字:B输入占用的时间片:3输入进程的名字:C输入占用的时间片:1输入进程的名字:D输入占用的时间片:4输入进程的名字:E输入占用的时间片:5ABCDEABDEBDEDEEPress any key to continue六、心得体会: 操作系统是计算机系统中必不可少的系统软件。它是计算机系统中各种资源的管理者和各种活动的组织者、指挥者。操作系统采用时间片法调度进程,使系统资源得到充分的利用,用户也可以花更少的时间完成更多的工作,通过这次进程调度实验,让我明白了系统时间片的调度方法,对操作系统理论的学习更加深一层.并且增强了用语言的编程能力。在编程的过程中,遇到了种种困难,并且一一的克服了,这使我产生很大的成就感。实验二 作业调度一、实验名称:进程调度用高级语言编写和调试一个或多个作业调度的模拟程序,加深对作业调度算法的理解。二、实验内容: 在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的CPU时限等因素。而在多道批处理系统中,作业首先存放在外存,当系统拥有的资源足够分配给一个作业,就将资源分配给此作业,并将此作业调进内存。当系统资源不足以分配给一个作业时,则等待已经分配资源的作业运行完成后释放资源增加系统资源。(一)、为单道批处理系统设计一个作业调度程序1、实验原理。作业等待算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRN)的调度算法。 (1)先来先服务(FCFS)算法先来先服务作业调度算法是一种较简单的作业调度算法,即每次调度是从后备作业队列中选择一个最先进入该队列的作业,将它调入内存,分配资源、创建相应的进程,放入进程就绪队列准备运行。FCFS算法利于长作业,不利于短作业,而大多数的作业是I/O繁忙的短作业。以FCFS作为主调度算法是不常用的。(2)短作业优先调度算法(SJF)短作业优先调度算法是指操作系统在进行作业调度时以作业长短作为优先级进行调度。该调度算法可以照顾到实际上占作业总数绝大部分的短作业,使它们能比长作业优先调度执行。这时后备作业队列按作业优先级由高到低顺序排列,当作业进入后备队列时要按该作业优先级放置到后备队列相应的位置。实践证明,该调度算法的性能是最好的,单位时间的作业吞吐量也最大,但也存在缺点:对长作业极为不利。(3)响应比高者优先(HRN)的调度算法采用响应比高者优先调度算法,进行调度时必须计算出系统中的所有满足必要条件作业的响应比;从中选择响应比最高的一个作业装入主存储器、分配资源,由于是实验,所以就用将作业的作业控制块出队,并输出作业的作业名代替装入主存储器,同时修改系统的资源数量;用同样方法选择第二个、第三个直到不再有满足必要条件的作业。调度算法的流程图如下 :2、源代码及运行结果:#include stdio.h#define getjcb(type) (type*)malloc(sizeof(type)#define NULL 0int n=0,time=0;float eti,ewi;struct jcb char name10; /* 作业名 */ char state; /* 作业状态 */ int ts; /* 提交时间 */ float super; /* 优先权 */ int tb; /* 开始运行时间 */ int tc; /* 完成时间 */ float ti; /* 周转时间 */ float wi; /* 带权周转时间 */ int ntime; /* 作业所需运行时间 */ struct jcb *link; /* 结构体指针 */ *p,*q,*head=NULL;typedef struct jcb JCB;inital()int i;printf(n输入作业数:n);scanf(%d,&n);printf(输入:n作业名t到达时间t服务时间n);for(i=0;iname,&p-ts,&p-ntime); p-state=W; p-link=NULL; if(head=NULL) head=q=p; else q-link=p; q=p; void print(JCB *pr,int m)JCB *p; printf(ntime=%d,time); if(m=3) printf(n作业名t状态t到达时间t服务时间t优先权tt完成时间t周转时间t带权周转时间n); printf(%st%ct%dt%dt%4.2ft%dt%4.2ft%4.2fn, pr-name,pr-state,pr-ts,pr-ntime,pr-super,pr-tc,pr-ti,pr-wi); else printf(n作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间n); printf(%st%ct%dt%dt%dt%4.2ft%4.2fn, pr-name,pr-state,pr-ts,pr-ntime,pr-tc,pr-ti,pr-wi); p=head; do if(p-state=W) if(m=3) printf(%st%ct%dt%dt%4.2fn, p-name,p-state,p-ts,p-ntime,p-super); else printf(%st%ct%dt%dn, p-name,p-state,p-ts,p-ntime); p=p-link; while(p!=NULL); p=head; do if(p-state=F) if(m=3) printf(%st%ct%dt%dt%4.2ft%dt%4.2ft%4.2fn, p-name,p-state,p-ts,p-ntime,p-super,p-tc,p-ti,p-wi); elseprintf(%st%ct%dt%dt%dt%4.2ft%4.2fn, p-name,p-state,p-ts,p-ntime,p-tc,p-ti,p-wi); p=p-link; while(p!=NULL);void last()eti/=n;ewi/=n; printf(n平均周转时间%7.3fn平均带权周转时间=%7.3fn,eti,ewi);super()JCB *padv;padv=head;do if(padv-state=W&padv-tssuper=(float)(time-padv-ts+padv-ntime)/padv-ntime; padv=padv-link;while(padv!=NULL);void hrn(m)JCB *min;int i,iden;for(i=0;istate=W&p-tssupermin-super) min=p; p=p-link; while(p!=NULL); if(iden) i-;time+;printf(ntime=%d,time); if(time1000)printf(nruntime is too long.error.);getch(); else running(min,m); void sjf(int m) JCB *min; int i,iden; for(i=0;istate=W&p-tsntimentime) min=p; p=p-link; while(p!=NULL) ; if(iden) i-;printf(ntime=%d,time);time+; if(time100)printf(nruntime is too long.error);getch(); elserunning(min,m); fcfs(int m) int i,iden; for(i=0;istate=W&p-tslink; while(p!=NULL&iden) ; if(iden) i-;printf(ntime=%d,time);time+; if(time100)printf(nruntime is too long.error);getch(); else running(p,m); running(JCB *p,int m) p-tb=time;p-state=R; p-tc=p-tb+p-ntime; p-ti=(float)(p-tc-p-ts); p-wi=(float)(p-ti/p-ntime); eti+=p-ti; ewi+=p-wi; print(p,m); time+=p-ntime; p-state=F; printf(n作业%s已经完成!npress any key to continue.n,p-name); getch();void runjcb(int m) printf(nn作业开始运行); switch(m)case 1:fcfs(m);break; case 2:sjf(m);break; case 3:hrn(m);break; default:printf(n运行错误!n);exit(); start() int m; char str100=n选择调度算法:n1.先来先服务FCFSn2.最短作业优先SJFn3.响应比高者优先HRNn ; printf(%s,str); m=getch()-48; inital(); if(1=m&m=3) runjcb(m); else printf(n选择错误,请重新选择!n); start(); last();main()start(); printf(n所有作业完成!); getch();运行结果:1、选择先来先服务FCFS选择调度算法:1.先来先服务FCFS2.最短作业优先SJF3.响应比高者优先HRN输入作业数:5输入:作业名到达时间服务时间A04B13C25D32E44作业开始运行Time=0作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间AR044 4.001.00BW13CW25DW32EW44作业A已经完成Press any key to continueTime=4作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间BR137 6.002.00CW25DW32EW44AF044 4.001.00作业B已经完成Press any key to continueTime=7作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间CR25 12 10.002.00DW32EW44AF044 4.001.00BF137 6.002.00作业C已经完成Press any key to continueTime=12作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间DR321411.005.50EW44AF044 4.001.00BF137 6.002.00CF25 12 10.002.00作业D已经完成Press any key to continueTime=14作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间ER441814.003.50AF044 4.001.00BF137 6.002.00CF25 12 10.002.00DF321411.005.50作业E已经完成Press any key to continue平均周转时间9.000平均带权周转时间=2.800所有作业完成!2、选择最短作业优先SJF(简要过程) 作业开始运行Time=0作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间AR044 4.001.00BW13CW25DW32EW44作业A已经完成Press any key to continueTime=4作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间DR3263.001.50BW13CW25EW44AF044 4.001.00作业D已经完成Press any key to continueTime=6作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间Br1398.002.67CW25EW44AF044 4.001.00DF3263.001.50作业B已经完成Press any key to continueTime=9作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间ER44139.002.25CW25AF044 4.001.00BF1398.002.67DF3263.001.50作业E已经完成Press any key to continueTime=13作业名 状态 到达时间 服务时间 完成时间 周转时间 带权周转时间CR251816.003.20AF044 4.001.00BF1398.002.67DF3263.001.50EF44139.002.25作业C已经完成Press any key to continue平均周转时间8.000平均带权周转时间=2.123所有作业完成!3、响应比高者优先HRN(简要过程) 作业开始运行Time=0作业名 状态 到达时间 服务时间 优先权 完成时间 周转时间 带权周转时间AR041.004 4.001.00BW130.00CW25DW32EW44作业A已经完成Press any key to continueTime=4作业名 状态 到达时间 服务时间 优先权 完成时间 周转时间 带权周转时间BR132.0076.002.00CW25DW32EW44AF041.004 4.001.00作业B已经完成Press any key to continueTime=7作业名 状态 到达时间 服务时间 优先权 完成时间 周转时间 带权周转时间DR323.0096.003.00CW25EW44AF041.004 4.001.00BF132.0076.002.00作业D已经完成Press any key to continueTime=9作业名 状态 到达时间 服务时间 优先权 完成时间 周转时间 带权周转时间CR252.401412.002.40EW442.25AF041.0044.001.00BF132.0076.002.00DF323.0096.003.00作业C已经完成Press any key to continueTime=14作业名 状态 到达时间 服务时间 优先权 完成时间 周转时间 带权周转时间ER443.251814.003.50AF041.0044.001.00BF132.0076.002.00CF252.401412.002.40DF323.0096.003.00作业E已经完成Press any key to continue平均周转时间8.400平均带权周转时间=2.380所有作业完成!(二)、编写并调度一个多道程序系统的作业调度模拟程序。 作业调度算法:采用基于先来先服务的调度算法。可以参考课本中的方法进行设计。 对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的CPU时限等因素。而在多道批处理系统中,作业首先存放在外存,当系统拥有的资源足够分配给一个作业,就将资源分配给此作业,并将此作业调进内存。当系统资源不足以分配给一个作业时,则等待已经分配资源的作业运行完成后释放资源增加系统资源。程序及运行结果如下:#include#include#define getb(type) (type *)malloc(sizeof(type)#define NULL 0typedef struct JCB/定义作业控制块JCBchar name10;/作业名int stime;/开始运行时刻int rtime;/需要运行时间,即提供服务的时间char state;/作业状态JCB *next;/链指针JCB;JCB *ready=NULL,*p;int T;/时间量int ttime;/总周转时间float trtime;/总的带权周转时间void sort()/构造链表存放作业JCB *fir,*sec; if(ready=NULL)ready=p;elsefir=ready-next;if(fir=NULL)sec=ready; else while(fir!=NULL) sec=fir;fir=fir-next;sec-next=p;void init()/输入作业参数int i,num; printf(输入作业数:); scanf(%d,&num);/输入作业数 for(i=0;iname); printf(开始运行时刻:); scanf(%d,&p-stime); printf(需要运行时间:); scanf(%d,&p-rtime); p-state=w;/每个作业的初始状态总是等待W p-next=NULL; sort(); T=0;/时间量ttime=0;/总周转时间trtime=0;/总的带权周转时间getchar();/接收字符int length()/链表长int i=0; JCB *q; q=ready; while(q!=NULL)i+;q=q-next; return i;void destroy(int end)/完成作业int i=end;float W;printf(n作业完成时间:%d,i);printf(n周转时间:%d,i-(p-stime);W=(float)(i-(p-stime)/(float)(p-rtime);/带权周转时间周转时间/提供服务的时间printf(n带权周转时间:%2.2f,W);void run()/运行作业int start,end;start=T;/初始值为0end=(p-rtime)+start;/作业完成时间运行时间开始运行时刻ttime+=end-p-stime;/总周转时间完成时间开始运行时刻trtime+=(float)(end-(p-stime)/(float)(p-rtime);/总的带权周转时间T+=p-rtime;destroy(end);void main()/主函数int len,count;count=0;printf(ttcopyright:林庆达 计算机03(7)班);printf(nt *作业调度算法:先来先服务(FCFS)*n);init();/初始化数据len=length();/就绪作业的长度 printf(npress any key to continue .);getchar();while(len!=0)&(ready!=NULL)/若就绪队列不为空count+;p=ready;printf(n正在执行的作业是: %s.,p-name);ready=ready-next;p-next=NULL;p-state=r;run();printf(npress any key to continue .);getchar();printf(n所有作业全部完成运行!n);printf(平均周转时间为:%3.2fn,(float)ttime/(float)count);/总周转时间/作业数printf(平均带权周转时间为:%3.2fn,trtime/(float)count);/总的带权周转时间/作业数getchar();运行结果: Copyright:林庆达 计算机03(7)班 *作业调度算法:先来先服务(FCFS)*输入作业数:5输入第1个作业的信息:作业名:A开始运行时刻:0需要运行时间:4输入第2个作业的信息:作业名:B开始运行时刻:1需要运行时间:3输入第3个作业的信息:作业名:C开始运行时刻:2需要运行时间:5输入第4个作业的信息:作业名:D开始运行时刻:3需要运行时间:2输入第5个作业的信息:作业名:E开始运行时刻:4需要运行时间:4Press any key to continue正在执行的作业是:A作业完成时间:4周转时间:4带权周转时间:1.00Press any key to continue正在执行的作业是:B作业完成时间:7周转时间:6带权周转时间:2.00Press any key to continue正在执行的作业是:C作业完成时间:12周转时间:10带权周转时间:2.00Press any key to continue正在执行的作业是:D作业完成时间:14周转时间:11带权周转时间:5.50Press any key to continue正在执行的作业是:E作业完成时间:18周转时间:14带权周转时间:3.50Press any key to continue所有作业全部完成运行!平均周转时间为:9.00平均带权周转时间:2.80Press any key to continue五、心得体会:通过实验和课程设计,还进一步锻炼了自己的编程能力,增强了实践和动手能力,使自己的编程能力和逻辑思考能力有了较大的进步。实验三 存储管理一.实验目的:存储管理的主要功能之一是合理分配空间,请求页式管理是一种常用的虚拟存储管理技术。本实验的目的是通过请求页式管理中的页面置换算法设计,了解虚拟存储技术的特点,掌握请求页式管理的页面置换算法。二.实验内容:1、分区管理的原理:将存储器划分成若干段大小固定的区域,一个区域里只能运行一个程序,程序只能在其自身所在的分区中活动。 2、固定式分区管理的原理:区域大小及起始地址是固定的。一个分区只能存放一个程序。需要设置一个分区说明表来标明内存的使用状态。根据分区说明表来给程序分配相应的区域。由于程序不可能刚刚占有一个分区的大小 ,这样就会在一个分区之中留下零头,造成了极大的浪费。 3、可变式分区管理的原理:区域的大小及起始地址是可变的,根据程序装入时的大小动态地分配一个区域。保证每个区域之中刚好放一个程序。这样可以充分地利用存储空间,提高内存的使用效率。如果一个程序运行完毕,就要释放出它所占
展开阅读全文