实验目的
1、进一步理解进程调度的过程
2、理解先来先服务FCFS、简单时间片轮转、动态优先级调度算法的基本原理
实验内容
1、编写一个C或C++代码,实现以上要求的算法(至少完成2个算法),每进行一次调度,打印一次运行进程、就绪队列,以及每个进程的PCB信息。
2、实现环境不限
基本思路及要求
1、输入及输出
程序开始时,输入进程的个数,每个进程的名称、到达时间、服务时间、初始优先级(值越大,优先级越高)
选择一个调度算法,开始运行
每进行一次调度,显示当前正在运行的进程名称、就绪队列中的进程名称(按顺序),以及当前所有进程的信息
2、每个进程用一个进程PCB来表示,一般包括进程名(10个字符)、到达时间、服务时间、已用时间、优先数、进程状态(运行、就绪、完成)
3、进程到达、服务、已用时间均为时间片
4、FCFS调度算法:按照进程到达时间,依次调度,每个进程结束后,调度下一个进程。
5、时间片轮转算法:每个进程完成一个时间片后,放弃处理机,转到就绪队列队尾(不考虑优先级)
6、动态优先级:每个进程完成一个时间片后,优先级减1,插入到就绪队列相关位置(队列头是优先级最高的进程),每次调度,选择优先级最高的队列运行。
实验代码
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef enum ProcessState{
Executing,
Ready,
Finish,
Unarrive
}STATE;
//进程三种状态,这里增加一种,表示虽然输入,但是还没有到达进入系统时刻typedef enum ProcessState{Executing, Ready, Finish, Unarrive}STATE;
typedef struct process_pcb
{
int ID; //进程标识
int priority; //进程优先数,值越大,优先级越高
int arrive_time; //进程到达时间,以时间片为单位
int service_time; //进程需要总的服务时间
int start_time; //进程开始执行时间
int end_time; //进程结束时间
int all_time; //进程仍然需要运行时间
int cpu_time; //进程已占用cpu时间
STATE state; //进程状态
}PCB;
//用于打印进程三种状态
const char* StateString[] = {"Executing", "Ready", "Finish", "--"};
//排序比较函数:按照进程到达时间升序排列
bool cmp_arrive_time(const PCB a, const PCB b);
//排序比较函数:按照进程优先数降序排序
bool cmp_priority(const PCB a, const PCB b);
void input_process(); //输入进程信息
int select_policy(); //选择进程调度策略
void print_all(int current); //打印所有进程信息
void FCFS(); //先来先服务算法
void round_robin(); //时间片轮转算法
void dynamic_prio(); //动态优先级算法
PCB *running_process = NULL;//当前运行任务
//进程到达队列,如进程还没到到达时间,则该进程仍然在到达队列中
vector<PCB> arrive_queue;
vector<PCB> ready_queue;//就绪队列
vector<PCB> finish_queue;//完成队列
int main()
{
printf("===================================================\n");
printf(" 操作系统进程调度模拟实验 \n");
printf("===================================================\n");
printf("\n");
input_process();
print_all(-1); //打印进程的初始状态
int policy = select_policy();
switch(policy)
{
case 1:
FCFS();
break;
case 2:
round_robin();
break;
case 3:
dynamic_prio();
break;
default:
FCFS();
break;
}
}
//按进程到达时间升序排列,先到达的排在队首
bool cmp_arrive_time(const PCB a, const PCB b)
{
return a.arrive_time < b.arrive_time;
}
//按进程优先级降序排列,优先级高的排在队首
//如优先级相同,先到的进程排在前面
bool cmp_priority(const PCB a, const PCB b)
{
if(a.priority != b.priority){
return a.priority > b.priority;
}
else{
return a.arrive_time < b.arrive_time;
}
}
//选择进程调度策略
int select_policy()
{
printf("\n请选择调度算法(输入、、选择):\n");
printf("1.先来先服务调度(FCFS) \n");
printf("2.时间片轮转调度(Round-Robin) \n");
printf("3.动态优先级调度(DynamicPriority) \n");
int n;
printf("请输入调度算法序号:");
while(scanf("%d",&n)){
if(n > 3 || n < 1){
printf("对不起,输入有误,请重新输入!\n");
}
else{
break;
}
}
return n;
}
//输入进程信息
void input_process()
{
int num;
printf("请输入进程数量:");
scanf("%d",&num);
PCB pro;
for(int i = 1; i <= num; i++){
printf("\n请输入第%d个进程的到达时间、服务时间及优先级(以空格隔开):\n",i);
scanf("%d%d%d",&pro.arrive_time,&pro.service_time,&pro.priority);
pro.ID = i;
pro.all_time = pro.service_time;
pro.cpu_time = 0;
pro.start_time = -1;//开始时间、结束时间默认为-1,表示尚未被调度过
pro.end_time = -1;
pro.state = Unarrive;//初始化为尚未进入到达
arrive_queue.push_back(pro);
}
//按照到达时间升序排队
sort(arrive_queue.begin(), arrive_queue.end(), cmp_arrive_time);
}
//打印单个进程的信息
void print_process(PCB* pro)
{
if(pro == NULL){
return;
}
printf("%4d%10d%10d%8d%10s", pro->ID, pro->arrive_time, pro->service_time, pro->priority, StateString[pro->state]);
if(pro->start_time == -1){//开始时间,结束时间,剩余时间
printf("%10s%10s%10s", "--", "--", "--");
}else{
if(pro->end_time == -1){
printf("%10d%10s%10d", pro->start_time, "--", pro->all_time);
}else{
printf("%10d%10d%10d", pro->start_time, pro->end_time, pro->all_time);
}
}
if(pro->state == Finish)//周转时间及带权周转时间
{
printf("%10d%10.2lf\n", pro->end_time - pro->arrive_time, (float)(pro->end_time - pro->arrive_time)/(float)pro->service_time);
}else{
printf("%10s%10s\n", "--", "--");
}
}
//打印所有进程的信息
void print_all(int current)
{
if(current == -1){
printf("\n进程初始状态:\n", current);
}else{
printf("\n当前时刻为:%d\n", current);
}
printf("进程号 到达时间 服务时间 优先级 状态 开始时间 结束时间 剩余时间 周转时间 带权周转时间\n");
//首先打印正在运行的进程
if(running_process != NULL){
print_process(running_process);
}
vector<PCB>::iterator it;
//然后打印就绪队列中的进程
for(it = ready_queue.begin(); it != ready_queue.end(); it ++){
print_process(&(*it));
}
//然后打印完成队列中的进程
for(it = finish_queue.begin(); it != finish_queue.end(); it ++){
print_process(&(*it));
}
//然后打印仍然在到达队列中的进程
for(it = arrive_queue.begin(); it != arrive_queue.end(); it ++){
print_process(&(*it));
}
}
//先来先服务算法
void FCFS()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while(1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if(!running_process && arrive_queue.empty() && ready_queue.empty()){
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while(!arrive_queue.empty()){
PCB pro = arrive_queue[0];
if(pro.arrive_time <= chip){
pro.state = Ready;
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}else{
break;
}
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if(need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
running_process->start_time = chip;
running_process->state = Executing;
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//FCFS当前任务运行到结束,才可能调度下一个任务
if(running_process){
running_process->end_time = running_process->start_time + running_process->service_time;
running_process->state = Finish;
running_process->cpu_time = running_process->service_time;
running_process->all_time = 0;
chip += running_process->service_time;
finish_queue.push_back(*running_process);//将完成任务放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}else{
chip += 1;
}
}
//所有任务全部完成后,打印一次
print_all(chip);
}
//时间片轮转算法
void round_robin()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while(1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if(!running_process && arrive_queue.empty() && ready_queue.empty()){
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while(!arrive_queue.empty()){
PCB pro = arrive_queue[0];
if(pro.arrive_time <= chip){
pro.state = Ready;
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}else{
break;
}
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if(need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
if(running_process->start_time == -1){//首次运行
running_process->start_time = chip;
}
running_process->state = Executing;
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//当前运行任务完成个时间片,判断该任务是否已经完成
if(running_process){
running_process->cpu_time += 1;
running_process->all_time -= 1;
if(running_process->all_time == 0){//任务运行结束
running_process->end_time = chip + 1;
running_process->state = Finish;
finish_queue.push_back(*running_process);//将其放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}else{//任务没有完成,如果就绪队列中仍有任务,则轮转调度,否则不调度(这里是一种调度的优化,避免重新调度开销)
if(!ready_queue.empty()){
running_process->state = Ready;
ready_queue.push_back(*running_process);//将其放回就绪队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}else{
need_schedule = false;
}
}
}
chip += 1;
}
//所有任务全部完成后,打印一次
print_all(chip);
}
//动态优先级算法
void dynamic_prio()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while(1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if(!running_process && arrive_queue.empty() && ready_queue.empty()){
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while(!arrive_queue.empty()){
PCB pro = arrive_queue[0];
if(pro.arrive_time <= chip){
pro.state = Ready;
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}else{
break;
}
}
if(!ready_queue.empty()){
//将就绪进程按照优先级降序排列
sort(ready_queue.begin(), ready_queue.end(), cmp_priority);
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if(need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
if(running_process->start_time == -1){//首次运行
running_process->start_time = chip;
}
running_process->state = Executing;
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//当前运行任务完成个时间片,判断该任务是否已经完成
if(running_process){
running_process->cpu_time += 1;
running_process->all_time -= 1;
if(running_process->all_time == 0){//任务运行结束
running_process->end_time = chip + 1;
running_process->state = Finish;
finish_queue.push_back(*running_process);//将其放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}else{//任务没有完成,如果就绪队列中仍有任务,且优先级大于或等于本任务的优先级,则轮转调度,否则不调度
if(running_process->priority > 1){
running_process->priority -= 1;//优先级最小为1
}
if(!ready_queue.empty() && ready_queue[0].priority >= running_process->priority){
running_process->state = Ready;
ready_queue.push_back(*running_process);//将其放回就绪队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}else{
need_schedule = false;
}
}
}
chip += 1;
}
//所有任务全部完成后,打印一次
print_all(chip);
}
实验结果