logo资料库

操作系统实验_多级反馈队列调度算法.doc

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
院 系:计 算 机 学 院 实验课程:操作系统教程 实验项目:进程调度的设计与实现 指导老师:冯刚 开课时间:2012 ~ 2013 年度第 2 学期 专 业:网络工程 班 级:11 级 6 班 学 生:黄兴静 学 号:20112100185 1
目录 一、 实验的目的………………………………………………1 二、 实验的内容(任务)及要求……………………………1 三、 实验设备及环境…………………………………………1 四、 实验的原理………………………………………………1 五、 关键算法的实现流程图…………………………………2 六、 实验的设计思想及相关代码……………………………3 七、 实验的图形用户界面 GUI 设计…………………………8 八、 心得体会…………………………………………………8 2
一、实验的目的 1、 综合应用下列知识点设计并实现操作系统的进程调度:邻接表,布尔数组, 非阻塞输入,图形用户界面 GUI ,进程控制块,进程状态转换,多级反馈队列 进程调度算法。 2、 加深理解操作系统进程调度的过程。 3、 加深理解多级反馈队列进程调度算法。 二、实验的内容(任务)及要求 1、设计一个虚拟处理机,编程序演示多级反馈队列调度算法的具体实现过程 2、用一种熟悉的语言,如 C、PASCAL 或 C++等,编制程序。在这次实验中,关 键代码(即多级反馈队列调度算法的代码)采用 C++,而界面设计采用 MFC 界面 设计。 三、实验设备及环境 PC(即电脑), Microsoft Visual C++ 6.0(编程软件) 四、实验的原理 多级反馈队列调度算法: 1、设置多个就绪队列,并给队列赋予不同的优先级数,第一个最高,依次递减。 2、赋予各个队列中进程执行时间片的大小,优先级越高的队列,时间片越小。 但在本实验中,各个队列中进程执行时间片的大小都为 1。 3、当一个新进程进入内存后,首先将其放入第一个队列末尾,按 FCFS 原则排 队等待调度;当轮到该进程执行时,如能在该时间片内完成,便可准备撤离系 统;如果在一个该时间片结束时尚未完成,将其转入第二队列末尾,再同样按 FCFS 原则排队等待调度执行;如果它在第二队列中运行一个该时间片仍未完 成,再依次将它转入第三队列。如此下去,当一个进程从一个对列移至第 n 个 队列后,便在第 n 个队列中采用时间片轮转执行完(最后一个队列的进程采用 时间片轮转执行完) 但在本实验中,一个新进程进入内存后,是将其放入某个就绪队列的末尾。当 轮到该进程执行时,如能在该时间片内完成,便可准备撤离系统;如果在一个 该时间片结束时尚未完成,将其转入优先级减半的队列末尾,如果它在第二队 列中运行一个该时间片仍未完成,再依次将它转入优先级减半的队列。如此下 去,当一个进程从一个对列移至第 n 个队列后,便在第 n 个队列中采用时间片 轮转执行完(最后一个队列的进程采用时间片轮转执行完) 4、仅当时间片空闲时,才调度第二个队列中的进程。(1~i-1)空闲时,才调度 i, 如果处理机正在第 i 队列中运行,在低优先级的队列中的进程在运行时,又有新 到达的作业,那么在运行完这个时间片后,CPU 马上分配给新到达的作业,即 新进程抢占处理机(抢占式),将正在运行的进程放入原来队列的下一个队列的 队尾,将处理机分给新进程。 3
但在本实验中,实验要求并没有要求我们实现进程抢占式 五、关键算法的实现流程图 开始 随机生成数个进程 调度进程 执行进程 i 是否按下 crtl+f? Y 插入新进程 N 进程 i 移到就绪队列 CPU 调新进程 继续执行进程 i 优先级减半 生命周期减 1 生命周期为 0? Y 进程 i 完成 撤销 PCB N 进程 i 变就绪状态 插入就绪队列 4
六、实验的设计思想及相关代码 Ⅰ每一个进程都有一个对应的进程控制块,即 PCB,其里面函数变量有进程标识 符 pid、进程的状态标识 status、进程优先 priority 和表示进程生命周期的数 据项 life (在实际系统中不包括该项)。 struct PCB { } int pid; int status; int priority; int life; //进程标识符 //进程的状态标识,0 表示就绪,1 表示运行 //进程优先级 //进程生命周期 Ⅱ进程状态 status 的取值为“就绪 ready”或“运行 run ”,刚创建时,状 态为“ready”,用整数 0 表示。被进程调度程序选中后变为“run”,用整数 1 表示。 Ⅲ进程优先级 priority 是 0 到 49 范围内的一个随机整数。 srand(unsigned(time(0))); priority=rand()%50+1; //在本次实验的进程优先级中,我用 1 到 50 范围内的一个随机数,是为了后面 的进程执行次序的代码作铺垫。 Ⅳ进程生命周期 life 是 1 到 5 范围内的一个随机整数。 srand(unsigned(time(0))); priority=rand()%5+1; Ⅰ到Ⅳ可得到进程创建的代码 //添加进程 void 头文件的名字::OnButton1() { //stop=true; // TODO: Add your control notification handler code here sum++;//进程数+1; srand(unsigned(time(0))); p[sum].pid=sum;//生成相同 id,有 BUG p[sum].life=rand()%5+1; p[sum].priority=rand()%50+1; p[sum].status=0;//准备状态; q[p[sum].priority].push(p[sum]); 5
show(); //stop=false; UpdateData(TRUE); } Ⅴ初始化时,创建一个邻接表,包含 50 个就绪队列,各就绪队列的进程优先级 priority 分别是 0 到 49。 注意:本次实验我用的是 1 到 50 在函数头文件中加函数变量: queueq[51]; queueq1[51]; Ⅵ为了模拟用户动态提交任务的过程,要求动态创建进程。进入进程调度 循环后,每次按 ctrl+f 即动态创建一个进程,然后将该 PCB 插入就绪队 列中。按 ctrl+q 退出进程调度循环。 1. 首先在头文件中加上(红色加粗部分为增加项,位置不能随意): afx_msg LRESULT OnHotKey(WPARAM wParam,LPARAM lParam); //}}AFX_MSG DECLARE_MESSAGE_MAP() 2. 关联消息及函数(红色加粗部分为增加项,位置不能随意): BEGIN_MESSAGE_MAP(头文件的名字, CDialog) //{{AFX_MSG_MAP(头文件的名字) ON_MESSAGE(WM_HOTKEY,OnHotKey) //消息和函数发生关联 //}}AFX_MSG_MAP END_MESSAGE_MAP() 3. 定义消息号在头文件的 CPP 文件的:: OnInitDialog()函数中加上(位置不限) RegisterHotKey(m_hWnd, 1001, MOD_CONTROL,'F');, RegisterHotKey(m_hWnd, 1002, MOD_CONTROL,'5'); RegisterHotKey(m_hWnd, 1003, MOD_CONTROL,'Q'); 4. 定义响应函数 //自定义快捷键 LRESULT 头文件的名字::OnHotKey(WPARAM wParam,LPARAM lParam) { // TODO: Add your code here if(wParam==1001) { OnButton1(); } else if(wParam==1002) 6
{ OnButton2(); } else if(wParam==1003) { OnButton3(); } return 0; } } void 头文件的名字::OnButton3() { // TODO: Add your control notification handler code here exit(0); Ⅶ在进程调度循环中,每次选择优先级最大的就绪进程来执行。将其状态从就 绪变为运行,通过延时一段时间来模拟该进程执行一个时间片的过程,然后优 先级减半,生命周期减一。 void 头文件的名字::OnButton2() { // TODO: Add your control notification handler code here for(int i=50;i>=1;i--) { bool flag=false; CString str=""; while(!q[i].empty()) { flag=true; PCB temp=q[i].front(); str=str+"进程 ID:"; CString s; s.Format(_T("%d"),temp.pid); str=str+s+" 进程生命时间:"; s.Format(_T("%d"),temp.life); str=str+s+" "; temp.life--; temp.priority=temp.priority/2; if(temp.life>0) { if(temp.priority>0) 7
else q[temp.priority].push(temp); q[1].push(temp);//重新加入队尾 sum--; q[0].push(temp); } q[i].pop(); //延迟有问题 SetDlgItemText(IDC_EDIT51,str); show(); UpdateData(TRUE); break; } else { } if(flag) { } } } Ⅷ设计图形用户界面 GUI ,在窗口中显示该进程和其他所有进程的 PCB 内容。 如果将该运行进程的生命周期不为 0 ,则重新把它变为就绪状态,插入就绪队 列中;否则该进程执行完成,撤消其 PCB 。以上为一次进程调度循环。 1、 首先在头文件中的 public:加上:输出函数 void show(); 例如: { // Construction public: 头文件的名字(CWnd* pParent = NULL); void show(); // standard constructor } 2、 在头文件.cpp 文件定义输出函数 void show();的响应函数 void 头文件的名字::show() { CString Str=""; CString str=""; int id=IDC_EDIT1; for(int i=1;i<=50;i++) 8
分享到:
收藏