青岛理工大学
操作系统课程设计报告
院(系): 计算机工程学院 专业: 计算机科学与技术专业 学生姓名:
班级:__ 学号:
题目: 短作业优先调度算法的进程调度程序_ 起迄日期: ___ _ ____
设计地点: 指 导 教 师:
2011—2012年度 第 1 学期
完成日期: 2012 年 1 月 日
一、 课程设计目的
进行操作系统课程设计主要是在学习操作系统课程的基础上,在完成操作系统各部分实
验的基础上,对操作系统的整体进行一个模拟,通过实践加深对各个部分的管理功能的认识,还能进一步分析各个部分之间的联系,最后达到对完整系统的理解。同时,可以提高运用操作系统知识解决实际问题的能力;锻炼实际的编程能力、开发软件的能力;还能提高调查研究、查阅技术文献、资料以及编写软件设计文档的能力。
二、 课程设计内容与要求
设计目的:在多道程序和多任务系统中,系统内同时处于就绪状态的进程可能有若干个,且进程之间也存在着同步与互斥的关系,要求采用指定的调度策略,使系统中的进程有条不紊地工作,通过观察诸进程的运行过程,以巩固和加深处理机调度的概念。
2、设计要求(多道、单处理机):
1) 每一个进程有一个PCB ,其内容可以根据具体情况设定。
2) 可以在界面设定的互斥资源(包括两种:输入设备与输出设备)的数目
3) 进程数、进入内存时间、要求服务时间可以在界面上进行设定
4) 进程之间存在一定的同步与互斥关系,可以通过界面进行设定,其表示方法如下: 进程的服务时间由三段组成:I2C10O5(表示进程的服务时间由2个时间片的输入,
10个时间片的计算,5个时间片的输出)
进程间的同步关系用一个段表示:W2,表示该进程先要等待P2进程执行结束后才
可以运行
因此,进程间的同步与互斥关系、服务时间可以统一用四段表示为:I2C10O5W2
5) 可以在运行中显示各进程的状态:就绪、阻塞、执行
6) 采用可视化界面,可在进程调度过程中随时暂停调度,查看当前进程的状态以及相应的阻塞队列
7) 具有一定的数据容错性
三、 系统分析与设计
1、系统分析
本系统主要是采用短作业优先算法进程的进程调度过程。短作业优先调度算法,是指对短作业或短进程优先调度的算法。他们可以分别用于作业调度和进程调度,短作业优先的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将他们调入内存运行。而短进程优先调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给他,,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再度重新调度。本程序采用了非抢占式短作业优先调度。而非抢占式这种方式,一旦把处理机分配给某进程后,便让该进程一直执行,直至该进程完成或发生某事件而被阻塞时,才再把处理机分配给其它进程,决不允许某进程抢占已经分配出去的处理机。这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统环境。但它难以满足紧急任务的要求——立即执行,因而可能造成难以预料的后果。因此,在要求比较严格的实时系统中,不宜采用这种调度方式本系统的主要是在满足要求多道单处理机的情况下进行短作业的优先调度。
本系统在测试时输入了五个进程,按实验要求如I2C10O5(表示进程的服务时间由2个时间片的输入,10个时间片的计算,5个时间片的输出,5个时间片的计算组成)的方式输入,各进程的信息如下:(0 0 1 1 1 ) (1 2 1 2 2 )(2 4 1 1 1 )
(3 6 2 1 1 ) (4 8 1 0 1),其中括号内第一个数字代表进程标识,第二个数字
代表进程的到达时间,第三的字符串则代表的是服务时间,由此可得五个进程的服务时间分别为3,6,4,5,2。
进程进入内存,则按照优先级进行执行进程。主要是实现了进程执行过程的界面演示以
及在暂停演示时各进程此时的状态,主要包括三种状态——就绪、执行、阻塞。同时,在暂停执行时可以查看当前时间的阻塞队列。其中进程执行界面的演示过程中用到了坐标轴,x 轴代表时间,y 轴代表进程的标志(默认进程标志为0,1,2,3,4„„n-1,n 表示进程的个数,在计数过程中按进程的到达时间开始计数),用灰色表示一个时间片,每个进程的执行过程即可表示为时间片不断增加的过程。
下面是进程信息的输入界面,界面介绍如下:
需要录入的进程数:输入需要执行的进程的个数。
保存文件:输入数据后将自动保存进程信息,保存在txt 文件中,因此输入你要
保存的txt 文件的名子,或者在输入进程信息时直接输入已保存的txt 文件名
(不包括扩展名.txt )便可直接点击“录入完毕”按钮,进行后续操作。
输入设备数目:主要是输入输入设备的数目。
输出设备数目:主要是输入输出设备的数目。
进入内存的时间:表示进程的到达时间。
要求服务时间:进程的服务时间由四段组成:I2C10O5(表示进程的服务时间由2个时
间片的输入,10个时间片的计算,5个时间片的输出),按此格式输入信息,
如若没有其中一步如没有计算这一步表示有0个时间片的计算,服务时间可
以表示为I2C105 。以此格式输入进程的服务时间。
“录入第1个数据“按钮:当你输入完毕第一个数据时,点击此按钮,进入第二个进程数
据信息的录入。
“录入完毕进行演示“按钮:当你将所有进程的信息输入完毕后点击此按钮。进入演示界面
进行演示。
“退出“按钮:在执行此界面的任何时刻均可点击此按钮,退出此界面。
录入完毕点击按钮“录入完毕进行执行”后便会弹出进程的执行演示界面如下:
右上角带颜色的三个矩形分别表示进程的执行状态,蓝色矩形代表进程正在执行,绿色矩形代表进程已经执行完成,红色矩形则代表进程受到阻塞。
“开始演示“按钮:点击此按钮则开始演示进程的执行过程。
“暂停演示“按钮:点击此按钮则暂停进程的演示过程。
“重新开始“按钮:点击此按钮则重新演示进程的执行过程。
“退出界面“按钮:点击此按钮则退出演示界面。
“查看阻塞队列”按钮:在点击“暂停演示”按钮之后,点击此按钮,可查看此时的阻塞队
列。
1、 系统设计
本调度算法在设计的时候主要运用了四个类库。PCB 类库主要是包括了要运用到得
相关类有三个,Process 类主要是声明了进程的相关属性以及方法结构体,GetProcess
和SetProcess 类主要是对进程相关属性进行处理。Scheduling 类库主要是实现短作业
优先调度,同样包括三个类,BlockQueue 类主要是实现对阻塞队列的处理,Rank 类主
要是实现按进程的优先级进行排序实现进程的短作业优先调度,SJF 类主要是为了实现
进程执行演示的方便设计的一个类,它声明了一个数组,将每个时刻的进程作为数组元
素放入数据组中。Used 类库主要是对演示界面的处理,里面包括一个类Drawing, 这个
类主要是完成对演示界面所运用到得坐标轴的实现。 最后一个类库为短作业优先调度
演示程序,主要包含了AddFrom 和ShowFrom 两个类,这两个类主要是实现程序界面的
设计,以及相关控件事件的连接以及实现。
在本程序中主要运用的数据结构是数组,如Process[]数组主要使用了存放进来的
进程(存放顺序按进程的到达时间,为方便描述一下均简写为P[]),block[]数组用来
存放阻塞队列,exeQ[]是将进程按短作业优先级排序后的数组,okP[]数组则是某一时
刻到达的所有进程所形成的数组,以上数组均已进程作为数组元素。
短作业优先调度流程图如下:
短作业优先调度
阻塞队列的流程图如下:
进程调度演示流程图: 阻塞队列
进程调度演示
四、系统测试与调试分析
1、系统测试 本程序主要是采用功能测试,对程序进行的相关的测试与分析。共输入五个进程信息,输入设备和输出设备各输入一个然后分别输入各进程的到达时间和服务时间,分别如下:(0 1 1 1 ) (2 1 2 2 )(4 1 1 1 ) (6 2 1 1 1) (8 1 0 1)。再输入过程中,进程的个数、到达时间以及输入设备和输出设备的个数分别是整数,否则将提示输入错误。进程的服务时间必须严格按照要求来填写,否则将提示输入错误。
由此可得五个进程的执行顺序为:3,6,4,5,2。
2、 调试分析
在调试本程序时和演示过程中,出现了不少的错误。其中在编写短作业优先调度算法的代码中,用到了不少的for 循环以及for 循环的嵌套,在这部分出现了变量的混淆,大括号的缺失或多余,经过检查后改正。在编写短作业优先算法代码的时候,
出现了思路紊乱,算法思路不清晰,不能够完成短作业的优先,后经请教同学以及通过画相关流程图得到解决。还有由于对c#的运用并不熟练以及对c#的可视化界面的制作不太了解,使自己在做程序过程中遇到了很大的阻力,后经过翻看相关书籍以及请教同学,解决的这个问题。
本程序的演示界面做的很简陋,只是简单的实现了非抢占式的短作业优先调度,但是在本程序的功能中有一项实现输入设备和输出设备只是实现了设备数目的输入功能,但是没有实现设备之间的互斥问题。因此,本程序无论是在界面还是在功能上均有很大的缺点和不足之处,需要不断的改进和完善。
五、用户手册
1、程序的编写是在win7系统下的VS2010成的。
2、由于电脑系统里已经安装了vs2010此不需要再进行安装。
3、使用本程序界面的步骤。
(1)运行本程序会弹出界面如图5-1:
图5-1
(2)在以上弹出的界面上输入进程的数目以及保存的文件名和输入设备和输出设备的数目。 然后输入第一个进程的进入内存的时间和要求服务的时间。如图5-2:
图5-2
(3)点击“录入第1个数据”按钮,弹出以下窗口,开始输入第二个数据的进入内存的时间和要求服务的时间。如若输入的数据格式正确,则会弹出图5-3:
图5-3
点击确定按钮,进入下一个数据的输入图5-4:
图5-4
如此依次输入所有进程的相关信息,直到所有的进程信息都输入完毕。 如若输入数据不正确则会弹出窗口图5-5:
图5-5
点击确定重新输入正确的进程信息。
(4)当将所有的进程信息都输入完毕后,点击“录入完毕进行演示”按钮。 则会弹出演示界面图5-6:
图5-6
(5)点击开始演示按钮,进程开始执行。演示状态如图5-7:
图5-7
(6)点击暂停按钮,演示暂停,进程停止执行,此时可查看各进程的状态图5-8。
图5-8
(7)在暂停的情况下,点击“查看阻塞队列”按钮。则会弹出以下窗口,并显示此刻的阻塞队列。如图5-9:
图5-9
(8)如果想重新演示,可以点击“重新开始”按钮。当演示完毕后,可以点击“退出界面”按钮。退出演示界面。
六、程序清单
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace
QD.Mg.Winform.Process
public class Process {
static int num = 0;
private int privatePcb;//程序内部使用的PCB public int PrivatePcb {
get { return privatePcb; } set { privatePcb = value ; } }
private int enteringTime;//进入内存的时间 public int EnteringTime {
get { return enteringTime; } set { enteringTime = value ; } }
private double serviceTime;//要求服务的时间 public double ServiceTime {
get { return serviceTime; } set { serviceTime = value ; } }
public Process() {
privatePcb = num++; enteringTime = -1; serviceTime = -1; }
///
///
public override string ToString() {
return privatePcb + "|" + enteringTime + "|" + serviceTime ; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.IO;
namespace QD.Mg.Winform.Process
public class SetProcess {
private static bool save(string filePosition,string content) {
try {
StreamWriter sw = new StreamWriter (filePosition, true , System.Text. Encoding .Default); //在原有的基础上添加 sw.Write(content); sw.Close(); }
catch (IOException e) {
Console .WriteLine(e.Message); return false ; }
return true ; }
public static int setProcesses(string filePosition,Process p) {
//将Process 中的每个进程对象都拼接成一个string 字符串,存放到txt 文件中 string saveString = p.ToString();
saveString = saveString + "\r\n"; //在字符串的最后加上换行的标志 //调用save 函数,实现存储
save(filePosition, saveString); return 0; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.IO;
using System.Text.RegularExpressions;
namespace QD.Mg.Winform.Process {
public class GetProcess {
public static Process [] getProcesses(string filePosition) {
string content = read(filePosition);
string []childString = content.Split(new string []{"\r\n"},StringSplitOptions .RemoveEmptyEntries); //
Process [] process = new Process [childString.Length]; for (int i = 0; i
process[i] = new Process (); }
for (int i = 0; i
//将一个进程的转化成对应的类
string [] grandsonString = childString[i].Split('|'); //为各个变量赋值
process[i].PrivatePcb = Convert .ToInt32(grandsonString[0]); process[i].EnteringTime = Convert .ToInt32(grandsonString[1]); process[i].ServiceTime = Convert .ToInt32(grandsonString[2]); }
return process; }
private static string read(string filePosition) {
FileStream fs = new FileStream (filePosition, FileMode .Open, FileAccess .Read);
StreamReader sr = new StreamReader (fs, Encoding .Default); string content = sr.ReadToEnd(); sr.Close(); return content; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
namespace QD.Mg.Winform.Scheduling {
///
/// 阻塞队列的处理函数 ///
public class BlockQueue {
public static Process. Process [] getBlockQueue(int time, Process. Process [] process) {
#region 变量初始化
Process.Process [] block = new
QD.Mg.Winform.Process. Process [process.Length];//阻塞队列数组
Process.Process [] exeQ;//每个算法的执行顺序 Process.Process [] okP;//给定时间内到达的进程 int num = 0;//阻塞队列的下标 int okPNumber = 0;
int isFinish = -1;//完成的进程的最后一个的下标
int isFinishTotalServiceTime = 0;//完成进程的总的服务时间 #endregion
#region SJF 短作业优先调度算法 //首先获取得到执行的序列
exeQ = Rank .getRank(process); //符合条件的
okP = new QD.Mg.Winform.Process.Process [process.Length]; #region 获取得到 给定时间内到达的进程,进行阻塞队列的计算 for (int i = 0; i
if (exeQ[i] != null && exeQ[i].EnteringTime
okP[okPNumber++] = exeQ[i]; } }
#endregion
#region 获取已经执行完了的进程的标志 已经执行完了的总的服务时间 for (int i = 0; i
if (okP[i] != null ) {
isFinishTotalServiceTime = isFinishTotalServiceTime + Convert .ToInt32(okP[i].ServiceTime);
if (isFinishTotalServiceTime > time) {
isFinish = i - 1; break ; } } }
#endregion
#region 去除不符合条件的
for (int j = 0; j
okP[j] = null ;
}
#endregion
#region 将okP 中的非空值,按照在数组中的顺序,存入阻塞数组中 for (int i = 0; i
if (okP[i] != null ) {
block[num++] = okP[i]; } }
#endregion #endregion return block; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
namespace QD.Mg.Winform.Scheduling {
public class Rank {
public static Process.Process [] getRank(Process.Process [] process) {
//首先按照进入时间排序,然后根据服务时间对排序进行调整 #region 按照进入时间进行排序 Process.Process temp;
for (int i = 0; i
for (int j = i + 1; j
if (process[i].EnteringTime > process[j].EnteringTime) {
temp = process[i];
process[i] = process[j]; process[j] = temp; } } }
#endregion
for (int i = 0; i
{
//获取前面一段的要求服务总时间 int totalServiceTime = 0; for (int x = 0; x
totalServiceTime = totalServiceTime + Convert .ToInt32(process[x].ServiceTime); }
//找到要处理的进程数组,即在前一个进程处理时间内到达的进程 Process.Process [] front = new
QD.Mg.Winform.Process. Process [process.Length];//注意空值
for (int j = i + 1; j
if (Convert .ToInt32(process[j].EnteringTime)
{
front[j] = process[j]; } }
#region 将front 中的非空数据 Process.Process m;
for (int ii = 0; ii
for (int j = ii + 1; j
//
if (front[ii] != null && front[j] != null ) {
if (front[ii].ServiceTime > front[j].ServiceTime)//将作业大的排在后面,实现短作业优先 {
m = front[ii];
front[ii] = front[j]; front[j] = m; } } } }
//将front 中的非空数据,覆盖process 中的相应位置的数据 for (int a = 0; a
if (front[a] != null ) {
process[a] = front[a];
} } }
return process; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
namespace QD.Mg.Winform.Scheduling {
public class SJF {
public static int [] getExecuteQueue(Process.Process [] process) {
int totalServiceTime = 0;
for (int i = 0; i
totalServiceTime = totalServiceTime + Convert .ToInt32(process[i].ServiceTime); }
int [] executeQueue = new int [totalServiceTime]; int tips = 0;
Process.Process [] exequeue = Rank .getRank(process); for (int i = 0; i
for (int j = 0; j
executeQueue[tips++] = exequeue[i].PrivatePcb; } }
return executeQueue; } } }
七、体会与自我评价
短作业优先调度算法,是指对短作业或短进程优先调度的算法。他们可以分别用于作业调度和进程调度,短作业优先的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将他们调入内存运行。而短进程优先调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给他,,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再度重新调度。本程序采用了非抢占式短作业优先调度。而非抢占式
这种方式,一旦把处理机分配给某进程后,便让该进程一直执行,直至该进程完成或发生某事件而被阻塞时,才再把处理机分配给其它进程,决不允许某进程抢占已经分配出去的处理机。这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统环境。但它难以满足紧急任务的要求——立即执行,因而可能造成难以预料的后果。因此,在要求比较严格的实时系统中,不宜采用这种调度方式本系统的主要是在满足要求多道单处理机的情况下进行短作业的优先调度。
在做课程设计的过程中,我渐渐发现了自己的许多不足之处。比如,对短作业优先调度的原理了解不透彻,对课本知识掌握不熟练,以至在做的过程中需要不断的去翻阅资料和课本,大大降低了制作课设的效率。但正是这样,通过这次短作业优先调度课设,使我更加深刻的理解了短作业优先调度的过程以及工作原理,同时也加深了我对其他进程的理解及原理的掌握,让我对操作系统的知识有了新的认识和感悟,加深了我对课本知识的掌握和理解。同时让我认识到自己的不足之处,自己对课本知识的掌握不透彻,对许多知识点一知半解之后便作罢,缺乏刻苦钻研的认真而又耐心思考问题的习惯,在以后的学习中我会不断的努力,并努力改正这些缺点。 其次,由于自己在编写程序的过程中,遇到了不少的问题,体现了自己编程的生疏不熟练,在一些细节问题上会出现一些小错误,反映了自己对编程许多规则和细节问题上的生疏以及自己的粗心大意的问题,因此在以后的学习之中,应注重自己的动手编程能力,勤加练习,努力做到熟能生巧,同时注重培养自己独立思考问题的能力,在遇到问题面前能够认真努力的思考一番之后在进行处理而不是手忙脚乱的不知所措。这些对我以后的学习将会有很大的帮助,不仅能够让我认识到自己的缺点并督促我改正,同时还能够让我养成许多学习的好习惯,使自己能够跟好的学习和掌握专业知识。我相信,在以后的学习中,我一定会更加努力认真,掌握好专业知识,并提高动手能力和自我解决问题的能力,使自己变的更好。
八、参考文献
【1】汤子瀛 编著,计算机操作系统(修订版),西安电子科技大学出版社,2001年 【2】赵会东 王军等编著,C#项目开发案例全程实录(第二版),清华大学出版社,2011年
【3】 传智播客.net 就业精品培训录像 下载地址:http://download.chinaitlab.com 【4】《初学Visual C# 2010》 下载地址:http://download.chinaitlab.com 【5】《ASP.NET 程序开发范例宝典(C#)(第2版) 》 下载地址:
http://download.chinaitlab.com
九、课程设计评价
青岛理工大学
操作系统课程设计报告
院(系): 计算机工程学院 专业: 计算机科学与技术专业 学生姓名:
班级:__ 学号:
题目: 短作业优先调度算法的进程调度程序_ 起迄日期: ___ _ ____
设计地点: 指 导 教 师:
2011—2012年度 第 1 学期
完成日期: 2012 年 1 月 日
一、 课程设计目的
进行操作系统课程设计主要是在学习操作系统课程的基础上,在完成操作系统各部分实
验的基础上,对操作系统的整体进行一个模拟,通过实践加深对各个部分的管理功能的认识,还能进一步分析各个部分之间的联系,最后达到对完整系统的理解。同时,可以提高运用操作系统知识解决实际问题的能力;锻炼实际的编程能力、开发软件的能力;还能提高调查研究、查阅技术文献、资料以及编写软件设计文档的能力。
二、 课程设计内容与要求
设计目的:在多道程序和多任务系统中,系统内同时处于就绪状态的进程可能有若干个,且进程之间也存在着同步与互斥的关系,要求采用指定的调度策略,使系统中的进程有条不紊地工作,通过观察诸进程的运行过程,以巩固和加深处理机调度的概念。
2、设计要求(多道、单处理机):
1) 每一个进程有一个PCB ,其内容可以根据具体情况设定。
2) 可以在界面设定的互斥资源(包括两种:输入设备与输出设备)的数目
3) 进程数、进入内存时间、要求服务时间可以在界面上进行设定
4) 进程之间存在一定的同步与互斥关系,可以通过界面进行设定,其表示方法如下: 进程的服务时间由三段组成:I2C10O5(表示进程的服务时间由2个时间片的输入,
10个时间片的计算,5个时间片的输出)
进程间的同步关系用一个段表示:W2,表示该进程先要等待P2进程执行结束后才
可以运行
因此,进程间的同步与互斥关系、服务时间可以统一用四段表示为:I2C10O5W2
5) 可以在运行中显示各进程的状态:就绪、阻塞、执行
6) 采用可视化界面,可在进程调度过程中随时暂停调度,查看当前进程的状态以及相应的阻塞队列
7) 具有一定的数据容错性
三、 系统分析与设计
1、系统分析
本系统主要是采用短作业优先算法进程的进程调度过程。短作业优先调度算法,是指对短作业或短进程优先调度的算法。他们可以分别用于作业调度和进程调度,短作业优先的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将他们调入内存运行。而短进程优先调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给他,,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再度重新调度。本程序采用了非抢占式短作业优先调度。而非抢占式这种方式,一旦把处理机分配给某进程后,便让该进程一直执行,直至该进程完成或发生某事件而被阻塞时,才再把处理机分配给其它进程,决不允许某进程抢占已经分配出去的处理机。这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统环境。但它难以满足紧急任务的要求——立即执行,因而可能造成难以预料的后果。因此,在要求比较严格的实时系统中,不宜采用这种调度方式本系统的主要是在满足要求多道单处理机的情况下进行短作业的优先调度。
本系统在测试时输入了五个进程,按实验要求如I2C10O5(表示进程的服务时间由2个时间片的输入,10个时间片的计算,5个时间片的输出,5个时间片的计算组成)的方式输入,各进程的信息如下:(0 0 1 1 1 ) (1 2 1 2 2 )(2 4 1 1 1 )
(3 6 2 1 1 ) (4 8 1 0 1),其中括号内第一个数字代表进程标识,第二个数字
代表进程的到达时间,第三的字符串则代表的是服务时间,由此可得五个进程的服务时间分别为3,6,4,5,2。
进程进入内存,则按照优先级进行执行进程。主要是实现了进程执行过程的界面演示以
及在暂停演示时各进程此时的状态,主要包括三种状态——就绪、执行、阻塞。同时,在暂停执行时可以查看当前时间的阻塞队列。其中进程执行界面的演示过程中用到了坐标轴,x 轴代表时间,y 轴代表进程的标志(默认进程标志为0,1,2,3,4„„n-1,n 表示进程的个数,在计数过程中按进程的到达时间开始计数),用灰色表示一个时间片,每个进程的执行过程即可表示为时间片不断增加的过程。
下面是进程信息的输入界面,界面介绍如下:
需要录入的进程数:输入需要执行的进程的个数。
保存文件:输入数据后将自动保存进程信息,保存在txt 文件中,因此输入你要
保存的txt 文件的名子,或者在输入进程信息时直接输入已保存的txt 文件名
(不包括扩展名.txt )便可直接点击“录入完毕”按钮,进行后续操作。
输入设备数目:主要是输入输入设备的数目。
输出设备数目:主要是输入输出设备的数目。
进入内存的时间:表示进程的到达时间。
要求服务时间:进程的服务时间由四段组成:I2C10O5(表示进程的服务时间由2个时
间片的输入,10个时间片的计算,5个时间片的输出),按此格式输入信息,
如若没有其中一步如没有计算这一步表示有0个时间片的计算,服务时间可
以表示为I2C105 。以此格式输入进程的服务时间。
“录入第1个数据“按钮:当你输入完毕第一个数据时,点击此按钮,进入第二个进程数
据信息的录入。
“录入完毕进行演示“按钮:当你将所有进程的信息输入完毕后点击此按钮。进入演示界面
进行演示。
“退出“按钮:在执行此界面的任何时刻均可点击此按钮,退出此界面。
录入完毕点击按钮“录入完毕进行执行”后便会弹出进程的执行演示界面如下:
右上角带颜色的三个矩形分别表示进程的执行状态,蓝色矩形代表进程正在执行,绿色矩形代表进程已经执行完成,红色矩形则代表进程受到阻塞。
“开始演示“按钮:点击此按钮则开始演示进程的执行过程。
“暂停演示“按钮:点击此按钮则暂停进程的演示过程。
“重新开始“按钮:点击此按钮则重新演示进程的执行过程。
“退出界面“按钮:点击此按钮则退出演示界面。
“查看阻塞队列”按钮:在点击“暂停演示”按钮之后,点击此按钮,可查看此时的阻塞队
列。
1、 系统设计
本调度算法在设计的时候主要运用了四个类库。PCB 类库主要是包括了要运用到得
相关类有三个,Process 类主要是声明了进程的相关属性以及方法结构体,GetProcess
和SetProcess 类主要是对进程相关属性进行处理。Scheduling 类库主要是实现短作业
优先调度,同样包括三个类,BlockQueue 类主要是实现对阻塞队列的处理,Rank 类主
要是实现按进程的优先级进行排序实现进程的短作业优先调度,SJF 类主要是为了实现
进程执行演示的方便设计的一个类,它声明了一个数组,将每个时刻的进程作为数组元
素放入数据组中。Used 类库主要是对演示界面的处理,里面包括一个类Drawing, 这个
类主要是完成对演示界面所运用到得坐标轴的实现。 最后一个类库为短作业优先调度
演示程序,主要包含了AddFrom 和ShowFrom 两个类,这两个类主要是实现程序界面的
设计,以及相关控件事件的连接以及实现。
在本程序中主要运用的数据结构是数组,如Process[]数组主要使用了存放进来的
进程(存放顺序按进程的到达时间,为方便描述一下均简写为P[]),block[]数组用来
存放阻塞队列,exeQ[]是将进程按短作业优先级排序后的数组,okP[]数组则是某一时
刻到达的所有进程所形成的数组,以上数组均已进程作为数组元素。
短作业优先调度流程图如下:
短作业优先调度
阻塞队列的流程图如下:
进程调度演示流程图: 阻塞队列
进程调度演示
四、系统测试与调试分析
1、系统测试 本程序主要是采用功能测试,对程序进行的相关的测试与分析。共输入五个进程信息,输入设备和输出设备各输入一个然后分别输入各进程的到达时间和服务时间,分别如下:(0 1 1 1 ) (2 1 2 2 )(4 1 1 1 ) (6 2 1 1 1) (8 1 0 1)。再输入过程中,进程的个数、到达时间以及输入设备和输出设备的个数分别是整数,否则将提示输入错误。进程的服务时间必须严格按照要求来填写,否则将提示输入错误。
由此可得五个进程的执行顺序为:3,6,4,5,2。
2、 调试分析
在调试本程序时和演示过程中,出现了不少的错误。其中在编写短作业优先调度算法的代码中,用到了不少的for 循环以及for 循环的嵌套,在这部分出现了变量的混淆,大括号的缺失或多余,经过检查后改正。在编写短作业优先算法代码的时候,
出现了思路紊乱,算法思路不清晰,不能够完成短作业的优先,后经请教同学以及通过画相关流程图得到解决。还有由于对c#的运用并不熟练以及对c#的可视化界面的制作不太了解,使自己在做程序过程中遇到了很大的阻力,后经过翻看相关书籍以及请教同学,解决的这个问题。
本程序的演示界面做的很简陋,只是简单的实现了非抢占式的短作业优先调度,但是在本程序的功能中有一项实现输入设备和输出设备只是实现了设备数目的输入功能,但是没有实现设备之间的互斥问题。因此,本程序无论是在界面还是在功能上均有很大的缺点和不足之处,需要不断的改进和完善。
五、用户手册
1、程序的编写是在win7系统下的VS2010成的。
2、由于电脑系统里已经安装了vs2010此不需要再进行安装。
3、使用本程序界面的步骤。
(1)运行本程序会弹出界面如图5-1:
图5-1
(2)在以上弹出的界面上输入进程的数目以及保存的文件名和输入设备和输出设备的数目。 然后输入第一个进程的进入内存的时间和要求服务的时间。如图5-2:
图5-2
(3)点击“录入第1个数据”按钮,弹出以下窗口,开始输入第二个数据的进入内存的时间和要求服务的时间。如若输入的数据格式正确,则会弹出图5-3:
图5-3
点击确定按钮,进入下一个数据的输入图5-4:
图5-4
如此依次输入所有进程的相关信息,直到所有的进程信息都输入完毕。 如若输入数据不正确则会弹出窗口图5-5:
图5-5
点击确定重新输入正确的进程信息。
(4)当将所有的进程信息都输入完毕后,点击“录入完毕进行演示”按钮。 则会弹出演示界面图5-6:
图5-6
(5)点击开始演示按钮,进程开始执行。演示状态如图5-7:
图5-7
(6)点击暂停按钮,演示暂停,进程停止执行,此时可查看各进程的状态图5-8。
图5-8
(7)在暂停的情况下,点击“查看阻塞队列”按钮。则会弹出以下窗口,并显示此刻的阻塞队列。如图5-9:
图5-9
(8)如果想重新演示,可以点击“重新开始”按钮。当演示完毕后,可以点击“退出界面”按钮。退出演示界面。
六、程序清单
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace
QD.Mg.Winform.Process
public class Process {
static int num = 0;
private int privatePcb;//程序内部使用的PCB public int PrivatePcb {
get { return privatePcb; } set { privatePcb = value ; } }
private int enteringTime;//进入内存的时间 public int EnteringTime {
get { return enteringTime; } set { enteringTime = value ; } }
private double serviceTime;//要求服务的时间 public double ServiceTime {
get { return serviceTime; } set { serviceTime = value ; } }
public Process() {
privatePcb = num++; enteringTime = -1; serviceTime = -1; }
///
///
public override string ToString() {
return privatePcb + "|" + enteringTime + "|" + serviceTime ; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.IO;
namespace QD.Mg.Winform.Process
public class SetProcess {
private static bool save(string filePosition,string content) {
try {
StreamWriter sw = new StreamWriter (filePosition, true , System.Text. Encoding .Default); //在原有的基础上添加 sw.Write(content); sw.Close(); }
catch (IOException e) {
Console .WriteLine(e.Message); return false ; }
return true ; }
public static int setProcesses(string filePosition,Process p) {
//将Process 中的每个进程对象都拼接成一个string 字符串,存放到txt 文件中 string saveString = p.ToString();
saveString = saveString + "\r\n"; //在字符串的最后加上换行的标志 //调用save 函数,实现存储
save(filePosition, saveString); return 0; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.IO;
using System.Text.RegularExpressions;
namespace QD.Mg.Winform.Process {
public class GetProcess {
public static Process [] getProcesses(string filePosition) {
string content = read(filePosition);
string []childString = content.Split(new string []{"\r\n"},StringSplitOptions .RemoveEmptyEntries); //
Process [] process = new Process [childString.Length]; for (int i = 0; i
process[i] = new Process (); }
for (int i = 0; i
//将一个进程的转化成对应的类
string [] grandsonString = childString[i].Split('|'); //为各个变量赋值
process[i].PrivatePcb = Convert .ToInt32(grandsonString[0]); process[i].EnteringTime = Convert .ToInt32(grandsonString[1]); process[i].ServiceTime = Convert .ToInt32(grandsonString[2]); }
return process; }
private static string read(string filePosition) {
FileStream fs = new FileStream (filePosition, FileMode .Open, FileAccess .Read);
StreamReader sr = new StreamReader (fs, Encoding .Default); string content = sr.ReadToEnd(); sr.Close(); return content; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
namespace QD.Mg.Winform.Scheduling {
///
/// 阻塞队列的处理函数 ///
public class BlockQueue {
public static Process. Process [] getBlockQueue(int time, Process. Process [] process) {
#region 变量初始化
Process.Process [] block = new
QD.Mg.Winform.Process. Process [process.Length];//阻塞队列数组
Process.Process [] exeQ;//每个算法的执行顺序 Process.Process [] okP;//给定时间内到达的进程 int num = 0;//阻塞队列的下标 int okPNumber = 0;
int isFinish = -1;//完成的进程的最后一个的下标
int isFinishTotalServiceTime = 0;//完成进程的总的服务时间 #endregion
#region SJF 短作业优先调度算法 //首先获取得到执行的序列
exeQ = Rank .getRank(process); //符合条件的
okP = new QD.Mg.Winform.Process.Process [process.Length]; #region 获取得到 给定时间内到达的进程,进行阻塞队列的计算 for (int i = 0; i
if (exeQ[i] != null && exeQ[i].EnteringTime
okP[okPNumber++] = exeQ[i]; } }
#endregion
#region 获取已经执行完了的进程的标志 已经执行完了的总的服务时间 for (int i = 0; i
if (okP[i] != null ) {
isFinishTotalServiceTime = isFinishTotalServiceTime + Convert .ToInt32(okP[i].ServiceTime);
if (isFinishTotalServiceTime > time) {
isFinish = i - 1; break ; } } }
#endregion
#region 去除不符合条件的
for (int j = 0; j
okP[j] = null ;
}
#endregion
#region 将okP 中的非空值,按照在数组中的顺序,存入阻塞数组中 for (int i = 0; i
if (okP[i] != null ) {
block[num++] = okP[i]; } }
#endregion #endregion return block; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
namespace QD.Mg.Winform.Scheduling {
public class Rank {
public static Process.Process [] getRank(Process.Process [] process) {
//首先按照进入时间排序,然后根据服务时间对排序进行调整 #region 按照进入时间进行排序 Process.Process temp;
for (int i = 0; i
for (int j = i + 1; j
if (process[i].EnteringTime > process[j].EnteringTime) {
temp = process[i];
process[i] = process[j]; process[j] = temp; } } }
#endregion
for (int i = 0; i
{
//获取前面一段的要求服务总时间 int totalServiceTime = 0; for (int x = 0; x
totalServiceTime = totalServiceTime + Convert .ToInt32(process[x].ServiceTime); }
//找到要处理的进程数组,即在前一个进程处理时间内到达的进程 Process.Process [] front = new
QD.Mg.Winform.Process. Process [process.Length];//注意空值
for (int j = i + 1; j
if (Convert .ToInt32(process[j].EnteringTime)
{
front[j] = process[j]; } }
#region 将front 中的非空数据 Process.Process m;
for (int ii = 0; ii
for (int j = ii + 1; j
//
if (front[ii] != null && front[j] != null ) {
if (front[ii].ServiceTime > front[j].ServiceTime)//将作业大的排在后面,实现短作业优先 {
m = front[ii];
front[ii] = front[j]; front[j] = m; } } } }
//将front 中的非空数据,覆盖process 中的相应位置的数据 for (int a = 0; a
if (front[a] != null ) {
process[a] = front[a];
} } }
return process; } } }
using System;
using System.Collections.Generic; using System.Linq; using System.Text;
namespace QD.Mg.Winform.Scheduling {
public class SJF {
public static int [] getExecuteQueue(Process.Process [] process) {
int totalServiceTime = 0;
for (int i = 0; i
totalServiceTime = totalServiceTime + Convert .ToInt32(process[i].ServiceTime); }
int [] executeQueue = new int [totalServiceTime]; int tips = 0;
Process.Process [] exequeue = Rank .getRank(process); for (int i = 0; i
for (int j = 0; j
executeQueue[tips++] = exequeue[i].PrivatePcb; } }
return executeQueue; } } }
七、体会与自我评价
短作业优先调度算法,是指对短作业或短进程优先调度的算法。他们可以分别用于作业调度和进程调度,短作业优先的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将他们调入内存运行。而短进程优先调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给他,,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再度重新调度。本程序采用了非抢占式短作业优先调度。而非抢占式
这种方式,一旦把处理机分配给某进程后,便让该进程一直执行,直至该进程完成或发生某事件而被阻塞时,才再把处理机分配给其它进程,决不允许某进程抢占已经分配出去的处理机。这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统环境。但它难以满足紧急任务的要求——立即执行,因而可能造成难以预料的后果。因此,在要求比较严格的实时系统中,不宜采用这种调度方式本系统的主要是在满足要求多道单处理机的情况下进行短作业的优先调度。
在做课程设计的过程中,我渐渐发现了自己的许多不足之处。比如,对短作业优先调度的原理了解不透彻,对课本知识掌握不熟练,以至在做的过程中需要不断的去翻阅资料和课本,大大降低了制作课设的效率。但正是这样,通过这次短作业优先调度课设,使我更加深刻的理解了短作业优先调度的过程以及工作原理,同时也加深了我对其他进程的理解及原理的掌握,让我对操作系统的知识有了新的认识和感悟,加深了我对课本知识的掌握和理解。同时让我认识到自己的不足之处,自己对课本知识的掌握不透彻,对许多知识点一知半解之后便作罢,缺乏刻苦钻研的认真而又耐心思考问题的习惯,在以后的学习中我会不断的努力,并努力改正这些缺点。 其次,由于自己在编写程序的过程中,遇到了不少的问题,体现了自己编程的生疏不熟练,在一些细节问题上会出现一些小错误,反映了自己对编程许多规则和细节问题上的生疏以及自己的粗心大意的问题,因此在以后的学习之中,应注重自己的动手编程能力,勤加练习,努力做到熟能生巧,同时注重培养自己独立思考问题的能力,在遇到问题面前能够认真努力的思考一番之后在进行处理而不是手忙脚乱的不知所措。这些对我以后的学习将会有很大的帮助,不仅能够让我认识到自己的缺点并督促我改正,同时还能够让我养成许多学习的好习惯,使自己能够跟好的学习和掌握专业知识。我相信,在以后的学习中,我一定会更加努力认真,掌握好专业知识,并提高动手能力和自我解决问题的能力,使自己变的更好。
八、参考文献
【1】汤子瀛 编著,计算机操作系统(修订版),西安电子科技大学出版社,2001年 【2】赵会东 王军等编著,C#项目开发案例全程实录(第二版),清华大学出版社,2011年
【3】 传智播客.net 就业精品培训录像 下载地址:http://download.chinaitlab.com 【4】《初学Visual C# 2010》 下载地址:http://download.chinaitlab.com 【5】《ASP.NET 程序开发范例宝典(C#)(第2版) 》 下载地址:
http://download.chinaitlab.com
九、课程设计评价