资源描述
课程设计阐明书
(操作系统)
题目: 进程调度
院 系:计算机科学与工程学院
专业班级: 信息安全13-2
学 号: 3029xx
学生姓名: xx
指引教师: xx
12月 15日
安徽理工大学课程设计(论文)任务书
计算机科学与工程学院
学 号
3029xx
学生姓名
Xx
专业(班级)
信息安全13-2
设计题目
进程调度模仿程序
设
计
技
术
参
数
(1)系统作业或进程数目;
(2)进程等待时间
(3)进程运营时间
设
计
要
求
1. 依照设计任务,用自己熟悉计算机语言编制程序,在机器上调试运营,并通过上机考核。
2. 模仿在单解决器状况下进程调度,目是加深对进程调度工作理解。
3. 设计一种准时间片轮转调度算法实现解决器调度程序。
4. 在完毕电子设计后,规定写一份详细设计报告。
工
作
量
1.编写代码不少于200行;
2.程设计阐明书不少于15页。
工
作
计
划
.11.23-11.25 依照课程设计规定,查找有关资料,完毕需求分析;
.11.26-11.27 进行系统概要设计;
.11.28-12.5 进行系统详细设计和源代码书写;
.12.6-12.10 对系统进行调试分析,写出课程设计报告。
参
考
资
料
[1] 龚沛曾等编.C/C++程序设计教程.北京:高等教诲出版社,.
[2] [美]Prata S.著. C Primer Plus(第5版 中文版).北京:人民邮电出版社,.
[3] 汤子瀛等编著. 计算机操作系统.西安:西安电子科技大学出版社,
[4] 胡志刚,谭长庚等,《计算机操作系统》,中南大学出版社
[5] 罗宇,邹鹏等,《操作系统》(第二版),电子工业出版社4月
[6] 庞丽萍,《操作系统原理》,华中理工大学出版社,
指引教师签字
教研室主任签字
安徽理工大学课程设计(论文)成绩评估表
学生姓名: xx 学号: 3029xx 专业班级: 信息安全13-2
程序设计训练题目: 进程调度模仿程序
评价单元
评价要素
评价内涵
满分
评分
知识水平
30%
文献查阅与
知识运用能力
能独立查阅文献资料,并能合理地运用到程序设计训练之中;能将所学课程(专业)知识精确地运用到程序设计之中,并归纳总结本程序设计训练所涉及关于课程知识
20
程序设计方案设计能力
程序设计整体思路清晰,程序设计方案合理可行
10
阐明书质量
50%
难度级别
与程序设计训练任务书题目难度级别相称
10
写作水平
整体思路清晰,构造合理,层次分明,语言表达流畅,综合概括能力强
30
写作规范
符合程序设计训练报告基本规定,用语、格式、图表、数据及各种资料引用规范(符合原则)
10
学习体现
20%
工作量
程序设计训练工作量饱满,能准时完毕程序设计训练规定工作量
10
学习态度
学习态度认真,遵守程序设计阶段纪律,作风严谨,准时完毕程序设计规定任务,准时上交程序设计训练关于资料
10
成绩:
指引教师:
年 月 日
摘要
当代计算机系统中,进程是资源分派和独立运营基本单位,是操作系统核心概念。因而,进程就成为理解操作系统如何实现系统管理最基本,也是最重要概念。进程调度是进程管理过程重要构成某些,是必然要发生事件。
在当代操作系统中,进程并发机制在绝大多数时候,会产生不断变化进程就绪队列和阻塞队列。处在执行态进程无论是正常或非正常终结、或转换为阻塞状态,都会引起从就绪队列中,由进程调度选取一种进程进占CPU。
进程调度核心是进程调度算法.在本课程设计中,用良好清晰界面向顾客展示了进程调度中时间片轮转调度算法。在最后实现成果中,顾客可指定需要模仿进程数,CPU时间片和进程最大执行时间,并且选取需要演示算法,界面将会动态显示进程调度过程及各个队列变化。 通过此进程调度模仿系统,顾客可以对时间片轮转调度算法有进一步以及直观理解。
核心词:进程,调度,PCB,时间片轮转 目录
1.设计目 6
2.设计思路 6
3.设计过程 8
3.1流程图 8
3.2算法 8
3.3数据构造 10
3.4源代码 10
4.实验成果及分析 20
4.1 使用阐明 20
4.2程序演示 20
5.实验总结 24
6.参照文献 24
1.设计目
依照设计任务,用自己熟悉计算机语言编制程序,在机器上调试运营,并通过上机考核。编写一程序,可以创立若干个虚拟进程,并对若干个虚拟进程进行调度,调度方略为时间片轮转。
虚拟程序描述:
虚拟指令格式: 操作命令 操作时间
其中,操作命令有如下几种:
² C :表达在CPU上计算
² I :表达输入
² O:表达输出
² W:表达等待
² H:表达进程结束
操作时间代表该操作命令要执行多长时间
假设I/O设备数量没有限制
I、O、W三条指令事实上是不占用CPU,执行这三条指令就应将进程放入相应等待队列(Input等待队列、Output等待队列、Wait等待队列)
例有一虚拟程序p1.prc描述如下:
c 30 o 12 c 9 i 14 h 0
该虚拟程序表达含义是:先在CPU上计算30秒,再在输出设备上输出12秒,计算9 秒,在输入设备上输入14秒,程序结束。
2.设计思路
进程调度是操作系统中重要功能,用来创立进程、撤除进程、实现进程状态转换,它提供了在可运营进程之间复用CPU办法。在进程管理中,进程调度是核心,由于在采用多道程序设计系统中,往往有若干个进程同步处在就绪状态,当就绪进程个数不不大于解决器数目时,就必要依照某种方略决定哪些进程优先占用解决器。本程序用时间片轮转调度算法对各种进程进行调度,每个进程有三个状态就绪、运营和完毕,初始状态为就绪状态。
时间片轮转调度算法中,系统将所有就绪进程按先来先服务算法原则,排成一种队列,每次调度时,系统把解决机分派给队列首进程,并让其执行一种时间片。当执行时间片用完时,由一种计时器发出时钟中断祈求,调度程序依照这个祈求停止该进程运营,将它送到就绪队列末尾,再把解决机分给就绪队列中新队列首进程,同步让它也执行一种时间片。
(1)建立一种进程控制块。PCB来代表。PCB涉及:进程名、链接指针、到达时间、预计运营时间、剩余时间和进程状态。进程状态分为就绪(W)、运营(R)和完毕(F)。
(2)为每个进程任意拟定一种规定运营时间和到达时间。
(3)按照进程到达先后顺序排成一种循环队列。再设一种对首指针指向第一种到达进程首址。
(4)执行解决机调度时,开始选取对首第一种进程运营。此外再设一种当前运营进程指针,指向当前正运营进程。
(5)执行:a)预测运营时间减1;b)输出当前运营进程名字。
(6)进程执行一次后,若该进程剩余运营时间为零,则将该进程状态置为完毕态F,并退出循环队列;若不为空,则将其移至队尾。继续在运营队首进程。
(7)若就绪队列不空,则重复上述(5)和(6)环节直到所有进程都运营完为止。在所设计调度程序中,规定包括显示或打印语句。以便显示或打印每次选操作系统课程设计中进程名称及运营一次后队列变化状况。
3.设计过程
3.1流程图
3.2算法
如果就绪队列中有n个进程,且时间片为q,则每个进程会得到CPU时间,每个长度不超过q时间单元。每个进程必要等待CPU时间不会超过(n-1)q个时间单元,直到它下一种时间片为止
void Run (){
int i,flag=0,time=10,pcbnum,Index=0,exenum,num,quenum;
char cmd;
int j,m,n;
int total=0;
JobEnQueueInit( &total );
save();
while( total!=0 ){
if( !EmptyQueue( Queue[1]) ){
outqueue(&Queue[1],&pcbnum);
insertqueue(&Queue[0],pcbnum);
}
else pcbnum=GetHead(Queue[0]);
delay();
jobpcb[ pcbnum].status='e';
printf(" \n\t\t作业 %d \n",pcbnum+1);
printf(" \t\t\t所处状态:%c \t执行了 %d 秒\n",jobpcb[ pcbnum].status,time);
for(i=0;i<3;i++){
if(jobpcb[i].id>=0){
//所有作业除在就绪队列获执行结束外等待时间 都减去时间片
if( jobpcb[i].status!='r'&&jobpcb[i].status!='h') jobpcb[i].wtime=jobpcb[i].wtime-time;
if(jobpcb[i].wtime<=0){ //查找所有队列 所在位置
for(j=0;j<5;j++){
for(m=Queue[j].head;m<Queue[j].tail;m++){
if(Queue[j].pcbnum[m]==i) {flag=1;break; }
}
if(flag==1) break;
}
if(flag==1){ //删除该指令
for(n=m;n<Queue[j].tail;n++) Queue[j].pcbnum[n]=Queue[j].pcbnum[n+1];
Queue[j].tail--;
jobpcb[i].exetoIndex++;
Index=jobpcb[i].exetoIndex;
JobEnQueue( i,Index,&total );
}
}
}
}
if(!EmptyQueue( Queue[1]) ){
outqueue(&Queue[0],&pcbnum);
if(jobpcb[pcbnum].wtime>0){
insertqueue(&Queue[1],pcbnum);
jobpcb[pcbnum].status='r';
}
}
printf(" \n\n\t\t 尚有\t %d 个作业没有完毕 \n",total );
save();
}
}
3.3数据构造
void delay()
int change(char *m)
int AllocPCB()
int AllocJob()
void displayIndex()
int CreatePcbLine()
void initqueue(struct Qnode *l)
void insertqueue(struct Qnode *l,int pcbnum)
int EmptyQueue( struct Qnode l)
void outqueue(struct Qnode *l,int *pcbnum)
void display()
void JobEnQueueInit( int * total)
void save ()
void JobEnQueue( int pcbnum,int Index ,int *total)
int GetHead(struct Qnode l)
void Run ()
void InitFile()
3.4源代码
//进程调度模仿程序,以时间片轮转调度算法为核心
#define NULL 0
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
FILE *GroupFile[10];
//定义一种pcb构造体
typedef struct index{
char name; //指令
int time; //指令执行时间
}index;
struct pcb {
char filename[10]; //进程名
int id; //作业编号
int exetoIndex; //当前正在执行指令
char status; //当前状态
int wtime; //等待时间
};
struct pcb jobpcb[100]; //pcb表
typedef struct job{
index idx[100]; //指令集
int pcbnum; //pcb编号 相应
}job;
job jobtab[100]; //作业表
char jobp[3][50]; //作业
//队列构造体
struct Qnode
{
int pcbnum[100]; //pcb编号
int head,tail;
};
struct Qnode Queue[5]; //5个队列 0E 1R 2I 3O 4W
void initqueue(struct Qnode *l);
//延迟
void delay( ){
time_t begin,end;
time(&begin);
do {
time(&end);
} while((end-begin)<=1);
}
//字符转化为数值
int change(char *m){
int i,j=0;
int len=strlen(m);
for(i=0;i<len;i++)
j=j*10+m[i]-'0';
return j;
}
//申请 pcb进程块
int AllocPCB(){
int i;
for(i=0;i<3;i++)
if(jobpcb[i].id ==-1) break;
if(i<3)
return i;
return -1;
}
//申请job
int AllocJob(){
int i;
for(i=0;i<3;i++)
if(jobtab[i].pcbnum == -1) break;
if(i<3)
return i;
return -1;
}
//显示指令
void displayIndex(){
int i,j;
for(i=0;i<3;i++){
printf(" Job % d \n",i+1);
for(j=0;j<10;j++)
printf(" %d %c % d \n",j+1,jobtab[i].idx[j].name,jobtab[i].idx[j].time);
}
}
//创立进程程序
int CreatePcbLine(){
char line[10];
int i,ll,jnum,pnum, ln=0, bpos,pos=0;
char buff[50];
char name [20];
char ch;
for(i=0;i<3;i++){
ln=0;
jnum=AllocJob();
if(jnum == -1) return 0;
pnum=AllocPCB();
if(pnum == -1) return 0;
jobtab[jnum].pcbnum=pnum;
strcpy(jobpcb[pnum].filename," ");
jobpcb[pnum].status='r';
jobpcb[pnum].exetoIndex=0;
jobpcb[pnum].id=jnum;
jobpcb[pnum].wtime=0;
int len=strlen(jobp[i]);
pos=0;
while(pos<len){
while(jobp[i][pos]==' ') pos++;
jobtab[jnum].idx[ln].name=jobp[i][pos++];///
while(jobp[i][pos]==' ') pos++;
bpos=0;
while(jobp[i][pos]!=' ')
buff[bpos++]=jobp[i][pos++];
buff[bpos]='\0';
jobtab[jnum].idx[ln].time=change(buff);/////
if(pos<len) {pos++;ln++;
}
}
}
displayIndex();
}
//初始化队列
void initqueue(struct Qnode *l){
l->head=0;
l->tail=0;
}
//插进入队列/
void insertqueue(struct Qnode *l,int pcbnum){
l->pcbnum[l->tail++]=pcbnum;
}
//队列与否为空
int EmptyQueue( struct Qnode l){
if(l.head==l.tail) return 1;
return 0;
}
//删除队列
void outqueue(struct Qnode *l,int *pcbnum)
{
if (l->head>=l->tail ) *pcbnum=-1;
else
*pcbnum=l->pcbnum[l->head++];
}
//显示作业
void display(){
int i,j;
for(i=0;i<5;i++){
printf(" 队列 %d ",i);
for(j=Queue[i].head;j<Queue[i].tail;j++)
printf("pcb 编号 %d \n\n ",Queue[i].pcbnum[j]);
}
}
//作业入队列
void JobEnQueueInit( int * total){
int i,num ,Index=0;
char cmd;
for( i=0;i<3;i++)
if(jobpcb[i].id>=0){
cmd=jobtab[ jobpcb[i].id ].idx[ Index ].name;
switch(cmd){
case 'c': insertqueue(& Queue[1],i); jobpcb[i].status='r';break;
case 'i': insertqueue(& Queue[2],i);jobpcb[i].status='i';break;
case 'o': insertqueue(& Queue[3],i);jobpcb[i].status='o';break;
case 'w': insertqueue(& Queue[4],i);jobpcb[i].status='w';break;
case 'h':jobpcb[i].status='h';num=jobpcb[i].id;jobtab[num].pcbnum=-1;jobpcb[i].id=-1;
}
if(cmd== 'h') {jobpcb[i].wtime=0; total--;}
jobpcb[i].wtime=jobtab [ jobpcb[i].id ].idx[Index].time;
(*total)++;
}
}
//保存成果
void save (){
FILE *fp;
int i;
fp=fopen("pcbtable.txt","a");
fprintf(fp," 文献名 作业编号 执行到指令数 所处状态 等待时间 \n" );
for(i=0;i<3;i++)
fprintf(fp," \t %s \t %d \t %d \t %c \t %d \n" ,
jobpcb[i].filename,jobpcb[i].id,jobpcb[i].exetoIndex,
jobpcb[i].status,jobpcb[i].wtime );
fclose(fp);
}
//作业入队列
void JobEnQueue( int pcbnum,int Index ,int *total){
int num;
char cmd;
if(jobpcb[pcbnum].id>=0){
cmd=jobtab[ jobpcb[pcbnum].id ].idx[ Index ].name;
switch(cmd){
case 'c': insertqueue(&Queue[1],pcbnum); jobpcb[pcbnum].status='r';break;
case 'i': insertqueue(& Queue[2],pcbnum);jobpcb[pcbnum].status='i';break;
case 'o': insertqueue(& Queue[3],pcbnum);jobpcb[pcbnum].status='o';break;
case 'w': insertqueue(& Queue[4],pcbnum);jobpcb[pcbnum].status='w';break;
case 'h': jobpcb[pcbnum].status='h';num=jobpcb[pcbnum].id;jobtab[num].pcbnum=-1;jobpcb[pcbnum].id=-1;
}
if(cmd== 'h') {
jobpcb[pcbnum].wtime=0;
printf(" \n\t\t作业 %d 完毕\n",pcbnum+1,jobpcb[ pcbnum].status);
(*total)--;
}
else jobpcb[pcbnum].wtime=jobtab [ jobpcb[pcbnum].id ].idx[Index].time;
printf(" \n\t\t作业 %d \n ",pcbnum+1);
printf("\t\t\t\t所处状态 : %c \n",jobpcb[ pcbnum].status);
printf("\t\t还需要时间 %d 秒\n",jobpcb[ pcbnum].wtime);
}
}
//得到队列首元素
int GetHead(struct Qnode l){
return l.pcbnum[l.head];
}
//执行
void Run (){
int i,flag=0,time=10,pcbnum,Index=0,exenum,num,quenum;
char cmd;
int j,m,n;
int total=0;
JobEnQueueInit( &total );
save();
while( total!=0 ){
if( !EmptyQueue( Queue[1]) ){
outqueue(&Queue[1],&pcbnum);
insertqueue(&Queue[0],pcbnum);
}
else pcbnum=GetHead(Queue[0]);
delay();
jobpcb[ pcbnum].status='e';
printf(" \n\t\t作业 %d \n",pcbnum+1);
printf(" \t\t\t所处状态:%c \t执行了 %d 秒\n",jobpcb[ pcbnum].status,time);
for(i=0;i<3;i++){
if(jobpcb[i].id>=0){
//所有作业除在就绪队列获执行结束外等待时间 都减去时间片
if( jobpcb[i].status!='r'&&jobpcb[i].status!='h') jobpcb[i].wtime=jobpcb[i].wtime-time;
if(jobpcb[i].wtime<=0){ //查找所有队列 所在位置
for(j=0;j<5;j++){
for(m=Queue[j].head;m<Queue[j].tail;m++){
if(Queue[j].pcbnum[m]==i) {flag=1;break; }
}
if(flag==1) break;
}
if(flag==1){ //删除该指令
for(n=m;n<Queue[j].tail;n++) Queue[j].pcbnum[n]=Queue[j].pcbnum[n+1];
Queue[j].tail--;
jobpcb[i].exetoIndex++;
Index=jobpcb[i].exetoIndex;
JobEnQueue( i,Index,&total );
}
}
}
}
if(!EmptyQueue( Queue[1]) ){
outqueue(&Queue[0],&pcbnum);
if(jobpcb[pcbnum].wtime>0){
insertqueue(&Queue[1],pcbnum);
jobpcb[pcbnum].status='r';
}
}
printf(" \n\n\t\t 尚有\t %d 个作业没有完毕 \n",total );
save();
}
}
//初始化
void InitFile(){
int i;
GroupFile[0]=fopen("p1.prc","r");
GroupFile[1]=fopen("p2.prc","r");
GroupFile[2]=fopen("p3.prc","r");
fgets(jobp[0],255,GroupFile[0]);
fgets(jobp[1],255,GroupFile[1]);
fgets(jobp[2],255,GroupFile[2]);
for(i=0;i<100;i++){
jobpcb[i].exetoIndex=0;
strcpy(jobpcb[i].filename," nothing");
jobpcb[i].id=-1;
jobpcb[i].status='r';
jobpcb[i].wtime=0;
}
for(i=0;i<100;i++)
jobtab[i].pcbnum=-1;
for(i=0;i<5;i++)
initqueue(&Queue[i]);
}
int main(){
char start;
printf("欢迎界面");
start=getch();
if(start!=NULL){
InitFile();
CreatePcbLine();
Run ();
}
return 0;
}
4.实验成果及分析
4.1 使用阐明
先用文本编辑器写三个虚拟程序保存在改程序目录下,可以分别命名为p1.prc p2.prc p3.prc。然后编一进程调度程序,将这三个虚拟程序创立成进程,并按各虚拟进程指令规定执行和调度。用一种文本文献, 里面只能放一种整数,表达一种时间因子,用于调节设计程序进程调度.EXE执行速度。
请在该程序目录下建立三个进程文献:
p1.prc p2.prc p3.prc
文献内容格式为:
操作命令 操作时间
c指令:CPU上计算
i指令:输入
o指令:输出
w指令:等待
h指令:结束。
4.2程序演示
图1 程序与进程文献
图2 程序初始界面
图3 程序运营状态
图4 程序运营状态
图5 运营结束
图6 程序运营成果
5.实验总结
本次课程设计虽然碰见许多困难,刚开始接触到课题感觉到无从下手,日后通过逐渐思考,认真研究逐渐建立了整个宏观流程,然后就是一段时间埋头苦干,狂敲代码,最后都解决了。在设计过程中碰见问题而提出问题并且寻找解决办法过程中颇是受益。通过征询有更多经验人和在网上、书籍上查找相应资料,最后在规定收件内完毕本次课程设计。
但是,细观测设计内容可以发现许多问题,一下是我个人以为局限性之处:设计过程中,存在许多不完整性控制,整个设计流程简朴,但是却没有阵中使用进程机制。通过这次课程设计,咱们对程序设计有了基本结识,对计算机操作系统进程机制也有了更进一步理解,并且在设计过程中学习团队合伙精神和提高个人解决问题能力均有了相应见识。相信在这次设计能为此后开发设计做一种较好铺垫。
固然,我成功也离不开人们协助。因此,在此我要感谢给于过我协助指引教师以及热心同窗们。
6.参照文献
[1] 龚沛曾等编.C/C++程序设计教程.北京:高等教诲出版社,.
[2] [美]Prata S.著. C Primer Plus(第5版 中文版).北京:人民邮电出版社,.
[3] 汤子瀛等编著. 计算机操作系统.西安:
展开阅读全文