实验二 进程调度算法的设计
实验题目
-
先来先服务(FCFS)调度算法
-
原理:每次调度是从就绪队列中,选择一个最先进入就绪队列的进程,把处理器分配给该进程,使之得到执行。该进程一旦占有了处理器,它就一直运行下去,直到该进程完成或因发生事件而阻塞,才退出处理器。
-
将用户作业和就绪进程按提交顺序或变为就绪状态的先后排成队列,并按照先来先服务的方式进行调度处理,是一种最普遍和最简单的方法。它优先考虑在系统中等待时间最长的作业,而不管要求运行时间的长短。
-
按照就绪进程进入就绪队列的先后次序进行调度,简单易实现,利于长进程,CPU繁忙型作业,不利于短进程,排队时间相对过长。
-
-
时间片轮转调度算法RR
- 原理:时间片轮转法主要用于进程调度。采用此算法的系统,其程序就绪队列往往按进程到达的时间来排序。进程调度按一定时间片(q)轮番运行各个进程。
- 进程按到达时间在就绪队列中排队,调度程序每次把CPU分配给就绪队列首进程使用一个时间片,运行完一个时间片释放CPU,排到就绪队列末尾参加下一轮调度,CPU分配给就绪队列的首进程。
- 固定时间片轮转法:
- 所有就绪进程按 FCFS 规则排队。
- 处理机总是分配给就绪队列的队首进程。
- 如果运行的进程用完时间片,则系统就把该进程送回就绪队列的队尾,重新排队。
- 因等待某事件而阻塞的进程送到阻塞队列。
- 系统把被唤醒的进程送到就绪队列的队尾
- 可变时间片轮转法:
-
进程状态的转换方法同固定时间片轮转法。
-
时间片的长短依据就绪队列进程数量的多少由 T = N ∗ ( q + t ) T=N*(q+t) T=N∗(q+t)的关系调整(T为响应时间(固定),N为就绪队列进程数,q为时间片的长短,t为上下文切换时间。其中q为毫秒级及以上,上下文切换时间t为纳秒级而忽略不计)。即就绪队列进程数有变化时,时间片需要调整。
-
程序中使用的数据结构及符号说明
-
结构体表示进程,结构体数组记录各个进程的信息:
struct process { int id; //编号 int pos; //排序后的位置 int arrive; //到达时间 int work; //区间时间 int begin; //开始时间 int end; //完成时间 int turnaround; //周转时间 int wait; //等待时间 bool in; //是否进入过就绪队列 bool finish; //是否完成 int rest; //剩余区间时间(RR) int block_p; //最近一次被阻塞的时间点 int block_t; //阻塞时间长度(RR) } proc[N];
-
使用数据结构queue(队列):
queue <process> ready; //就绪队列 queue <process> block; //阻塞队列(RR) queue <process> block_new; //(临时)新阻塞队列,用于阻塞队列的更新(RR)
-
整型变量:
//全局变量 int k, k_RR, n, q; /* k:算法类型(0:FCFS 1:RR) k_RR:RR算法类型(0:时间片固定 1:可变) n:进程数 q:时间片 */ int now = 0; //当前时间 //FCFS_And_RR函数内部 int left = n; //剩余的未完成进程数 int once_max; //一个时间片内一个进程最大运行时间 int once; //记录一个时间片内的运行时间 int min_arrive = 0x3f3f3f; //未到达进程的最小到达时间(可能有多个进程) int in_flag = 0; //当前时间是否有进程入就绪队列
-
函数:
bool cmp_FCFS(process a, process b)
:FCFS规则排队的比较函数;bool cmp_id(process a, process b)
:按编号顺序的排序函数void init()
:输入信息进行初始化的函数void block_check()
: 查看阻塞队列中是否有进程被唤醒的函数void FCFS_And_RR()
:FCFS调度算法和RR调度算法的函数void display()
:用于输出结果的函数
源程序及注释:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using namespace std;
#define N 100001
//算法类型(0:FCFS 1:RR),RR算法类型(0:时间片固定 1:可变),进程数,时间片
int k, k_RR, n, q;
int now = 0; //当前时间
struct process
{
int id; //编号
int pos; //排序后的位置
int arrive; //到达时间
int work; //区间时间
int begin; //开始时间
int end; //完成时间
int turnaround; //周转时间
int wait; //等待时间
bool in; //是否进入过就绪队列
bool finish; //是否完成
int rest; //剩余区间时间
int block_p; //最近一次被阻塞的时间点
int block_t; //阻塞时间长度
} proc[N];
queue <process