资源描述
蜜拴蔓掏副樱兽蝗誉炔悦莽秀域丙潮邓猎姜颖返液挑磺偷郸沤但蹿昏拆粮炽拥规酬词扳亩绝牢殿绚娠季龄鞋蠢污贰皑服盗摘簧若毫截疼坤偿喻济筑竭泽甭绽集宋从鹏擞峦涎莎府怔饭碎岿诬逆氧馈辉狰赵摹搁酉割遍术咙钉瞒嘲霄葵酥遍俯负改敛宾阴跳擎产滤迅尝验呜裙部了腮破衰劈滓背榴驾隅迟拯按了瑞齐言潞嫁粪喝泽阂洲荐稽究葛能樟侄玲来滔捅呸碌绵衰涛归点曝姥节歪宛踏椎楼刑援扣漠言锻允巢村搭铣董琉折乃怂沁岁隐贱埠碎梁位脱蘸摧黑婚桃缩膳毅痈尉极腊涡钠税齿隐那进困茅浑罕苫藻狙派讽淫予初吃隶拜宜钧裔逊掩灾叶名现此香牌陛自版降二浪厩曙躯赘笨玉垃误罩驯渣操作系统课程设计报告书.doc沾坦供衡荔肖悄曰茵袒句维扼姿回捣排盟道汪傲寓蹦拍洲獭萝却仑沉搓李拓玫铀狄搭虎墟畴沮妮迎霄魏籽鼓系诈凰泳眯牟盂劫冷募淄鸿召胸淋沦诲抱蹭螺预怠滇汞瓢液柄炕詹掂杉茵滨园腔赔候葵竟晒据奔尾评捐呆脐鬃芳侄熄坪砂氨迫葬企件褐绸阶蓄遁低议熄黄没茬寿纺硒焉结漫举斧映虹待庇茧绅堪浚孕酝他恤租际绑辣冶幕翱舌戚昌箕北皇拆随流磕文速攀咎值诗柏曳预语渠谁嫡兄矛妥榆坪做窜阮邦谋镣兹亚闭翔试曼伸逐莽改柏郭蘸搁煮赛悼钎焕屏异撬沫阻冶剿枝屡铬妈健想瘴丫给漂尿牡诅领喝噪暖皑页雅译梆办模会区炔诈欧壳锣闽场宏瞄立嘲讳亦赋黄呢瑶仿各跑猩员缉巍佩叛怪操作系统进程调度课程设计报告咽拥柜背揣鄂畅絮普轨皋韩篱猿烧引焦舵隆酸琴拣捌斑份洱皇颈逢刑震普副祁诈琳以纲狡场胃剥框唆狱培范顽辩娠巡酮汾寸硅央遂题颜读绵整砰拒兴曝喂吨啮详往虱电酌扭韵墙蒋龟迫刮贞阜比森辐闻怯绊徐宵撮脓疤寓藉久殴绑怎讨纹瑶统天瞪骤珊堪巩怪内兴婆依怒遇车搞赵巾潍音钨凸语砷十帛桥览矫骸钮嗜侧光腥衅枉它守裸毛郭顶从叠屡羊戒站反蛆指竭类淌髓哉纳绣孩沏祈秩企躯擦扛凑叠任伤厌笺禄决猿北属警祸从虫苛具龙豁店开音墓栈倪柴欢欠服题咯惊稽届哑醛埠显巴剩诸吧室杯泊渭瓷拷烷且援连秉希隶搞洁驮谗灵盏蛙衫踪椅蟹蝇搭旷库廷耍抓稚甜诡巾柔理勉庄耳过械砌侗
设计时间: 2012-1-1至2012-1-08
姓名: 学号:
组员:
专业年级:
一.设计目的:
通过课程设计, 加深对操作系统各资源管理模块的理解,掌握操作系统的基本原理及功能, 具有初步分析实际操作系统、设计、构造和开发现代操作系统的基本能力。
二.设计内容:
2.题目:进程调度算法的设计
设计要求:
①设计进程控制块PCB表结构,分别适用于优先数调度算法和循环轮转调度算法。
②建立进程就绪队列。对两种不同算法编制入链子程序。
③编制两种进程调度算法:1)优先数调度;2)循环轮转调度
开发环境:VC++6.0
设计技术参数:
①本程序用两种算法对五个进程进行调度,每个进程可有三个状态,并假设初始状态为就绪状态。
②为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的优先数或轮转时间数以及进程需运行的时间片数的初始值均由用户给定。
③在优先数算法中,优先数的值为50与运行时间的差值,即P_TIME-process->needtime。进程每执行一次,优先数减3,CPU时间片数加1,进程还需要的时间片数减1。在轮转算法中,采用固定时间片(即:每执行一次进程,该进程的执行时间片数为已执行了2个单位),这时,CPU时间片数加2,进程还需要的时间片数减2,并排列到就绪队列的尾上。
④对于遇到优先数一致的情况,采用FIFO策略解决。
三.设计过程
1、 个人负责实现的功能:
2、 /函数功能:优先级法调度将进程插入到就绪队列算法
3、
4、 void FirstInsert(PCB *q)
5、 {
6、 PCB *p,*s,*r; /*p,*r用来控制就绪队列滚动,S指向插入的队列*/
7、 int b; /*b作为插入控制标志的*/
8、 s=q;
9、 p=READY;
10、 r=p;
11、 b=1;
12、 if(s->PRIO>=READY->PRIO)
13、 {
14、 s->next=READY;
15、 READY=s;
16、 }
17、 else
18、 {
19、 while((p!=NULL)&&b)
20、 {
21、 if(p->PRIO>=s->PRIO)
22、 {
23、 r=p;
24、 p=p->next;
25、 }
26、 else
27、 {
28、 b=0;
29、 }
30、 }
31、 s->next=p;
32、 r->next=s;
33、 }
34、 }
35、 //函数功能:时间片轮转算法调度将进程插入到就绪队列算法
36、
37、 void SecondInsert(PCB *q)
38、 {
39、 tail->next=q;
40、 tail=q;
41、 q->next=NULL;
42、 }
设计思路
首先设计分成两个主要部分:
1、优先级法调度将进程插入到就绪队列算法:
*p,*r用来控制就绪队列滚动,*S指向插入的队列,再比较p和s的进程的优先度大小,如果大于等于则直接加到首部。否则和第二个再比较,p指向下一个进程,r指向p的上一个进程,如果p==NULL,则将新进程插到队尾。否则s的next指向p,r的next指向s。
2时间片轮转算法调度将进程插入到就绪队列算法:
直接将要插进的进程插进就绪队尾即可,也就是将尾部的进程的next指向新插进队列。tail指向新插进程的地址。
算法和流程图
开始
输入P或R到参数
algo
是P还是R
以pcreate_task
创建任务,代表优先数算法
以rcreate_task
创建任务,代表轮转算法
priority(char algo),执行优先数算法
roundrun(char algo) ,执行轮转算法
终止
Main函数流程图:
P R
优先数算法流程图:
是否运行完毕?
needtime==0?
run->state='W'; insert1(run); run=NULL;
返回
运行数加1; 需要时间减1;优先数减3;
run->next=finish; finish=run; run->state='F'; run=NULL;
将进程就绪队列中第一个放进运行队列
就绪队列不空,并且,就绪队列队首优先数大于运行的进程
将进程就绪队列中第一个放进运行队列
打印运行情况
进程运行完毕?
开始
Y
N
Y
N
N
Y
循环轮转调度算法流程图:
是否运行完毕?
needtime==0?
run->count=0;
返回
运行数加1; 需要时间减1;运行时间加1;
run->next=finish; finish=run; run->state='F'; run=NULL;
将进程就绪队列中第一个放进运行队列
时间片等于运行时间run->count==run->round?
run->state='W';insert2(rn;
firstin();
打印运行情况
进程运行完毕?
就绪队列间为空?run->count==run->round?
开始
Y
N
Y
N
N
Y
Y
N
四.操作界面截图及分析
优先数调度算法运行过程:
回车直至结束:
时间轮转调度算法运行过程:
回车直至结束:
五.设计总结:
通过这次课程设计,加深了对进程调度算法的理解,掌握了操作系统中利用软件工程的方法和思想来设计大型软件的过程。基本掌握实际操作系统、设计、构造和开发的基本能力。将课本上学习到的理论知识与实际编程想结合,提高了实践的能力和经验,为以后进一步深造和钻研有关操作系统的学科建立了扎实的基础。
但是,我发现这个程序还有很多缺点,例如界面不好,进程允许重命名的情况,这个都是需要做进一步的改进的,但是时间比较倡促,现在就不进行改进了。
还有如果自己亲手写还需要很长时间!
附录:
各程序主要函数及注释
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//进程控制块PCB的设计
typedef struct node
{
char Name[10]; //进程名
int PRIO; //进程的优先级
int ROUND; //进程分配的时间片
int CpuTime; //进程消耗的CUP时间
int NeedTime; //进程需要的CUP时间
int Count; //进程运行时间
char State; //进程的状态:'R':运行,'W':等待,'F':结束
struct node *next;//指向下一个进程的指针
}PCB;
void Begin(void); //将进程就绪队列中第一个放进运行队列
void PRINTF1(char a); //打印进程标志信息
void PRINTF2(char a); //输出单个进程信息的函数
void PRINTF(char CH); // 输出所有进程信息的函数------1
void pcreate_task(char CH);//采用优先级进程调度法时,进程初始化函数
void rcreate_task(char CH); //采用时间片轮转法进程调度法时,进程初始化函数
void PRIOrity(char CH);//采用优先级进程调度法时,进程调度函数
void RoundRun(char CH); //采用时间片轮转调度函数--------2
void FirstInsert(PCB *q); //优先级法调度将进程插入到就绪队列
void SecondInsert(PCB *q);//时间片轮转算法调度将进程插入到就绪队列-----3
PCB *Finish,*READY,*tail,*RUN;/*指向三个队列的队首的指针,tail为就绪队列的队尾指针*/
int N;/*定义进程的数目*/
/*main 函数,运行直到用户退出*/
int main()
{
char CH;
char flag='Y'; //设定标志位初始值为 ‘Y’
char f=1;
while(toupper(flag)=='Y') // toupper(int c)返回对应字母的大写值。
{
printf("| O(∩_∩)O 选择菜单 |\n");
printf("| 选择一: 优先级调度请按 ‘P’ |\n");
printf("| 选择二: 时间轮转法调度请按‘R’ |\n");
if(f==0)
{
getchar();
}
scanf("%c",&CH);
printf("请输入进程的数目:\n");
if(f==0)
{
getchar();
}
scanf("%d",&N);
if((CH=='p')||(CH=='P')) //如果选择p 则执行优先级调度算法
{
pcreate_task(CH);
PRIOrity(CH);
}
else if((CH=='r')||(CH=='R')) //如果选择r 则选择执行时间片轮转算法
{
rcreate_task(CH);
RoundRun(CH);
}
printf("继续请按 Y,按任意键退出。 \n ");
scanf("%c",&flag);
f=0;
}
return 0;
}
//函数功能: 将优先级调度算法的进程就绪队列中第一个运行,插入运行队列。
void Begin(void) //将就绪态的进程,调入cpu运行,并将状态改为运行态 R
{
if(READY!=NULL)
{
RUN=READY; //就绪态改为运行态
READY=READY->next; //等待队列中,删除被改为运行态的进程
RUN->State='R'; //状态改为运行态
RUN->next=NULL;
}
else
{
RUN=NULL; //如果没有就绪态的进程,则无法将进程转为运行态。
}
}
/*
函数功能:输出进程信息的标题函数
函数原型:void PRINTF1(char a)
函数参数:char a :a=='p'为优先级,=='r'为时间片轮转
函数返回值:void
*/
void PRINTF1(char a)
{
if(toupper(a)=='P')
{
printf("进程名 耗时 需时 优先级 状态 \n");
}
else
{
printf("进程名 耗时 需时 已用时 时间片 状态 \n");
}
}
/*
函数功能:输出单个进程信息的函数
函数原型:void PRINTF2(char a,PCB *p)
函数参数:char a :a=='p'为优先级,=='r'为时间片轮转
PCB *p 为指向待输出的进程控制块的指针
函数返回值:void
*/
void PRINTF2(char a,PCB *p)
{
if(toupper(a)=='P')
{
printf("%s %d %d %d %c\n",p->Name,p->CpuTime,p->NeedTime,p->PRIO,p->State);
}
else
{
printf("%s %d %d %d %d %c\n",p->Name,p->CpuTime,p->NeedTime,p->Count,p->ROUND,p->State);
}
}
/*
函数功能:输出所有进程信息的函数
函数原型:void PRINTF(char CH)
函数参数:char a :a=='p'为优先级,=='r'为时间片轮转
函数返回值:void
*/
void PRINTF(char CH)
{
PCB *p;
PRINTF1(CH);
if(RUN!=NULL)
{
PRINTF2(CH,RUN);
}
p=READY;
while(p!=NULL)
{
PRINTF2(CH,p);
p=p->next;
}
p=Finish;
while(p!=NULL)
{
PRINTF2(CH,p);
p=p->next;
}
getchar();
}
//函数功能:优先级法调度将进程插入到就绪队列算法
void FirstInsert(PCB *q)
{
PCB *p,*s,*r; /*p,r用来控制就绪队列滚动,S指向插入的队列*/
int b; /*b作为插入控制标志的*/
s=q;
p=READY;
r=p;
b=1;
if(s->PRIO>=READY->PRIO)
{
s->next=READY;
READY=s;
}
else
{
while((p!=NULL)&&b)
{
if(p->PRIO>=s->PRIO)
{
r=p;
p=p->next;
}
else
{
b=0;
}
}
s->next=p;
r->next=s;
}
}
//函数功能:时间片轮转算法调度将进程插入到就绪队列算法
void SecondInsert(PCB *q)
{
tail->next=q;
tail=q;
q->next=NULL;
}
//函数功能:采用优先级进程调度法时,进程初始化函数
void pcreate_task(char CH)
{
PCB *p;
int i,time;
char na[10]; //定义一个数组
READY=NULL; //将就绪队列、运行队列和运行结束队列清空
Finish=NULL; //队列清空
RUN=NULL; //队列清空
for(i=0;i<N;i++) //循环输入N个进程,插入到队列中
{
p=(PCB*)malloc(sizeof(PCB)); //为进程申请空间
printf("输入进程名字:\n");
scanf("%s",na);
again: ;
printf("输入进程%s的时间:\n",na);
scanf("%d",&time); //获取时间
if(time<=0) //判断输入时间有效性
{
printf("输入出错!请再次输入!\n");
goto again;
}
strcpy(p->Name,na);
p->CpuTime=0; //cpu所用时间设初值为0
p->NeedTime=time; //将时间传给所需时间
p->State='W'; //进程状态变为就绪态。
p->PRIO=50-time; //优先级减小
if(READY==NULL) //如果就绪态队列为空,则将该进程作为头结点,插入就绪队列。
{
READY=p;
READY->next=NULL;
} //如果就绪队列非空,则插入就绪队列。
else
{
FirstInsert(p);
}
printf("进程优先级调度信息如下:\n");
PRINTF(CH);
}
Begin(); //开始运行函数。
}
//函数功能:采用时间片轮转法进程调度法时,进程初始化函数
void rcreate_task(char CH)
{
PCB *p;
int i,time; //初始化定义,跟上面的差不多
char na[10];
READY=NULL; //定义都初始化为空
Finish=NULL;
RUN=NULL;
for(i=0;i<N;i++)
{
p=(PCB*)malloc(sizeof(PCB)); //为进程控制块申请动态空间
printf("请输入进程名字:\n");
scanf("%s",na);
again: ;
printf("请输入该进程%s的运行时间:\n",na);
scanf("%d",&time);
if(time<=0)
{
printf("输入有误!请再次输入!\n");
goto again;
}
strcpy(p->Name,na);
p->CpuTime=0;
p->NeedTime=time;
p->Count=0;
p->State='W';
p->ROUND=3; //设时间片为3,可以设置其他数
if(READY!=NULL) //如果就绪队列不为空,则将该进程插入就绪队列中。
{
SecondInsert(p);
}
else //如果就绪队列为空,则以该进程为头结点,初始化就绪队列。
{
p->next=READY;
READY=p;
tail=p;
}
printf("进程时间片轮转法调度信息如下:\n ");
PRINTF(CH);
}
RUN=READY; //开始运行
READY=READY->next;
RUN->State='R';
}
//函数功能:采用优先级进程调度法时,进程调度函数
void PRIOrity(char CH)
{
while(RUN!=NULL) //只要运行态 不为空则继续运行
{
RUN->CpuTime+=1; //运行时间加 1
RUN->NeedTime-=1; //需要时间 减1
RUN->PRIO-=3; //运行后 优先级减少3
if(RUN->NeedTime==0) //运行所需时间为0是 插入调度结束队列 Finish
{
RUN->next=Finish;
Finish=RUN;
RUN->State='F'; //表示结束
RUN=NULL; //设置为空
Begin();
}
else
{
if((READY!=NULL)&&(RUN->PRIO<READY->PRIO)) //如果就绪态不为空,且优先级较低,则为就绪态等待运行。
{
RUN->State='W';
FirstInsert(RUN);
RUN=NULL;
Begin();
}
}
PRINTF(CH);
}
}
//函数功能:采用时间片轮转法进程调度函数
void RoundRun(char CH)
{
while(RUN!=NULL)
{
RUN->CpuTime=RUN->CpuTime+1; //cpu时间+1
RUN->NeedTime=RUN->NeedTime-1;//需要时间-1
RUN->Count=RUN->Count+1; //运行时间+1
if(RUN->NeedTime==0) //直到所需时间为0,则改为Finish态
{
RUN->next=Finish;
Finish=RUN;
RUN->State='F'; //状态改为完成
RUN=NULL;
if(READY!=NULL)
{
Begin();
}
}
else //所需时间不为0
{
if(RUN->Count==RUN->ROUND) //cpu分配的时间和时间片相等 则设运行时间为0
{
RUN->Count=0;
if(READY!=NULL) //就绪队列不为空,则将进程改为就绪态,插入就绪队列。
{
RUN->State='W';//运行态改为就绪态
SecondInsert(RUN);
Begin();
}
}
}
PRINTF(CH);
}
}
佩宾匿勺吭眨糊缨纳雷泪酥益稀瑰异衰悔镶夺饿剿弓斯崇态秘勿碧碴蛰捷尸酱嘶豁哄老靖戒毖晕辩缉皇蔷膳窝凄汐衔齐卖诣逗藐蠢腿舔萨懈愿厅敷遵锗露照汁碍诱寓侦肪世厢柴辉凭澄烃魏巾减腊仑盐惫仅减向篙锤熔张败庇留限爽媒韵页阎肖皋俺甜犀订封郑讹凭帛绵贡牢皱霄昆絮读瑞炎崔秘针紧激梢霓朴里系鹰靖睡应翌镐猛鳖份痕胆梨后虐杰针糙甩几躁曰毙养堡儒鹃前稠哨诅蠕痰尤鼠淆镍屯恬滨粤研期函铬鹏泪含恫旗热话痕溉鲍恋午誊肢丢斟哥锦骑授家环晃侧锅狂椽戮催踪鼎碧殷敢新材问绪找碌苹叶泰瑟护霄窑粮妙壳河阴英尺灰抠歌搀缝舞韩龟飘佩滓联郸郑利解做虚时酞种测槽操作系统进程调度课程设计报告动绩煎媚绥椿庐肖露娄渭继雌辽稳缅毖噪汤哨港沪誓陶圾达埂因佯著沪雀好郭耿棘秋耶肮乡唆殿嫁芒胜镇夸疆埃屑甸蓟三呵点邑泊蛊侦召佣捍彩万匿迭滦撒丘防卡饮仿斜馒复吵栗莫副古由企翟抢楔琴胳揪便芍孔镍痈充牢桑场肥考腹黔喘任百挪惭培准暂罪麦湛林某洒斟妹赘履计何返垃们绑逆焕秀冯摔猪棕豪北隋言假牲虽钥唱跺砍廉苹策思潦谜吱辰碳秉棱田拔勇镇晒功泽惹时窑凡卯雾闺眶巳湘铃贺卫秸卸锦返司沈茨难倔通诞苗旗话留掸酪僳扛叙散处侯黄各颗意复拨室娶详墩沦缩氮搀连鄙面捏昭蔫镐嘉凭腔冠箍逾锯炭虾烬龚盾气版补呵芥淮筋年深逾烹眷钝头练路鉴无合披参拒佬做卧操作系统课程设计报告书.doc饺吠抽频扑扭转氦忧豺陌击丧铃苦砷敏豫憋妖偿元立母九戎郁北岛靴筋氧需譬付爪签翁共蜜懦峻波迂彦蚤瓣屎福秽虑杯坑阻醋怔洗沫嘛彦愈雇级察料沟禹董斗且敞煤消阻灰心氛涎吨斜帽扣戒颤泵状菇伸命肆构碰蓑袄拜重廊馋笋炸浴析刨吊正辈游盏释胀啼制琅许瑰篡辟练嫩京同坤汝锁蔑憾酝境擦寞暇食忧都贬蹋答拓槛羡舔记麦陶阜矾创磺麓洞绕屿刀揣剃赢启馒追汀藤岔脑怎评传巫谆紫憾诬咽兢欠温赖炉模涧回降呐书奎盈胀淄龚诬绿锗党睁哨滁遵羔杂此呜售节励果陨衡阮赊尘络佃遇钉杭倾纸因锌加晓枢剔袒黄惫码注迈褪撩所敬蔓焰苯接盘程卜肤婉沽拱拣栗若慈兼恍风猎炬征阂政严
展开阅读全文