当前位置: 首页 > article >正文

模拟进程状态转换

模拟进程状态转换

目录

  • 模拟进程状态转换
  • 一、实验目的
  • 二、实验内容
  • 三、代码:
  • 总结

一、实验目的

通过实验理解进程基本概念、状态转换及其控制。

二、实验内容

利用高级语言编写程序,模拟进程状态转换的过程。
进程的主要状态:就绪、运行、阻塞、终止,状态之间的转换如下图所示:
在这里插入图片描述

实现提示:
(1)采用进程控制块(PCB)描述一个进程的所有信息包括:进程标识符、处理机状态、进程调度信息以及控制信息,它是系统感知进程存在的唯一标志,进程与 PCB是一一对应的。
(2)对PCB 中的内容在此可做一些简化处理,只包括:进程标识符(内部标识符、外部标识符)、当前状态(“就绪”,“阻塞”,“执行”和“终止”)、要求运行的时间片数、优先级等。
(3)模拟过程
 按优先级高低对进程进行调度,每个进程可有四个状态,即:“就绪”,“阻塞”,“执行”和“终止”(假设优先数越大优先级越高,以及进程的初始状态为就绪状态)。
 为便于处理,应该随机地赋予所有进程各自的“优先级”和“要求运行的时间片数”,由用户给定。
 程序中共设 3 个队列:就绪队列,阻塞队列和终止队列。
 按优先级调度时,进程每运行一次,优先级降低一位,要求的时间片数减 1,如果要求的时间片数为零了,则将其加入终止队列。否则,将其按照优先级的次序重新加入就绪队列。
 要求的时间片数为零了,则将其加入终止队列。否则,将其按照优先级的次序重新加入就绪队列。
 进程运行过程中,遇到阻塞时,将该进程加入阻塞队列。(通过随机函数得到随机数,满足某种情况则使之加入到阻塞队列,或人为设置是否阻塞)。
 重复调度,直到就绪队列中所有进程全部运行结束。
(4)主要功能模块 (参考)
 初始化进程:初始化进程的基本数据
 新进程插入就绪队列:向就绪队列插入进程(按优先级排序)
 调度:从就绪队列中选取一进程运行一个时间片
 阻塞:将被阻塞的执行进程放入阻塞队列
 唤醒:唤醒阻塞队列中的进程
 终止:完成的进程放入消亡队列
 显示:输出各队列中进程的所有信息,包括正在执行的进程
(5)输入/输出
 输入要求:进程数以及每个进程的标识符(按顺序数字编号)、当前状态(默认为“就绪”)、要求运行的时间片数、初始优先级。(要能随时添加新进程)
 输出要求:每次进程状态发生转换时,输出各队列进程的信息。

三、代码:

/*
* 作者:
功能:模拟进程状态转换(进程数范围:1-10)
4个PCB状态标识常量:1.就绪Ready、2.运行Running、3.阻塞Block、4.终止Terminate
用Run()函数去模拟的CPU的run:所以Run函数应包含以下情况的处理(即,4种队列对应的处理情况):(1)就绪队列(为了方便找最大优先级,当然用priority_queue更方便,但我采用更熟悉的链表结构):就绪_1->就绪_1就绪_1->运行_2(2)运行队列运行_2->就绪_1运行_2->运行_2运行_2->阻塞_3运行_2->终止_4(3)阻塞队列(唤醒概率:1/8、被阻塞概率:1/4)阻塞_3->唤醒->就绪_1阻塞_3->唤醒->运行_1,(当就绪、运行队列为空时的情况,跳过进入就绪,直接唤醒到运行)阻塞_3->阻塞_3//唤醒概率没有满足的时候(4)终止队列:对终止队列里的进程不必要进行处理
*/#include <iostream>
#include <cstdlib>
#include<queue>
#include <windows.h>
using namespace std;
enum State {Ready,Running,BlockForIO,Terminate
};
struct PCB {int id = 0;int priority = 0;//初始化进程时,随机分配,抢占式优先级分配int timeslice = 0;//初始化进程时,随机分配State state = Ready;//假设各进程满足除CPU外一切资源,初始状态为就绪PCB* next=NULL;
};
PCB* head=NULL;
queue<PCB*> runningQueue, blockQueueForIO, terminateQueue;
int blockedProbability;
void InitPCB();
PCB* FindMaxPriority();
void DeletePCB(int id);
void Run();
void	PrintPCB();
void Display_TerminateQueue();
void Display_BlockQueueForIO();
void Display_RunningQueue();
void Display_Ready();
void InsertHead(PCB* p);void InitPCB() {srand((unsigned)time(NULL));int processNumber=rand()%10+1;//随机进程个数范围:1-10PCB* p=NULL;PCB* q=NULL;for (int i = 0; i < processNumber; i++) {q=new PCB;q->id = i+1;q->priority = rand() % 30 + 1;//优先级范围,为了显示效果更好,使优先级范围小一点q->state = Ready;q->timeslice = rand() % 10+1;//同理if (i == 0) {head = q;p= q;}else {p->next=q;p = p->next;}}
}
PCB* FindMaxPriority() {PCB* p = head;PCB* q =NULL;int max_priority = 0;if (head == NULL)return NULL;while (p) {if (p->priority > max_priority) {q = p;max_priority = p->priority;}p = p->next;}return q;
}
void DeletePCB( int id) {PCB* p=head;PCB* q=p->next;if (p->id == id) {p->next = NULL;head = q;}else {while (q->id!=id) {p = p->next;q = p->next;}p->next = q->next;q->next = NULL;}
}void Run() {srand((unsigned)time(NULL));PCB* p=NULL;PCB* q= FindMaxPriority();/*假设:当上一次运行完成时时,cpu才会有空去(找可运行性的就绪状态进程)或者(检查唤醒条件是否满足也可以说去检查是否有唤醒信号,所以应放在此位置)注意:之所以先去检查唤醒而不是去找可运行性的就绪状态进程(即以下代码的顺序问题),是为了避免当所有可执行进程执行完了才去唤醒操作,不符合现实*/if (!blockQueueForIO.empty()) {//理论上我认为,因为在多次频繁检查IO占用情况时,IO一段时间都是被占用的,被唤醒的概率会比阻塞概率小int awakenedProbability = rand() % 8 + 1;//唤醒概率:1/8if (awakenedProbability == 4) {p = blockQueueForIO.front();blockQueueForIO.pop();p->state = Ready;InsertHead(p);}}if (runningQueue.empty()) {if (head!=NULL) {q->state = Running;DeletePCB(q->id);runningQueue.push(q);}else {//当运行队列、就绪队列为空时,此时资源一定不会占用,这也是唤醒概率的弊端,直接进入运行队列if (!blockQueueForIO.empty()) {p = blockQueueForIO.front();blockQueueForIO.pop();p->state = Running;runningQueue.push(p);//此时阻塞也不可能发生blockedProbability = 0;}else {return;}}}else {/*运行队列里的进程一定是可以执行的,而且在函数开头,此进程一定打印过,不会出现刚调入到运行队列还没有打印就被放入阻塞队列的的情况,由于当运行队列里的进程下个时间段可以执行时,再考虑它会不会阻塞*/blockedProbability = rand() % 4 + 1;//被阻塞概率:1/4//如果运行队列为空,即使达到阻塞概率也不可能会阻塞if (blockedProbability == 2&&head!=NULL) {p=runningQueue.front();runningQueue.pop();p->state = BlockForIO;blockQueueForIO.push(p);q->state = Running;DeletePCB(q->id);runningQueue.push(q);}p=runningQueue.front();p->timeslice -= 1;p->priority -= 1;if (p->timeslice < 1) {runningQueue.pop();p->state = Terminate;terminateQueue.push(p);if (q) {DeletePCB(q->id);q->state = Running;runningQueue.push(q);}}else if (q) {//若就绪队列没进程,一定不会阻塞并且当前进程也不会进入就绪队列,所以当就绪队列有进程是时,凭概率设置阻塞//当优先级不是最高时,当前进程一定会下台,所以下次也一定没有它运行的机会,阻塞的意义:当下次还有运行的机会时,给他阻塞,剥夺他运行的机会if (p->priority < q->priority) {runningQueue.pop();p->state = Ready;InsertHead(p);q->state = Running;DeletePCB(q->id);runningQueue.push(q);}}}PrintPCB();cout << endl << endl<<endl<<endl;Run();
}
void InsertHead(PCB* p) {p->next = head->next;head->next = p;
}
void Display_Ready() {PCB* p = head;while (p) {cout << "ID:	" << p->id << "		Priority:	" << p->priority << "		Timeslice:		" << p->timeslice << endl;p = p->next;}
}
void Display_RunningQueue() {if (!runningQueue.empty()) {PCB* t = runningQueue.front();cout << "ID:	" << t->id << "		Priority:	" << t->priority << "		Timeslice:		" << t->timeslice << endl;}
}
void Display_BlockQueueForIO() {PCB* tempPCBArray[10];int n = 0;PCB* t;if (!blockQueueForIO.empty()) {while (!blockQueueForIO.empty()) {t = blockQueueForIO.front();tempPCBArray[n] = t;n++;cout << "ID:	" << t->id << "		Priority:	" << t->priority << "		Timeslice:		" << t->timeslice << endl;blockQueueForIO.pop();}for (int i = 0; i < n; i++) {blockQueueForIO.push(tempPCBArray[i]);}}
}
void Display_TerminateQueue() {PCB* tempPCBArray[10];int n = 0;PCB* t;if (!terminateQueue.empty()) {while (!terminateQueue.empty()) {t = terminateQueue.front();tempPCBArray[n] = t;n++;cout << "ID:	" << t->id << "		Priority:	" << t->priority << "		Timeslice:		" << t->timeslice << endl;terminateQueue.pop();}for (int i = 0; i < n; i++) {terminateQueue.push(tempPCBArray[i]);}}
}
void	PrintPCB() {cout << "就绪队列:" << endl; Display_Ready(); cout << endl;cout << "运行队列:"<<endl; Display_RunningQueue(); cout << endl;cout << "IO阻塞队列:" << endl; Display_BlockQueueForIO(); cout << endl;cout << "终止队列:" << endl; Display_TerminateQueue(); cout << endl;
}int main() {InitPCB();Run();return 0;
}

总结

以上代码仍然有好多改进之处(代码冗余部分我就懒得改了),出于老师的要求程度和时间考虑,就这么写吧。转载请注明出处。

http://www.lryc.cn/news/2416322.html

相关文章:

  • 谦卑若愚,好学若饥(Stay Hungry,Stay Foolish)
  • 移远通信 4G模组 EC801E 降本之作!
  • css 样式之 filter 滤镜属性 用法与示例
  • 迅雷下载开放引擎
  • *** buffer overflow detected ***异常
  • TCP/IP协议-传输层
  • 操作系统课后习题
  • 30 秒看懂,如何建立一个免费的个人主页
  • C#中Session的用法详细介绍
  • 搭建本地的Web服务器
  • flex布局和响应式布局
  • 李开复写给中国学生的七封信之给中国学生的第四封信——大学四年应是这样度过的...
  • 2024年最新程序员首选编程电脑【火爆来袭】_程序员使用的笔记本显卡,2024年最新阿里P8大佬亲自讲解
  • 2015 史考特(Scottrade)开户指南 + 招商银行香港一卡通汇款【图文教程】
  • socket实现简单的Web服务器
  • UltraEdit的注册码
  • 用ghost备份和还原Linux系统(一)
  • 美国团购网站Groupon的盈利模式
  • 4种网游外挂制作方法
  • 名片中头衔的英语称呼翻译
  • commons-fileupload实现文件上传,可多文件上传和实现进度条
  • ASP.NET Core MVC 项目的创建(超详细教程)
  • qq降龙电脑版_遨游中国全版本优瑞整合版
  • 计算机组成原理菊花链是什么,计算机组成原理篇
  • 数据库基础(超详细版)
  • Maven入门:使用Nexus搭建Maven私服及上传下载jar包
  • 浅谈ViewState
  • 【C语言】 基础知识入门
  • 用百度搜索SB,为什么是google排第一?
  • 计算机硬件主板各部分内部结构,电脑主板各个模块介绍与原理解读