目录
1、课程设计目的…………………………………………………3
2、课程设计要求…………………………………………………3
3、相关知识………………………………………………………3
4、需求分析………………………………………………………4
5、概要设计………………………………………………………5
6、详细设计………………………………………………………6
7、测试,修改及运行结果………………………………………13
8、参考文献………………………………………………………15
9、结束语…………………………………………………………15
10、附件…………………………………………………………15
1、 课程设计的目的
理解操作系统进程管理中进行进程调度的过程和编程方法,掌握先来先服务调度算法和最高优先数优先的调度算法,创建进程控制块PCB。理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况
2、 课程设计要求
编写一个进程调度程序,允许多个进程共行的进程调度程序
1).进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。
2).每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等.
3).进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为输入进程的时间。
4).进程的运行时间以时间片为单位进行计算。
5).每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。.
6).就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
7).如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
8).每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止
3、 相关知识
进程:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动
进程的状态:
运行状态:进程正在处理器上运行
就绪状态:一个进程获得了除处理器外的一切所需资源,一旦得到处理器即可运行
等待状态:一个进程正在等待某一事件发生而暂时停止运行
先进先出调度算法:其基本原则是按照作业到达系统或进程进入就绪对列的先后次序来选择。对于进程调度来说,一旦一个进程占有了处理器,它就一直运行下去,直到该进程完成其工作或者因等待事件而不能继续运行时才释放出处理器。
优先级调度算法:按照进程的优先级大小来调度。使高优先级进程或线程得到优先的处理的调度策略称为优先级调度算法。进程的优先级可以由系统自动地按一定原则赋给它,也可由系统外部来进行安排
但在许多采用优先级调度的系统中,通常采用动态优先数策略。即一个进程的优先级不是固定的,往往是随许多因素的变化而变化。尤其随作业(进程)的等待时间,已使用的处理器时间或其他系统资源的使用情况而定,以防止低优先级进程或线程长期饥饿现象发生
时间片轮转算法:时间片轮转算法主要用于处理器调度。采用此算法的系统,其进程就绪队列往往按进程到达的时间来排序。进程调度程序总是选择就绪队列中的第一个进程,也就是说按照先进先出原则调度,但一旦进程占有处理器仅使用一个时间片,在使用完一个时间片后,进程还没有完成其运行,它也必须释放出(被抢占)处理器给下一个就绪的进程。而被抢占的进程返回到就绪队列的末尾重新排队等候再次运行。
4、 需求分析
进程调度程序选择一个就绪状态的进程,使之在处理器上运行,每个进程的状态信息用数据结构(进程控制块PCB)表示,进程的调度采用最高优先数优先的调度算法和先来先服务调度算法相结合的算法,并且采用动态优先数策略,选择进程占用处理器后该进程仅能使用一个时间片,运行完后优先数减1
5、 概要设计
进程控制块:描述进程的状态信息,用结构体定义
typedef struct process
{ char name[10]; //进程名
int priority; //优先数
Time ReachTime; //到达时间
Time NeedTime; //需要运行时间
Time UsedTime; //已用时间
char state; //进程状态
}PCB; //进程控制块
图1.进程调度模拟程序模块图
算法思想:
定义结构体PCB描述进程的进程控制块,定义数组PCB pcb[Max]存放进程
进程调度程序调用face()函数选择所要进行的操作。输入1则增加进程并调度进程,输入2则打印进程,输入0则任务结束
增加进程,调用AddProcess()函数,将输入的进程存放在数组pcb[Max]中
打印进程,调用print()函数,在该函数中首先调用sort()函数对进程按优先级和先来先服务排序,然后显示输出排序后的进程
进程调度,调用attemper()函数,调度优先级最高的进程分配给CPU使之运行一个时间片
进程优先级排序,调用sort()函数,按照先来先服务和优先级排序,使排序完最优先运行的进程存放在pcb[0]中。
6、 详细设计
图2.程序设计流程图
图3.sort( )函数流程图
sort( )函数:函数用冒泡法排序,首先按到达时间排序,使到达时间最早(即pcb[n].ReachTime最小)的进程被交换到pcb[0]中,再按优先级排序,使具有最高优先级(即pcb[n].priority最大)的进程被交换到pcb[0]中。相同优先级的进程只按到达时间排序
主要代码如下:for (i=0;i<n-1;i++) //先按到达时间排序
{ for (j=n-2;j>=i;j--)
{ if (pcb[j+1].ReachTime<pcb[j].ReachTime)
{
temp=pcb[j];
pcb[j]=pcb[j+1];
pcb[j+1]=temp;
}
}
}
for (i=0;i<n-1;i++) //再按优先级进行排序
{ for (j=n-2;j>=i;j--)
{ if (pcb[j+1].priority>pcb[j].priority)
{ temp=pcb[j];
pcb[j]=pcb[j+1];
pcb[j+1]=temp;
}
}
图4.print( )函数
图5. AddProcess()函数
print( )函数: 打印函数,先调用sort()排序函数对进程进行排序,排序完再打印输出进程
主要代码如下: sort();
printf("\n 进程名 优先级 到达时间 需要时间 已用时间 进程状态 \n");
for (i=0;i<n;i++)
{printf("%8s%8d%8d%10d%10d%10c\n",pcb[i].name,pcb[i].priority,pcb[i].ReachTime,pcb[i].NeedTime,pcb[i].UsedTime,pcb[i].state);
}
AddProcess()函数:增加进程函数,输入要添加的进程的进程控制块的信息,并依次存放在数组PCB pcb[Max]中,每加入一个进程后判断是否还要继续增加进程,若是则继续循环的执行操作
主要代码如下: do{
printf("\n请输入进程名");
scanf("%s",pcb[n].name);
printf("请输入进程的优先级");
scanf("%d",&pcb[n].priority);
printf("请输入进程需要的时间");
scanf("%d",&pcb[n].NeedTime);
pcb[n].ReachTime=n;
pcb[n].UsedTime=0;
pcb[n].state='W';
n++;
printf("还要继续增加进程吗,是(Y),否(N)");
do
{
ch=getchar();
} while(ch!='Y'&&ch!='N'&&ch!='y'&&ch!='n');
}while (ch=='Y'||ch=='y');
图6.attemper( )函数
attemper( )函数:进程调度函数,调度排完序后存放在pcb[0]中的进程,分配给该进程CPU,使之运行一个时间片,然后比较进程的剩余时间(pcb[0].NeedTime-pcb[0].UsedTime)是否小于时间片的大小pTime,若是,则该进程调度完成,进程处于完成状态,若非,则已用时间加上一个时间片,进程处于就绪状态继续等待运行,然后调用print( )函数打印输出当前进程的状态并排序,直至所有进程处于完成状态后结束运行
主要代码如下: do{
if ((pcb[0].NeedTime-pcb[0].UsedTime)>pTime)
{ pcb[0].UsedTime+=pTime;//已用时间加时间片
pcb[0].priority--;//优先级减一
pcb[0].state='W';
}
else
{ pcb[0].UsedTime=pcb[0].NeedTime;
//已用时间等于需要时间
pcb[0].priority=-1000;//优先级置为零
pcb[0].state='F';//完成进程,将状态置为完成
}
print();
}while(pcb[0].state!='F');
图7.face( )函数
face( )函数:函数打印所能进行的操作以供选择。输入1则是增加进程后调度进程,输入2则是打印进程,输入0则是任务结束。
主要代码如下:char choose;
printf("\n增加进程并调度进程,请按1");
printf("\n打印进程,请按2");
printf("\n任务结束, 请按0");
printf("\n请选择:");
do{
choose=getchar();
} while(choose!='1'&&choose!='2'&&choose!='0');
return choose;
}
图8.main( )函数
main( )函数:首先设置时间片的大小pTime,然后调用face()函数选择要进行的操作,choose='1'则增加进程并调度,choose='2'则打印进程,choose='0'则任务结束。
主要代码如下:char choose;
n=0; //初始化进程数为0
printf("设置时间片的大小:");
scanf("%d",&pTime);
choose=face();
do
{ if (choose=='1')
{ AddProcess();
print();
attemper();
}
if (choose=='2')
{ print();
}
if (choose=='0')
{ return;
}
choose=face();
} while(1);
函数间的关系:1)sort( )函数嵌套在print()函数中调用
2)调用AddProcess()函数前必须先调用print()函数对进程进行排序并打印
7、 测试,修改及运行结果
测试过程如上所述,分析得知,进程的调度正确
8、 参考文献
操作系统基础(第三版)…屠祁 屠立德等编著…清华大学出版社2000.9
Helen Custer著.Windows NT技术内幕 程渝荣译 北京:清华大学出版社,1993
Andrew S.Tanenbaum,Albert S.Woodhull.操作系统设计及实现(第二版) 北京:清华大学出版社,1998
9、 结束语
通过这次课设加深了我对操作系统的认识,进一步了解了进程调度的过程,在老师的指导下,对进程模拟程序做了进一步的改进,并且学会了怎么分析问题和解决问题
10、 附件
程序清单
#include <stdio.h>
#define Time int
#define Max 100
typedef struct process
{
char name[10]; //进程名
int priority; //优先数
Time ReachTime; //到达时间
Time NeedTime; //需要运行时间
Time UsedTime; //已用时间
char state; //进程状态
}PCB; //进程控制块
int n; //标示进程的总数
PCB pcb[Max];
int pTime; //时间片大小
void AddProcess()
{
char ch;
do {
printf("\n请输入进程名");
scanf("%s",pcb[n].name);
printf("请输入进程的优先级");
scanf("%d",&pcb[n].priority);
printf("请输入进程需要的时间");
scanf("%d",&pcb[n].NeedTime);
pcb[n].ReachTime=n;
pcb[n].UsedTime=0;
pcb[n].state='W';
n++;
printf("还要继续增加进程吗,是(Y),否(N)");
do
{
ch=getchar();
} while(ch!='Y'&&ch!='N'&&ch!='y'&&ch!='n');
}while (ch=='Y'||ch=='y');
}
// 排序函数,将最先运行的进程放在最先即pcb[0]
void sort()
{ //用冒泡排序
int i,j;
PCB temp;
//先按到达时间排序
for (i=0;i<n-1;i++)
{
for (j=n-2;j>=i;j--)
{
if (pcb[j+1].ReachTime<pcb[j].ReachTime)
{
temp=pcb[j];
pcb[j]=pcb[j+1];
pcb[j+1]=temp;
}
}
}
//再按优先级进行排序
for (i=0;i<n-1;i++)
{
for (j=n-2;j>=i;j--)
{
if (pcb[j+1].priority>pcb[j].priority)
{
temp=pcb[j];
pcb[j]=pcb[j+1];
pcb[j+1]=temp;
}
}
}
if (pcb[0].state!='F')
{
pcb[0].state='R'; //将优先级最高的状态置为运行
}
}
void print() //打印
{
int i;
sort();
printf("\n 进程名 优先级 到达时间 需要时间 已用时间 进程状态 \n");
for (i=0;i<n;i++) { printf("%8s%8d%8d%10d%10d%10c\n",pcb[i].name,pcb[i].priority ,pcb[i].ReachTime,pcb[i].NeedTime,pcb[i].UsedTime,pcb[i].sta te);
}
}
void attemper() //调度
{
do{
if ((pcb[0].NeedTime-pcb[0].UsedTime)>pTime)
{
pcb[0].UsedTime+=pTime; //已用时间加时间片
pcb[0].priority--; //优先级减一
pcb[0].state='W';
}
else
{
pcb[0].UsedTime=pcb[0].NeedTime;//已用时间等于需要时间
pcb[0].priority=-1000; //优先级置为零
pcb[0].state='F'; //完成进程,将状态置为完成
}
print();
}while(pcb[0].state!='F');
}
char face()
{
char choose;
printf("\n增加进程并调度进程,请按1");
printf("\n打印进程,请按2");
printf("\n任务结束, 请按0");
printf("\n请选择:");
do{
choose=getchar();
} while(choose!='1'&&choose!='2'&&choose!='0');
return choose;
}
void main()
{
char choose;
n=0; //初始化进程数为0
printf("设置时间片的大小:");
scanf("%d",&pTime);
choose=face();
do
{
if (choose=='1')
{
AddProcess();
print();
attemper();
}
if (choose=='2')
{
print();
}
if (choose=='0')
{
return;
}
choose=face();
} while(1);
}
操作系统实验题设计一若干并发进程的进程调度程序一实验目的无论是批处理系统分时系统还是实时系统用户进程数一般都大于处理机数这将导致用…
实验一进程调度实验专业XXXXX学号XXXXX姓名XXX实验日期20XX年XX月XX日一实验目的通过对进程调度算法的模拟加深对进程…
实验二进程调度实验内容进程调度模拟实验实验目的通过模拟进程调度算法了解进程调度的过程并比较不同的调度算法的区别实验题目设计一段程序…
目录1课程设计目的32课程设计要求33相关知识34需求分析45概要设计56详细设计67测试修改及运行结果138参考文献159结束语…
计算机操作系统课程实验报告题目实验一进程调度计算机学院计算机科学与技术学院专业姓班学名级号20xx年10月21日1实验一进程调度1…
沈阳理工大学课程设计任务书1沈阳理工大学目录1课程设计目的32课程设计要求33相关知识34需求分析45概要设计56详细设计67测试…
实验二进程管理一进程的创建实验思考题1系统是怎样创建进程的解linux系统创建进程都是用fork系统调用创建子进程2当首次调用新创…
实验二进程管理二进程的控制实验思考题1可执行文件加载时进行了哪些处理解可执行文件加载时首先是创建一个新进程的fork系统调用然后用…
XXXX大学20xx年20xx年第2学期院系计算机信息工程学院专业信息管理与信息系统课程名称操作系统原理及应用班级姓名学号指导教师…
实验一进程管理一目的进程调度是处理机管理的核心内容本实验要求编写和调试一个简单的进程调度程序通过本实验加深理解有关进程控制块进程队…
操作系统实验题设计一若干并发进程的进程调度程序一实验目的无论是批处理系统分时系统还是实时系统用户进程数一般都大于处理机数这将导致用…