收藏 分享(赏)

进程调度算法.doc

上传人:gnk289057 文档编号:9501198 上传时间:2019-08-10 格式:DOC 页数:48 大小:825KB
下载 相关 举报
进程调度算法.doc_第1页
第1页 / 共48页
进程调度算法.doc_第2页
第2页 / 共48页
进程调度算法.doc_第3页
第3页 / 共48页
进程调度算法.doc_第4页
第4页 / 共48页
进程调度算法.doc_第5页
第5页 / 共48页
点击查看更多>>
资源描述

1、进程调度算法目录一 总体设计二 详细设计三 计目的意义、设计内容 四 程序功能模块设计(程序功能模块划分及层次等)五 程序总控流程图六计方案(软硬件环境,开发工具或语言选择及思路) 七 数据结构设计八 程序代码结构(函数调用关系或类层次关系)九 程序主要代码解析十 测试数据及测试结果十一. 目前资料收集情况(含指定参考资料) 总体设计:进程管理是操作系统中的重要功能,用来创建进程、撤消进程、实现进程状态转换,它提供了在可运行的进程之间复用 CPU 的方法。在进程管理中,进程调度是核心,因为在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态,当就绪进程个数大于处理器数目时,就必须依照某

2、种策略决定哪些进程优先占用处理器。本实验模拟在单处理器情况下的进程调度,目的是加深对进程调度工作的理解,掌握不同调度算法的优缺点。本实验主要采用一个模块来实现头文件名为process_schedule.h,程序文件名为 process_schedule.cpp。实验中用到的主要数据结构是进程控制块,其结构如图 1-2 所示。实验中用到 1 个宏和 8个全局变量,如图 1-3 所示。实验中用到的主要函数有 10 个,如图 1-4所示。程序设计组成框图数据项 作用next 前向指针,指向下一个进程控制块,用来构成进程队列process_name 进程名称process_number 进程号,当进程

3、有相同名称时,用来区分进程process_start_moment 进程启动时刻process_need_time 进程要求运行时间process_time_slice 时间片process_priority 优先数图1-2 进程控制块全局变量名称 作用MAX_PROCESS 程序最多能处理的进程数process_number 存放下一个被创建进程的进程号pcb_table 进程控制块表pcb_run 进程运行队列头指针pcb_free 进程空闲队列头指针pcb_ready 进程就绪队列头指针pcb_ready_rear 进程就绪队列尾指针pcb_blocked 进程阻塞队列头指针pcb_bl

4、ocked_rear 进程阻塞队列尾指针图1-3 宏和全局变量函数名称 作用main 初始化进程队列,并管理主菜单命令init_pcb_table 初始化进程空闲队列display_process_queue 以表格的形式显示进程队列create_process 创建进程block_process_by_name 阻塞进程wakeup_process 唤醒进程FCFS 先进先出进程调度算法RR 时间片轮转进程调度算法HPF 优先数进程调度算法MFBQ 多级反馈队列进程调度算法图1-4 函数名称及作用程序流程图开始创建进程及属性选择算法 先来先服务算法优先数算法时闾片轮转法多级反馈队列调度法显示

5、进程执行状态结束 详细设计数据结构设计:用 C+中的结构体模拟进程,用数据结构中的单链表,模拟进程队列,通过对链表的操作实现进程调度算法,进而达到实验的目的。设计方案:(软硬件环境,开发工具或语言选择及思路等)设计环境平台:该软件在 Windows XP,JDK1.6开发工具: DEVC+设计思路 :1、进程概念:进程是被独立分配资源的最小单位进程是动态概念,必须程序运行才有进程的产生。2、进程控制块为了管理和控制进程,系统在创建每一个进程时,都为其开辟一个专用的存储区,用以随时记录它在系统中的动态特性。而当一个进程被撤消时,系统就收回分配给它的存储区。通常,把这一存储区称为该进程的“进程控制

6、块”(Process Control Block) 。由于 PCB 是随着进程的创建而建立,随着进程的撤消而取消的,因此系统是通过 PCB 来“感知”一个个进程的,PCB 是进程存在的唯一标志。随操作系统的不同,PCB 的格式、大小以及内容也不尽相同。一般地,在 PCB 中大致应包括如下 4 方面的信息。标识信息:进程名等。说明信息:进程状态、程序存放位置、数据存放位置等。现场信息:通用寄存器内容、控制寄存器内容、断点地址等。管理信息:进程优先数、队列指针等。3、 进程控制块队列在多道程序设计环境里,同时会创建多个进程。当计算机系统只有一个 CPU 时,每次只能让一个进程运行,其他的进程或处于

7、就绪状态,或处于阻塞状态。为了对这些进程进行管理,操作系统要做三件事。(1)把处于相同状态的进程的 PCB,通过各自的队列指针链接在一起,形成一个个队列。通常有运行队列、就绪队列、阻塞队列。(2)为每一个队列设立一个队列头指针,它总是指向排在队列之首的进程的 PCB。(3)排在队尾的进程的 PCB,它的“队列指针”项内容应该为“NULL”,或一个特殊的符号,以表示这是该队的队尾 PCB。在单 CPU 系统中,任何时刻都只有一个进程处于运行状态,因此运行队列中只能有一个 PCB;系统中所有处于就绪状态的进程的 PCB 排成一队,称其为“就绪队列” 。一般地,就绪队列中会有多个进程的 PCB 排在

8、里面,它们形成处理机分配的候选对象。如果就绪队列里没有 PCB 存在,则称该队列为空;所有处于阻塞状态进程的 PCB,应该根据阻塞的原因进行排队,每一个都称为一个“阻塞队列”。比如等待磁盘输入/输出进程的 PCB 排成一个队列,等待打印机输出进程的 PCB 排成一个队列等。所以,系统中可以有多个阻塞队列,每个阻塞队列中可以有多个进程的PCB,也可以为空。4、 进程调度算法进程调度算法用于确定就绪队列中的哪一个进程即将获得 CPU。常用的进程调度算法有先来先服务法、时间片轮转法、优先数法等。1先来先服务调度算法先来先服务调度算法的基本思想是:以到达就绪队列的先后次序为标准来选择占用处理机的进程。

9、一个进程一旦占有处理机,就一直使用下去,直至正常结束或因等待某事件的发生而让出处理机。采用这种算法时,应该这样来管理就绪队列:到达的进程的 PCB 总是排在就绪队列末尾;调度程序总是把 CPU 分配给就绪队列中的第一个进程使用。2时间片轮转法时间片轮转调度算法的基本思想是:为就绪队列中的每一个进程分配一个称为“时间片 ”的时间段,它是允许该进程运行的时间长度。在使用完一个时间片后,即使进程还没有运行完毕,也要强迫其释放处理机,让给另一个进程使用。它自己则返回到就绪队列末尾,排队等待下一次调度的到来。采用这种调度算法时,对就绪队列的管理与先来先服务完全相同。主要区别是进程每次占用处理机的时间由时

10、间片决定,而不是只要占用处理机就一直运行下去,直到运行完毕或为等待某一事件的发生而自动放弃。3优先数调度算法优先数调度算法的基本思想是:为每一个进程确定一个优先数,进程就绪队列按照优先数排序。如何确定进程的优先数(也就是进程的优先级)?可以从如下几个方面考虑。(1)根据进程的类型。系统中既有系统进程,又有用户进程。系统进程完成的任务是提供系统服务,分配系统资源,因此,给予系统进程较高的优先数能够提高系统的工作效率。(2)根据进程执行任务的重要性。重要性和紧迫性高的进程应当被赋予较高的优先级。(3)根据进程程序的性质。一个 CPU 繁忙的进程,由于需要占用较长的运行时间,影响系统整体效率的发挥,

11、因此只能给予较低的优先数。一个 I/O 繁忙的进程,给予它较高的优先数后,就能充分发挥 CPU 和外部设备之间的并行工作能力。(4)根据对资源的要求。系统资源有处理机、内存储器和外部设备等。可以按照一个进程所需资源的类型和数量,确定它的优先数。比如给予占用 CPU 时间短或内存容量少的进程以较高的优先数,这样可以提高系统的吞吐量。(5)根据用户的请求。系统可以根据用户的请求,给予它的进程很高的优先数,作“加急” 处理。4 多级队列调度算法多级队列调度算法也称多级反馈队列调度算法,它是时间片调度算法与优先数调度算法的结合。实行这种调度算法时,系统中将维持多个就绪队列,每个就绪队列具有不同的调度级

12、别,可以获得不同长度的时间片。例如,系统维持 N 个就绪队列,第 1 级就绪队列中进程的调度级别最高,可获得的时间片最短,第 N 级就绪队列中进程的调度级别最低,可获得的时间片最长。具体的调度方法是:创建一个新进程时,它的 PCB 将进入第 1 级就绪队列的末尾。对于在第 1 级到第 N-1 级队列中的进程,如果在分配给它的时间片内完成了全部工作,那么就撤离系统;如果在时间片没有用完时提出了输入/输出请求或要等待某事件发生,那么就进入相应的阻塞队列里等待。在所等待的事件出现时,仍回到原队列末尾,参与下一轮调度(也就是每个队列实行先来先服务调度算法) ;如果用完了时间片还没有完成自己的工作,那么

13、只能放弃对 CPU 的使用,降到低一级队列的末尾,参与那个队列的调度。对位于最后一个队列里的进程,实行时间片轮转调度算法。整个系统最先调度 1 级就绪队列;只有在上一级就绪队列为空时,才去下一级队列调度。当比运行进程更高级别的队列中到达一个进程(可以肯定,在此之前比运行进程级别高的所有队列全为空)时,系统将立即停止当前运行进程的运行,让它回到自己队列的末尾,转去运行级别高的那个进程。可以看出,多级队列调度算法优先照顾 I/O 繁忙的进程。I/O 繁忙的进程在获得一点 CPU 时间后就会提出输入/输出请求,因此它们总是被保持在 1、2 级等较前面的队列中,总能获得较多的调度机会。对于 CPU 繁

14、忙的进程,它们需要较长的 CPU 时间,因此会逐渐地由级别高的队列往下降,以获得更多的 CPU 时间,它们“沉”得越深,被调度到的机会就越少。但是,一旦被调度到,就会获得更多的 CPU 时间。实验要求采用简单的控制台界面,包括一级功能菜单,如图 2-1 所示。图 2-1 界面要求实验应该包括以下功能:1. 运行先来先服务进程调度算法;2. 运行时间片轮转进程调度算法;3. 运行优先数进程调度算法;4. 运行多级反馈队列进程调度算法;5. 显示就绪进程队列;6. 显示运行进程队列;7. 显示阻塞进程队列;8. 创建新进程;9. 阻塞进程;10. 唤醒进程;11. 删除进程;12. 退出程序。1.

15、 头文件头文件中含有图 2-2、图 2-3 和图 2-4 的内容。#include #include #include #include #include #define MAX_PROCESS 10int process_number=0; /下一个可用的进程编号typedef struct pcbstruct pcb *next; /下一个进程控制块指针char process_name20; /进程名int process_number; /进程编号int process_start_moment; /进程启动时刻int process_need_time; /要求运行时间int pro

16、cess_time_slice; /时间片int process_priority; /优先数PCB; /自定义数据类型:进程控制块PCB pcb_tableMAX_PROCESS; /进程控制块表PCB *pcb_run=NULL; /进程运行队列头指针PCB *pcb_free=NULL; /进程空闲队列头指针PCB *pcb_ready=NULL; /进程就绪队列头指针PCB *pcb_ready_rear=NULL; /进程就绪队列尾指针PCB *pcb_blocked=NULL; /阻塞队列头指针PCB *pcb_blocked_rear=NULL; /阻塞队列尾指针void ini

17、t_pcb_table( ); /初始化进程控制块表void print_space(int num); /显示若干个空格void display_process_queue(PCB *queue); /显示进程队列PCB *create_process( ); /创建进程函数,成功时返回新创建进程的PCB,失败时返回 NULL。void block_process_by_name( ); /阻塞指定名称的进程。void wakeup_process( ); /唤醒进程void FCFS( ); /先来先服务进程调度算法void RR( ); /时间片轮转进程调度算法void HPF( );

18、/优先数进程调度算法void MFBQ( ); /多级反馈队列进程调度算法2. 主函数 main主函数用来初始化进程队列,显示菜单,接收用户输入的菜单选项,并根据用户的选项执行相应的功能。其处理流程如下:main( )初始化进程控制块表;while(1)显示菜单;输出提示信息;接收用户输入的选项,如果输入不是数字 18 或者字母 ad 则重新输入;switch(选项 )case 1:调用先来先服务进程调度算法;break;case 2:调用时间片轮转进程调度算法;break;case 3:调用优先数进程调度算法;break;case 4:调用多级反馈队列进程调度算法;break;case 5:

19、显示就绪进程队列;break;case 6:显示阻塞进程队列;break;case 7:显示运行进程队列;break;case a:调用创建进程函数;break;case b:调用删除进程函数;break;case c:调用阻塞进程函数;break;case d:调用唤醒进程函数;break;case 8:返回;返回;说明:通常用循环语句和多分支语句实现菜单。while 语句实现菜单的循环选择,switch 语句实现功能分支,只有当用户输入数字 8 时,才会跳出循环,结束程序的执行,输入其它合法数字或者字符时,程序将执行对应的功能,并在执行完功能后,重新显示菜单,供用户做下一步选择。main

20、函数的源代码如下:#include “process_schedule.h“ /包含头文件int main(int argc,char *argv )char select; /存放用户选择的菜单项init_pcb_table( ); /初始化进程控制块表while(1)printf(“|-MAIN MENU-|n“); /显示菜单项printf(“| 1:first come first served |n“);printf(“| 2:round robin |n“);printf(“| 3:highest priority first |n“);printf(“| 4:multi_leve

21、l feedback queue |n“);printf(“| 5:display ready process queue |n“);printf(“| 6:display blocked process queue |n“);printf(“| 7:display running queue |n“);printf(“| a:create a process |n“);printf(“| b:delete a process |n“);printf(“| c:block a process |n“);printf(“| d:wakeup a process |n“);printf(“| 8:

22、exit |n“);printf(“|-|n“);printf(“select a function(18,ad):“); /输出提示信息doselect=(char)getch( ); /接收用户的选项while(!(49process_name); /显示进程名称print_space(23-strlen(p-process_name); /右边用空格补齐printf(“| “);printf(“%d“,p-process_number); /显示进程号itoa(p-process_number,buffer,10); /整数转换成字符串print_space(8-strlen(buffe

23、r); printf(“| “);printf(“%d“,p-process_start_moment); /显示进程启动时刻itoa(p-process_start_moment,buffer,10);print_space(6-strlen(buffer);printf(“| “);printf(“%d“,p-process_need_time); /显示进程要求运行时间itoa(p-process_need_time,buffer,10);print_space(5-strlen(buffer);printf(“| “);printf(“%d“,p-process_time_slice)

24、; /显示时间片itoa(p-process_time_slice,buffer,10);print_space(6-strlen(buffer);printf(“| “);printf(“%d“,p-process_priority); /显示优先数itoa(p-process_priority,buffer,10);print_space(10-strlen(buffer);printf(“|n“);p=p-next; /指针下移一个节点printf(“|-|-|-|-|-|-|n“);编译、链接并运行程序。依次选择功能 5、6、7,运行结果都像图 2-6 这样。这是因为到目前为止就绪队列

25、、运行队列和阻塞队列都为空。图 2-65. 创建进程函数 create_process( )为调试方便,要求该函数根据用户从终端输入的数据创建进程,输入数据包括:进程名称、进程启动时刻、要求运行时间、时间片和优先数。如果创建成功则返回新进程 PCB 的地址;如果不成功则返回空指针,不成功的原因是没有空闲 PCB。如果有空闲 PCB,则取空闲 PCB 链首的 PCB 作为新进程的 PCB,并将空闲 PCB 链首下移一个节点,提示用户输入数据,根据用户输入的数据填写 PCB 的数据项,将填写完的 PCB 连到就绪队列尾部。/创建进程函数PCB * create_process( )PCB *p=p

26、cb_free;if(p=NULL) /若无空闲 PCB则返回空指针return NULL;else /有空闲 PCBpcb_free=pcb_free-next; /空闲 PCB 链首下移一个节点system(“cls“);printf(“please enter the following fields:n“); /提示用户输入以下数据项printf(“| name | start_moment | need_time | time_slice | priority |n“);scanf(“%s%d%d%d%d“,p-process_name, /从键盘读取进程名称、/优先数p-proce

27、ss_number=(process_number+1)%100; /生成进程号(0100)process_number+; /下一个进程号p-next=NULL;if(pcb_ready=NULL) /若就绪队列为空pcb_ready=pcb_ready_rear=p; /则新节点为就绪队列唯一节点,对首与队尾相同else /就绪队列不空pcb_ready_rear-next=p; /新建进程插入就绪队列尾部pcb_ready_rear=p;return p; /返回新进程 PCB 地址6. 阻塞进程函数 block_process_by_name( )根据用户输入的进程名阻塞相应的进程,其

28、处理流程如下:(1)若就绪队列为空则直接返回;(2)显示就绪队列;(3)输入要阻塞的进程名称;(4)在就绪队列中按名称查找要阻塞的进程,若查找不到,则返回;(5)将查找到的进程从就绪队列中删除;(6)将查找到的进程插入阻塞队列尾部。7. 唤醒进程函数 wakeup_process( )将阻塞队列的队首进程移入就绪队列尾部。8. 先来先服务进程调度函数 FCFS()总是选择就绪队列的队首进程运行。9. 其它函数其它函数留给同学们自己实现。2.3.3 参考源程序2.3.3.1 windows 下的参考源程序#include “process_schedule.h“int main(int argc

29、,char *argv )char select;init_pcb_table( );while(1)printf(“|-MAIN MENU-|n“);printf(“| 1:first come first served |n“);printf(“| 2:round robin |n“);printf(“| 3:highest priority first |n“);printf(“| 4:multi_level feedback queue |n“);printf(“| 5:display ready process queue |n“);printf(“| 6:display block

30、ed process queue |n“);printf(“| 7:display running queue |n“);printf(“| a:create a process |n“);printf(“| b:delete a process |n“);printf(“| c:block a process |n“);printf(“| d:wakeup a process |n“);printf(“| 8:exit |n“);printf(“|-|n“);printf(“select a function(18,ad):“);doselect=(char)getch( );while(!

31、(49process_name);print_space(13-strlen(p-process_name);printf(“| “);printf(“%d“,p-process_number);itoa(p-process_number,buffer,10);print_space(8-strlen(buffer);printf(“| “);printf(“%d“,p-process_start_moment);itoa(p-process_start_moment,buffer,10);print_space(6-strlen(buffer);printf(“| “);printf(“%d

32、“,p-process_need_time);itoa(p-process_need_time,buffer,10);print_space(5-strlen(buffer);printf(“| “);printf(“%d“,p-process_time_slice);itoa(p-process_time_slice,buffer,10);print_space(6-strlen(buffer);printf(“| “);printf(“%d“,p-process_priority);itoa(p-process_priority,buffer,10);print_space(9-strle

33、n(buffer);printf(“|n“);p=p-next;printf(“|-|-|-|-|-|-|n“);/显示若干个空格void print_space(int num)int i;for(i=0;inext;pcb_run-next=NULL;/时间片轮转进程调度算法void RR( )/优先数进程调度算法void HPF( )/多级反馈队列进程调度算法void MFBQ( )/创建进程函数PCB *create_process( )PCB *p=pcb_free;if(p=NULL)return NULL;elsepcb_free=pcb_free-next;system(“cl

34、s“);printf(“please enter the following fields:n“);printf(“| name | start_moment | need_time | time_slice | priority |n“);scanf(“%s%d%d%d%d“,p-process_name,p-process_number=(process_number+1)%100; /生成进程编号process_number+;p-next=NULL;if(pcb_ready=NULL)pcb_ready=pcb_ready_rear=p;elsepcb_ready_rear-next=

35、p;pcb_ready_rear=p;return p;/阻塞进程函数void block_process_by_name( )char process_name20;PCB *p=pcb_ready;PCB *previous_p=pcb_ready;if(p=NULL)printf(“ready queue is empty,no process can be blocked!n“);return;display_process_queue(pcb_ready);printf(“enter the process name you want to block:n“);scanf(“%s“,

36、process_name);while(p!=NULL) /在就绪队列中查找指定名称的进程if(!strcmp(p-process_name,process_name)break;previous_p=p;p=p-next;if(p=NULL) /没有找到指定名称的进程printf(“no such a process in ready queue:%snyou typed the wrong namen“,process_name);return;else /找到了指定名称的进程if(p=pcb_ready_rear) /找到的进程是就绪队列中最后一个进程pcb_ready_rear=pre

37、vious_p;previous_p-next=p-next; /将指定名称的进程从就绪队列中删除if(pcb_blocked=NULL) /阻塞队列为空pcb_blocked=pcb_blocked_rear=p;p-next=NULL;else /阻塞队列不空pcb_blocked_rear-next=p;pcb_blocked_rear=pcb_blocked_rear-next;p-next=NULL;/唤醒进程函数void wakeup_process( )PCB *p=pcb_blocked;if(pcb_blocked=NULL) /阻塞队列为空,没有进程需要被唤醒printf(

38、“blocked queue is empty,no process needs to be wakeuped.n“);else /阻塞队列不为空,队首进程需要被唤醒if(pcb_blocked=pcb_blocked_rear) /阻塞队列中只有一个进程,唤醒后队列为空pcb_blocked=pcb_blocked_rear=NULL;else /阻塞队列中有多个进程pcb_blocked=pcb_blocked-next; /删除队首进程if(pcb_ready=NULL) /就绪队列为空插入在就绪队列首pcb_ready=pcb_ready_rear=p;p-next=NULL;else

39、 /就绪队列不为空则插入就绪队列尾pcb_ready_rear-next=p;pcb_ready_rear=pcb_ready_rear-next;p-next=NULL;/wakeup2.3.3.2 linux 下的参考源程序编译命令 1gcc process_schedule.cpp o process_schedule.o lcurses程序清单 2头文件 process_schedule.h#include #include #include #include #define MAX_PROCESS 10int process_number=0;typedef struct pcbst

40、ruct pcb *next;char process_name20;int process_number;int process_start_moment;int process_need_time;int process_time_slice;int process_priority;PCB;PCB pcb_tableMAX_PROCESS;PCB *pcb_run=NULL;PCB *pcb_free=NULL;PCB *pcb_ready=NULL;PCB *pcb_ready_rear=NULL;PCB *pcb_blocked=NULL;PCB *pcb_blocked_rear=

41、NULL;void init_pcb_table();void display_process_queue(PCB *queue);PCB *create_process();void block_process_by_name();void wakeup_process();void FCFS();void RR();void HPF();void MFBQ();源文件 process_schedule.cpp#include “process_schedule.h“int main(int argc,char *argv)char select;initscr();init_pcb_tab

42、le();bool end=false;while(!end)clear();refresh();printw(“|-MAIN MENU-|n“);printw(“| 1:first come first served |n“);printw(“| 2:round robin |n“);printw(“| 3:highest priority first |n“);printw(“| 4:multi_level feedback queue |n“);printw(“| 5:display ready process queue |n“);printw(“| 6:display blocked

43、 process queue |n“);printw(“| 7:display running queue |n“);printw(“| a:create a process |n“);printw(“| b:delete a process |n“);printw(“| c:block a process |n“);printw(“| d:wakeup a process |n“);printw(“| 8:exit |n“);printw(“|-|n“);printw(“select a function(18,ad):“);refresh();doselect=(char)getch();

44、refresh();while(!(49process_name);move(i,12);printw(“| “);printw(“%d“,p-process_number);move(i,23);printw(“| “);printw(“%d“,p-process_start_moment);move(i,34);printw(“| “);printw(“%d“,p-process_need_time);move(i,45);printw(“| “);printw(“%d“,p-process_time_slice);move(i,56);printw(“| “);printw(“%d“,p-process_priority);move(i,67);printw(“|“);p=p-next;i+;move(i,1);printw(“|-|-|-|-|-|-|n“);refresh();void FCFS()if(pcb_ready=NULL)printw(“ready queue is empty,no process to run.n“);elsepcb_run=pcb_ready;if(pcb_ready=pcb_ready_rear)pcb_re

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报