模拟进程调度功能的设计与实现操作系统课程设计(MFC版本)
目录
1、设计目的意义„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2
1.1、目的意义„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2
1.2、实现目标„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 2、设计
„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„3
2.1、软硬件环境„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„3
2.2、开发工具„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„3
2.3、思路„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„3 3、程序功能模块设计„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„4
3.1、总体模块„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„4
3.2、部分模块„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„4
3.3、详细功能描述„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„6 4、程序总控
图„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„6 5、数据结构设计„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„8
5.1、PCB结构„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„8
5.2、进程状态结构„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„8
5.3、控件结构„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„9 6、程序代码结构„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„9 7、程序主要代码解析„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„10 8、测试数据及测试结果„„„„„„„„„„„„„„„„„„„„„„„„„„„„„15
8.1、运行时部分界面„„„„„„„„„„„„„„„„„„„„„„„„„„„„15
8.2、数据测试
„„„„„„„„„„„„„„„„„„„„„„„„„„„„„17 9、设计过程中遇到的问题及解决方法„„„„„„„„„„„„„„„„„„„„„„„18 10、结论„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„18
10.1、系统实现情况„„„„„„„„„„„„„„„„„„„„„„„„„„„„„18
10.2、系统特点„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„18
10.3、设计体会及收获„„„„„„„„„„„„„„„„„„„„„„„„„„„„18 11、参考资料„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„19 [键入文字] 1
设计目的意义
1.1、目的意义
, 通过课程设计理解进程调度的概念,深入了解进程控制的功能、进程的创建、删除以
及进程各个状态间的转换过程;实现先来先服务、时间片轮转、最短作业优先、优先
级调度算法对进程进行的调度过程;通过观察有关的队列结构的内容的动态变化过程
深入体会各个调度算法的特点;从而能够更好的巩固从
本上学到的知识。 , 编程过程中需要建立队列等结构进行各种操作,通过该次课程设计,我们更加从实用
的角度对《数据结构》课程内容进行更深入理解和更熟练的应用。 , 使用C++语言进行编程,通过对调度功能的编程实现,不但能有效训练我们对编程语
言的熟练使用,还能促进我们独立思考解决问题、以及独立查新获取知识的能力。
1.2、实现目标
, 一个进程的生命期可以划分为一组状态,这些状态刻画了整个进程。系统根据PCB结
构中的状态值控制过程。在进程的生命期内,一个进程至少具有5种基本状态,它们
是:初始态、执行状态、等待状态、就绪状态和终止状态。通过系统设计,实现进程
相关数据结构的创建和查看功能;实现多种进程调度算法:先来先服务算法、优先级
调度算法、时间片轮转法等;实现对执行进程的阻塞,对等待进程的唤醒等功能。进
程的转换过程如下:
初始
就绪 因等待事件 调度 发生而唤醒
时间片到
等待 执行
等待某个事件
发生而睡眠
完成
终止
2、设计方案
[键入文字] 2
2.1 软硬件环境
, 硬件设备: PC机
, 软件设备:WINDOWSXP、Microsoft Visual C++ 6.0
2.2、开发工具
, 由于现在使用的操作系统大多数都是微软公司的产品,为了更好更贴近的模拟操作系
统中进程调度功能,我们选择使用C++语言,开发平台Microsoft Visual C++ 6.0,
借助MFC来完成应用Windows应用程序的开发。另外通过课余时间的学习,对Windows
应用程序的开发过程也有一些了解,很想学以致用,做点使用的东西加深对学习过的
知识的理解与吸收。
2.3、思路
, 进程根据外界条件的不断变化引起状态的改变,可以利用系统时间片的大小、进程执
行时间、进入主存的时间、系统内存大小、以及调度算法的选择来作为条件对进程进
行调度。通过在对话框中添加按钮、文本编辑框、列
等控件,并为控件关联相应的
变量和消息函数,实现各个控件内部以及控件之间的协同工作,并使用定时器进行时
间的设置,从而完成系统所要求的进程调度工作。Windows应用程序,操作系统,计
算机硬件之间的相互关系如下:
应用程序 消息队列
操作系统
输入输出设备
3、程序功能模块设计(程序功能模块划分及层次等)
3.1、总体模块
[键入文字] 3
3.2、部分模块
[键入文字] 4
3.3、详细功能描述
[键入文字] 5
, 根据需要设置系统内存的大小
, 选择不同的进度调度算法进行进程调度模拟
, 设置进程的各种属性值创建进程
, 根据进程不同的状态放在不同的位置显示进程调度过程中的动态变化情况
, 在某一时间点击按钮进行进程调度模拟
, 进程调度模拟过程中可以暂停调度过程,查看进程的状态变化过程
, 通过双击状态列表中的某个进程可以查看进程的各属性值
, 对执行进程、就绪进程进行强制“阻塞”操作
, 对等待进程进行强制“就绪”操作
, 将没有执行完毕的进程进行强制“杀死”操作
4、程序总控流程图
(见下页)
[键入文字] 6
开始
创建新的进程 设置内存大小 选择不同的调度算法
新添加的进程所需要
的资源因为主存的限
制按先后顺序进入就
本图只是系绪队列或是等待队列
统运行时的
大致过程
开始调度
按不同对处于不同状暂停操作可双击某个进程可
的调度态队列的进程以停止进程以查看进程的属
算法开进行阻塞、就调度并可以性、复位操作清空
始进行 绪、杀死等操作 继续执行 各状态队列等
只要各进程状态队列不空,根
据不同的条件,进程状态而改
变
执行进程执行条件不一旦有执行进程执行完毕只要剩余内存允许,
满足则立即进入等待或是转为别的状态,就从就从等待队列中选择
队列或是就绪队列 就绪队列选择一个执行 进程进入就绪队列
直至各队列全为
空
结束
5、数据结构设计
[键入文字] 7
5.1、PCB结构
5.2、进程状态结构
[键入文字] 8
5.3、控件结构
6、程序代码结构
, 程序主要函数如下,各函数通过关联相关变量进行消息传递 , CProgressExDlg::CProgressExDlg(CWnd* pParent /*=NULL*/)
: CDialog(CProgressExDlg::IDD, pParent)
构造函数,调用基类CProgressExDlg,并传递两个参数:一个CProgressExDlg类的
IDD成员,一个是父窗口指针。
, void CProgressExDlg::DoDataExchange(CDataExchange* pDX)
主要用来完成对话框数据的交换和校验。 , void CProgressExDlg::OnButPause()
用于暂停进程调度操作
, void CProgressExDlg::OnButStart()
用于启动进程调度
, void CProgressExDlg::OnButton1()
用于复位,清除各进程
, void CProgressExDlg::OnButton2()
[键入文字] 9
用于创建进程
, void CProgressExDlg::OnButtonBlock()
用于使选定进程进入就绪状态
, void CProgressExDlg::OnButtonKill()
用于杀死选定进程
, void CProgressExDlg::OnButtonNotify()
用于阻塞选定进程
, HBRUSH CProgressExDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
用于设置显示进程属性时的字体和颜色
, void CProgressExDlg::OnDblclkListReadypro()
用于双击就绪队列中的某个进程,进而显示其属性
, void CProgressExDlg::OnDblclkListRunpro()
用于双击执行队列中的某个进程,进而显示其属性
, void CProgressExDlg::OnDblclkListWaitpro()
用于双击等待队列中的某个进程,进而显示其属性
, BOOL CProgressExDlg::OnInitDialog()
初始化对话框
, void CProgressExDlg::OnPaint()
绘制对话框
, void CProgressExDlg::OnTimer(UINT nIDEvent)
处理各种调度算法
7、程序主要代码解析
由于代码较多,以下只列出了先来先服务算法和最短作业优先算法的代码。
if (nIDEvent == 0) //为先来先服务调度算法
{
if (((((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->GetCount())==0) &&
(ReadyVec.size()!=0)) //如果没有进程运行,先择优先级最高的进入运行
{
sort(ReadyVec.begin(),ReadyVec.end(),Compare);
((CListBox *)GetDlgItem(IDC_LIST_READYPRO))->ResetContent();
for (int i = 0; i
InsertString(i,buf);
}
ReadyVec[0].status=0;
RunVec.push_back(ReadyVec[0]);
tempRunPcb = ReadyVec[0];
((CListBox *)GetDlgItem(IDC_LIST_READYPRO))->DeleteString(0);
CString buf;
buf.Format("%d %s",ReadyVec[0].PID,ReadyVec[0].PName);
((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->AddString(buf);
}
else if(((((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->GetCount())!=0) && (ReadyVec.size()!=0))
{
RunVec[0].WorkTime-=100;
if ( RunVec[0].WorkTime <= 0)
{
((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->ResetContent();
m_memSize+= ReadyVec[0].MemCount;
runTime = 0;
RunVec.clear();
vector::iterator pos1 = ReadyVec.begin();
ReadyVec.erase(pos1);
}
}
else if (((((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->GetCount())!=0) &&
(ReadyVec.size()==0))
{
RunVec[0].WorkTime-=100;
if ( RunVec[0].WorkTime <= 0)
{
((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->ResetContent();
m_memSize+= ReadyVec[0].MemCount;
runTime = 0;
RunVec.clear();
vector::iterator pos1 = ReadyVec.begin();
ReadyVec.erase(pos1);
}
}
if ((((CListBox *)GetDlgItem(IDC_LIST_WAITPRO))->GetCount())!=0)
{
if (WaitVec.size()!=0)
{
sort(WaitVec.begin(),WaitVec.end(),Compare);
for (int j = 0;j::iterator pos = &WaitVec[j];
WaitVec.erase(pos);
((CListBox *)GetDlgItem(IDC_LIST_WAITPRO))->DeleteString(j);
CString buf;
buf.Format("%d %s",ReadyVec[j].PID,ReadyVec[j].PName);
((CListBox
*)GetDlgItem(IDC_LIST_RUNPRO))->InsertString(ReadyVec.size()
,buf);
}
}
((CListBox *)GetDlgItem(IDC_LIST_WAITPRO))->ResetContent();
for (j = 0;jInsertString(j,buf);
}
}
}
UpdateData(FALSE);
}
else if (nIDEvent == 1)//最短作业优先算法
{
if ((!ReadyVec.empty()) && ((((CListBox
*)GetDlgItem(IDC_LIST_RUNPRO))->GetCount())==0))
{
std::stable_sort( ReadyVec.begin(),ReadyVec.end(),CompareByWkt);
((CListBox *)GetDlgItem(IDC_LIST_READYPRO))->ResetContent();
for (int i = 0; iInsertString(i,buf);
}
ReadyVec[0].status=0;
RunVec.push_back(ReadyVec[0]);
ReadyVec[0].WorkTime-=100;
tempRunPcb = ReadyVec[0];
CString buf;
[键入文字] 12
((CListBox *)GetDlgItem(IDC_LIST_READYPRO))->GetText(0,buf);
((CListBox *)GetDlgItem(IDC_LIST_READYPRO))->DeleteString(0);
((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->AddString(buf);
UpdateData(false);
}
else if (((((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->GetCount())!=0) &&
(ReadyVec.size()!=0))
{
ReadyVec[0].WorkTime-=100;
if ( ReadyVec[0].WorkTime <= 0)
{
((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->ResetContent();
UpdateData(false);
m_memSize+= ReadyVec[0].MemCount;
runTime = 0;
RunVec.clear();
vector::iterator pos1 = ReadyVec.begin();
ReadyVec.erase(pos1);
}
//操作阻塞队列
stable_sort(WaitVec.begin(),WaitVec.end(),CompareByWkt);
if (WaitVec.size()!=0)
{
if (WaitVec[0].MemCount <= m_memSize)
{
m_memSize-= WaitVec[0].MemCount;
WaitVec[0].status=1;
ReadyVec.push_back(WaitVec[0]);
vector::iterator pos = WaitVec.begin();
WaitVec.erase(pos);
if (ReadyVec.size()!=0)
{
((CListBox *)GetDlgItem(IDC_LIST_READYPRO))->ResetContent();
for (int i = 0; iInsertString(i,buf);
}
UpdateData(false);
}
((CListBox *)GetDlgItem(IDC_LIST_WAITPRO))->ResetContent();
for (int i = 0; iInsertString(i,buf);
}
UpdateData(FALSE);
}
}
}
else if (((((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->GetCount())!=0) && (ReadyVec.empty()))
{
ReadyVec[0].WorkTime-=100;
if ( ReadyVec[0].WorkTime <= 0)
{
((CListBox *)GetDlgItem(IDC_LIST_RUNPRO))->ResetContent();
UpdateData(FALSE);
m_memSize+= ReadyVec[0].MemCount;
runTime = 0;
RunVec.clear();
}
}
else
{
UpdateData(FALSE);
}
}
8、测试数据及测试结果
8.1、运行时部分界面
刚启动时
[键入文字] 14
添加进程后:
先来先服务算法调度点击开始模拟后:
[键入文字] 15
双击执行进程时:
点击阻塞时:
[键入文字] 16
8.2、数据测试记录
系统内存:10M 时间片:1000
进程名称 进程ID 进入时间 执行时间 优先级 所需内存
a 1001 2000 3 1
运行时捕捉b 1002 1000 1 2
系统时间,以c 1003 3000 2 2 毫秒为单位
d 1004 2000 4 6
e 1005 5000 5 3
调度算法 进程执行顺序
先来先服务算法 a,b,c,e,d
最短作业优先算法 b,a,c,e,d
优先级调度算法 e,a,c,b,d
时间片轮转法 a,b,c,e,a,c,e,c,e,d,e,d,e,d
9、设计过程中遇到的问题及解决方法
, 满足进程动态生成的需要,使用向量vector进行存放进程
[键入文字] 17
, 向量vector中的内容不能直接使用下标删除,使用迭代器iterator并结合函数erase
使用。
, 使用组合框Combo Box时没有下拉滚动条,可以刚开始时把组合框画的大一点就可以。 , 运行时同一个进程在不同的两个状态同时出现,在状态转换时删除列表框中的内容后
要更新一下。
, 进程运行完后对应的内存资源没有增加,在每次的进程运行结束或是从执行状态转换
到等待状态,都要释放资源。
, 编码过程中也出现了逻辑不够严密等错误,经过一一排查都把错误改正了。
10、结论
10.1、系统实现情况
, 课程设计任务书中所要求的功能我们都已经准确无误的实现,测试中没有出现什么错
误。该系统实现了进程控制的功能、进程的创建、删除以及进程各个状态间的转换
过程;实现了先来先服务、时间片轮转、最短作业优先、优先级调度算法对进程进
行调度过程;系统界面上所有的功能部件表明的功能都已实现。 10.2、系统特点
, 系统界面清晰明了,便于使用
, 系统外观不是很美观,不过功能强大,很实用。实现了进程的动态创建,提供多种调
度算法,并可以很容易的观察中间运行情况。
, 系统有一定的容错和出错检验能力,比如对输入数据的类型进行判断是否符合要求,
输入数据是否超过了某个范围,点击“阻塞”“就绪”“杀死”按钮需要先要选定一
个进程,否则会弹出出错对话框。
10.3、设计体会及收获
, 这次的课程设计给我们很大的收获,使我们对操作系统的基本知识有了进一步的提
高,并在实践中对各种概念有了进一步的深化,开始的时候总觉得很简单的课程设
计,不过在实际的动手操作中没有想象中的那么轻松。 , 程序的设计思想的精巧的重要性,是不管怎么说都不为过的,好的设计可以让大家很
快的明白你的思想,而且很方便的来实现它。
, 良好的编程习惯,它可以使你的程序很方便的被别人阅读,也很方便的被更改,所以
可以的话,尽可能多的写出注释,没有人会闲你写的太多。 , 尽可能多的和小组成员讨论,自己写的东西可能存在逻辑上的失误,而自己可能并不
知道,或者完成了后才发现自己根本没有符合要求 。在多人一起协调工作的时候,
队员的交流是非常重要的,接口的说明和思想的交流都是很关键的部分。 , 基本的语言功底一定要扎实,通过课程设计,我们有把C++复习了一下,并编程能力
也有一定得提高。从使用的角度对数据结构等课程有了更深入的认识和掌握。 [键入文字] 18
, 体验了使用MFC开发的过程,很好的巩固了从书本上学到的知识,对更深入的学习
Visual C++很有帮助。尤其在编程过程中得到很多很实用的编程经验。
, 课程设计结束了,不只学到了设计进程的创建以及状态如何转换的思想,重要的是有
了多人合作的经验,这是平时上课或是书本上无法获得的宝贵财富。
11、参考资料
著作:[1] 张尧学,史美林.计算机操作系统教程第2版.清华大学出版社2000年 著作:[2] 张尧学.计算机操作系统教程第2版 习题与实验指导. 清华大学出版社2000年 著作:[3] 孙鑫,余安萍.VC++深入详解.电子工业出版社 2006年
著作:[4] 求是科技.Windows API 程序设计参考大全.人民邮电出版社 2006年
[键入文字] 19