2013-2014学年第二学期《高级语言程序设计》课程设计报告题目:进程调度模拟专业:计算机科学与技术班级:12级对口(3)班姓名:刘以鹏指导教师:代美丽成绩:计算机与信息工程系2014年 5月 23日目录1 1 设计目的及要求 (3)1.1 设计目的 (3)1.2 课程设计的实验环境 (3)1.3 课程设计的预备知识 (3)1.4 课程设计要求 (3)2 课程设计内容 (3)2.1程序功能介绍 (3)2.2程序整体设计说明 (4)2.2.1设计思路 (4)2.2.2数据结构设计及用法说明 (5)2.2.3程序结构(流程图) (5)2.2.4各模块的功能及程序说明 (6)2.2.5程序运行结果 (7)3 总结 (9)参考资料 (11)程序源代码 (12)1 设计目的及要求1.1 设计目的本课程设计是计算机科学与技术专业重要的实践性环节之一,是在学生学习完《程序设计语言(C)》课程后进行的一次全面的综合练习。
本课程设计的目的和任务:1. 巩固和加深学生对C语言课程的基本知识的理解和掌握2. 掌握C语言编程和程序调试的基本技能3. 利用C语言进行基本的软件设计4. 掌握书写程序设计说明文档的能力5. 提高运用C语言解决实际问题的能力1.2 课程设计的实验环境硬件要求能运行Windows 2000/XP操作系统的微机系统。
C语言程序设计及相应的开发环境。
1.3 课程设计的预备知识熟悉C语言及C语言开发工具。
1.4 课程设计要求1. 分析课程设计题目的要求2. 写出详细设计说明3. 编写程序代码,调试程序使其能正确运行4. 设计完成的软件要便于操作和使用5. 设计完成后提交课程设计报告2课程设计内容2.1程序功能介绍在多道程序环境下,进程数目往往多于处理机数目,致使他们争用处理机。
这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之运行。
分配处理机的任务是由进程调度程序完成的。
一个进程被建立后,系统为了便于对进程进行管理,将系统中的所有进程按其状态,将其组织成不同点进程队列。
于是系统中有运行进程队列、就绪队列和各种事件的进程等待队列。
进程调度的功能就是从就绪队列中挑选一个进程到处理机上运行。
2.2程序整体设计说明用C语言实现进程调度-操作系统课程设计设计思想:“最高优先数优先”调度算法的基本思想是把cpu分配给就绪队列中优先数最高的进程。
采用动态优先数,即优先数在创建进程时给定一个初始值,当进程获得一次cpu后其优先数就减少1。
它用C语言编写的实现模拟进程调度的程序,用户模拟几个进程,输入它们的进程名,优先级,运行时间等,进程的初使状态为就绪状态。
然后就按优先级优先方式调度各个进程,进程的状态也因此会变成等待状态或完成状态。
2.2.1设计思路进程是当前操作系统下一个被加载到内存的、正在运行的应用程序的实例。
每一个进程都是由内核对象和地址空间所组成的,内核对象可以让系统在其内存放有关进程的统计信息并使系统能够以此来管理进程,而地址空间则包括了所有程序模块的代码和数据以及线程堆栈、堆分配空间等动态分配的空间。
进程仅仅是一个存在,是不能独自完成任何操作的,必须拥有至少一个在其环境下运行的线程,并由其负责执行在进程地址空间内的代码。
在进程启动的同时即同时启动了一个线程,该线程被称作主线程或是执行线程,由此线程可以继续创建子线程。
如果主线程退出,那么进程也就没有存在的可能了,系统将自动撤消该进程并完成对其地址空间的释放。
加载到进程地址空间的每一个可执行文件或动态链接库文件的映象都会被分配一个与之相关联的全局唯一的实例句柄。
该实例句柄实际是一个记录有进程加载位置的基本内存地址。
进程的实例句柄在程序入口函数中通过第一个参数传递,其实际值即为进程所使用的基本地址空间的地址。
对于VC++链接程序所链接产生的程序,其默认的基本地址空间地址为0x00400000,如没有必要一般不要修改该值。
通过创建一个新的进程及在其地址空间内运行的主线程来启动并运行一个新的程序。
具体的,在执行函数时,首先由操作系统负责创建一个进程内核对象,初始化计数为1,并立即为新进程创建一块虚拟地址空间。
随后将可执行文件或其他任何必要的动态链接库文件的代码和数据装载到该地址空间中。
在创建主线程时,也是首先由系统负责创建一个线程内核对象,并初始化为1。
最后启动主线程并执行进程的入口函数RunProc(),完成对进程和执行线程的创建。
2.2.2数据结构设计及用法说明数据结构设计:本程序运用了struct函数,并用if语句判断运行指针,用while循环语句确定插入位置。
typedef struct PCB{char NAME[10]; //进程名字int PRIO; //进程优先数int ROUNT; //轮转时间片int COUNT; //计数器int NEEDTIME; //需要的CPU时间int CPUTIME; //占用cpu时间char *STATE; //进程状态}ElemPCB;用法说明:1.进程通过定义一个进程控制块的数据结构(PCB)来表示;2.每个进程需要赋予进程信息、进程到达时间、进程需要运行的总时间的属性;3.在程序进程中,以1为时间片单位;4.运行时,输入5个进程序列,按照进程的信息输出其执行序列。
2.2.3程序结构(流程图)2.2.4各模块的功能及程序说明①高级调度模块:又称作业调度。
其主要功能是根据一定的算法,从输人的一批作业中选出若干个作业,分配必要的资源,如内存、外设等,为它建立相应的用户作业进程和为其服务的系统进程(如输人、输出进程),最后把它们的程序和数据调人内存,等待进程调度程序对其执行调度,并在作业完成后作善后处理工作。
②中级调度模块:又称交换调度。
为了使内存中同时存放的进程数目不至于太多,有时就需要把某些进程从内存中移到外存上,以减少多道程序的数目,为此设立了中级调度。
特别在采用虚拟存储技术的系统或分时系统中,往往增加中级调度这一级。
所以中级调度的功能是在内存使用情况紧张时,将一些暂时不能运行的讲程从内存对换到外存上等待。
当以后内存有足够的空闲空间时,再将合适的进程重新换人内存,等待进程调度。
引人中级调度的主要目的是为了提高内存的利用率和系统吞吐量。
它实际上就是存储器管理中的对换功能。
③低级调度模块:又称进程调度。
其主要功能是根据一定的算法将CPU分派给就绪队列中的一个进程。
执行低级调度功能的程序称做进程调度程序,由它实现CPU在进程间的切换。
进程调度的运行频率很高,在分时系统中往往几十毫秒就要运行一次。
进程调度是操作系统中最基本的一种调度。
在一般类型的操作系统中都必须有进程调度,而且它的策略的优劣直接影响整个系统的计能。
2.2.5程序运行结果1. 运行界面2.进行调度界面总结通过做本实验,让我对进程或作业先来先服务、高优先权、按时间片轮转调度算法以及进程调度的概念和算法,有了更深入的认识!初步理解了操作系统对于作业处理的基本思想!对于时间片轮转法的处理要比优先级调度算法的理解要深。
在实验的过程中遇到了很多困难,感谢同学们的帮助。
C语言在我的世界里占有的地位无所能及,虽然是有那么多的课程,那么多的纷扰,我最喜欢的还是C语言,因为它是直接面对问题,无所畏惧,在众多的计算机学科中,C语言依旧是帝王!我手里捧着它,感到它是如此有分量。
当你必须要失去,唯一可以做的就是不要忘记!我首先觉得,用到的程序段不必太高级,因为天下事有高低之分,决定优劣的不是集体中某部分的强弱,起决定作用的是组合内各元素的和谐,要能在一个集体中各能尽其用,每个人都能发挥长处,避免自己的短处,那么这个集体的实际组合能量是最优的。
选择什么等级的语言就是关键,最后我决定运用文件,以及指针,去实现自己的构想。
文章设计有几个要求:要能录入新的文档,要能删除不需要的文档,要能按照关键字查找已有的文档,要能按照要求的顺序进行排序。
我的理解是:必须建立一个文件,它既能够保存新的录入文档,又能在提示语言的要求下读出文档。
然而,这只是万里长征的第一步。
后面的路还很长,困难还很多,可是我能成功的编译一个程序,能够在思路卡壳的情况下,继续前进,我在此很想感谢那些给予我耐心解答的老师和同学,是他们为我小程序的成功起到了关键性的作用,那么多个日夜,如此多的困难,同学们勤恳塌实,从开始到结束,没有显出一点倦意,始终热情高涨,我感谢这种氛围,感谢学校提供的良好条件。
在课程设计过程中,我学到了很多人生的哲理,懂得怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪,黑夜过去了,我们收获的是黎明。
在本次实践中,给我印象最为深刻的是在文件删除程序的编译过程中,先有我的各个子程序都已经编辑成功,那么这最后的程序就将是我成功的关键。
老天不会让我太过顺利,他在这最后的时刻设置的障碍,是要考验我的能力,他要置我于死地?在这个问题的解决上,我打了退堂鼓,我不能忍受长时间的无功而反,时间正在消磨我的意志。
没有了柳暗花明的一天,那么我怎么能说经受住了考验?我鼓起勇气,到处问,到处查资料,黄天不负有心人,在一篇文章上,终于看到了我所特别要求的函数,我实现了组合是关键的理论。
不得不说这是精神的胜利,是永不言败的精神。
参考资料[1] 谭浩强.C程序设计题解与上机指导.北京:清华大学出版社,2009[2] 廖雷.C语言程序设计.北京:高等教育出版社,2006[3] 贾学.宋海民.C语言程序设计.北京:中国铁道出版社,2007[4] 赵海廷.C语言程序设计.北京:人民邮电出版社,2006.[5] 范刚龙.王康平.C程序设计.武汉:武汉理工大学出版社,2006[6] 张强华. C 语言程序设计.北京:人民邮电出版社,2010[7] 徐新华. C 语言程序设计教程.北京:清华大学出版社,2010[8] 谭浩强. C 语言程序设计.北京:清华大学出版社,2011[9] 徐建民. C 语言程序设计.北京:电子工业出版社,2009[10] 李大友. C 语言程序设计. 北京:清华大学出版社,2008[11] 毕万新. C 语言程序设计.大连:大连理工大学出版社,2005[12] 刘燕. C 语言程序设计.北京:中国铁道出版社,2008[13] 廖雷. C语言程序设计.北京:高等教育出版社,2006[14] 方少卿. C语言程序设计.北京:中国铁道出版社,2007[15] 谭浩强. C语言程序设计. 北京:清华大学出版社,2007程序源代码#include<stdio.h>#include<malloc.h>typedef int Status;#define ERROR 0#define OK 1typedef struct PCB{char NAME[10]; //进程名字int PRIO; //进程优先数int ROUNT; //轮转时间片int COUNT; //计数器int NEEDTIME; //需要的CPU时间int CPUTIME; //占用cpu时间char *STATE; //进程状态}ElemPCB;typedef struct QNode{ElemPCB pcb;struct QNode *next;}QNode, *QueuePtr;typedef struct{ //就绪队列QueuePtr RUN; //当前运行进程指针QueuePtr READY; //头指针QueuePtr TAIL; //尾指针}READYQueue;typedef struct{ //完成队列QueuePtr FINISH; //头指针QueuePtr TAIL; //尾指针}FINISHQueue;Status Create(READYQueue &ready);Status Print(READYQueue ready,FINISHQueue finish); Status Printr(READYQueue ready,FINISHQueue finish); Status Fisrt(READYQueue &ready);Status Insert1(READYQueue &ready);Status Insert2(READYQueue &ready);Status Prisch(READYQueue &ready,FINISHQueue &finish);Status Roundsch(READYQueue &ready,FINISHQueue &finish);void main(){char ch;READYQueue ready;FINISHQueue finish;ready.READY=ready.TAIL=(QueuePtr)malloc(sizeof(QNode)); //存储分配ready.RUN=(QueuePtr)malloc(sizeof(QNode));ready.RUN->next=NULL;finish.FINISH=finish.TAIL=(QueuePtr)malloc(sizeof(QNode));Create(ready);//创建后就绪对列中printf("\n就绪对列中初始值:\n");Print(ready,finish);Fisrt(ready);printf("请您输入要选择调度的算法为\002 1.优先数调度, \002 2.时间片轮转法)请选择算法(1 or 2):\n");while(1){do{ch=getchar();scanf("%c",&ch);}while(ch!='1' && ch!='2');switch(ch){case '1'://优先数调度Prisch(ready,finish);break;case '2'://时间片轮转法Roundsch(ready,finish);break;}}Status Print(READYQueue ready,FINISHQueue finish){ //打印就绪队列中的进程状态QueuePtr p,q;p=ready.READY;q=finish.FINISH;//运行中的进程if(ready.RUN->next!=NULL){printf("%s",ready.RUN->next->);printf(":%s\t",ready.RUN->next->pcb.STATE);printf("这个优先数是:%d\n",ready.RUN->next->pcb.PRIO);}//就绪队列的进程while(p!=ready.TAIL){printf("%s",p->next->);printf(":%s\t",p->next->pcb.STA TE);printf("这个优先数是:%d\n",p->next->pcb.PRIO);p=p->next;}//完成队列的进程while(q!=finish.TAIL){printf("%s",q->next->);printf(":%s\t",q->next->pcb.STA TE);printf("这个优先数是:%d\n",q->next->pcb.PRIO);q=q->next;}return OK;}Status Printr(READYQueue ready,FINISHQueue finish){ //打印就绪队列中的进程状态QueuePtr p,q;p=ready.READY;q=finish.FINISH;//运行中的进程if(ready.RUN->next!=NULL){printf("%s",ready.RUN->next->);printf(":%s\t",ready.RUN->next->pcb.STATE);printf("进程剩余时间为:%d\n",ready.RUN->next->pcb.NEEDTIME);}//就绪队列的进程while(p!=ready.TAIL){printf("%s",p->next->);printf(":%s\t",p->next->pcb.STA TE);printf("进程剩余时间为:%d\n",p->next->pcb.NEEDTIME);p=p->next;}//完成队列的进程while(q!=finish.TAIL){printf("%s",q->next->);printf(":%s\t",q->next->pcb.STA TE);printf("进程剩余时间为:%d\n",q->next->pcb.NEEDTIME);q=q->next;}return OK;}Status Create(READYQueue &ready){QueuePtr p;int i=0 ;int n;printf(" \n \002 您好,这个是C语言模拟进程调度\002 \n\n");printf(" 您好! \002 \002 请输入进程的个数:");scanf("%d",&n);while(i<n){p=(QueuePtr)malloc(sizeof(QNode));printf("请您输入第%d进程名:",i+1);scanf("%s",p->);printf("请您输入进程需要的时间:");scanf("%d",&p->pcb.NEEDTIME);printf("请您输入进程的进程优先数:");scanf("%d",&p->pcb.PRIO);p->pcb.STATE="W";p->pcb.ROUNT=2;p->pcb.COUNT=0;i++;p->next=NULL;ready.TAIL->next=p;ready.TAIL=p;}return OK;}Status Fisrt(READYQueue &ready){if(ready.READY==ready.TAIL)return ERROR;ready.RUN->next=ready.READY->next;ready.RUN->next->pcb.STA TE="RUN"; //修改进程状态if(ready.TAIL==ready.READY->next)ready.READY=ready.TAIL;elseready.READY->next=ready.READY->next->next; //头指针后移printf("\n%s被从就绪队列调度运行\n",ready.RUN->next->);return OK;}Status Insert1(READYQueue &ready){int i=0,j=0;QueuePtr p=ready.READY,q;ElemPCB temp;QueuePtr s=(QueuePtr)malloc(sizeof(QNode));s->pcb=ready.RUN->next->pcb;s->next=NULL; //将未完成的进程插入就绪队列ready.TAIL->next=s;ready.TAIL=s;//按优先数从大到小排序for(p;p!=ready.TAIL;p=p->next){for(q=p->next;q!=ready.TAIL;q=q->next){if(p->next->pcb.PRIO < q->next->pcb.PRIO){temp=p->next->pcb;p->next->pcb=q->next->pcb;q->next->pcb=temp;}}}return OK;}Status Insert2(READYQueue &ready){QueuePtr p=ready.RUN->next;if(p->pcb.NEEDTIME > 0){ready.TAIL->next=p; //插入到就绪队列ready.TAIL=p;ready.RUN->next=NULL;}return OK;}Status Prisch(READYQueue &ready,FINISHQueue &finish){ int i=0 ;while(ready.RUN->next!=NULL){ready.RUN->next->pcb.CPUTIME++;ready.RUN->next->pcb.NEEDTIME--;ready.RUN->next->pcb.PRIO-=3;if(ready.RUN->next->pcb.NEEDTIME==0){finish.TAIL->next=ready.RUN->next; //插入到完成队列finish.TAIL=ready.RUN->next; //尾指针后移ready.RUN->next->pcb.STA TE="FINISH";ready.RUN->next=NULL;if(ready.READY!=ready.TAIL){Fisrt(ready);}}Else if(ready.READY!=ready.TAIL&&(ready.RUN->next->pcb.PRIO) < (ready.READY->next->pcb.PRIO)){ready.RUN->next->pcb.STA TE="W";printf("%s被调到就绪队列里为\n",ready.RUN->next->);Insert1(ready);Fisrt(ready);}i++;printf("\n进程执行第%d个时间片的结果为:\n",i);Print(ready,finish);}return OK;}Status Roundsch(READYQueue &ready,FINISHQueue &finish){int i=0;while(ready.RUN->next!=NULL){ready.RUN->next->pcb.CPUTIME++;ready.RUN->next->pcb.NEEDTIME--;ready.RUN->next->pcb.COUNT++;if(ready.RUN->next->pcb.NEEDTIME==0){finish.TAIL->next=ready.RUN->next; //插入到完成队列finish.TAIL=ready.RUN->next; //尾指针后移ready.RUN->next->pcb.STA TE="FINISH";ready.RUN->next=NULL;if(ready.READY!=ready.TAIL){Fisrt(ready);}}else if(ready.RUN->next->pcb.COUNT==ready.RUN->next->pcb.ROUNT){ready.RUN->next->pcb.COUNT=0;if(ready.READY != ready.TAIL){ready.RUN->next->pcb.STA TE="W";printf("%s被调到就绪队列里为\n",ready.RUN->next->);Insert2(ready);Fisrt(ready);}}i++;printf("\n进程执行第%d个时间片的结果为:\n",i); Printr(ready,finish);}return OK;}。