操作系统实验一 处理器调度/调度系统

简介: 操作系统实验一 处理器调度/调度系统

一、实验内容

 选择一个调度算法,实现处理器调度。

二、实验目的

 在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪状态进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实验模拟在单处理器情况下处理器调度,帮助学生加深了解处理器调度的工作。

三、实验题目

 设计一个按优先数调度算法实现处理器调度的进程。

 (1)假定系统有5个进程,每一个进程用一个进程控制块PCB来代表。进程控制块的格式为:

进程名
指针
要求运行时间
优先数
状态

 其中,

 进程名——作为进程的标识,假设五个进程的进程名分别是P1,P2,P3,P4,P5。

 指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块首地址,最后一个进程中的指针为“0”。

 要求运行时间——假设进程需要运行的单位时间数。

 优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。

 状态——可假设有两种状态,“就绪”状态和“结束“状态,五个进程的初始状态都为“就绪”状态,用“R”表示,当一个进程运行结束后,它的状态变为“结束”,用“E”表示。

 (2)在每次运行你所设计的处理器调度程序之前,为每个进程任意地确定它的“优先数”和“要求运行时间”。

 (3)为了调度方便,把五个进程按给定的优先数从大到小连成队列,用一单元指出队首进程,用指针指出队列的连接情况。例:

 (4)处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行次优先数就减1。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:优先数-1、要求运行时间-1,来模拟进程的一次运行。提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。

 (5)进程运行一次后,若要求运行时间≠0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改为“结束”,且退出队列。

 (6)若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。

 (7)在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。

  (8)为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。

四、实验报告

(1)实验题目

见上文

(2)程序中使用的数据结构及符号说明

  系统有5个进程,用PCB结构体表示,如图2。这5个进程都存放在一个数组中。但PCB结构体自带next指针,所以PCB结构体也是自带了头指针的、用链表实现的队列结构。队列头指针为head。PCB的name表示进程名,reqtime表示要求运行时间,rank表示优先级,state表示状态。

  需要说明的是,实验指导书并未规定进程的优先级是否能够为负数。

  State字符有两种值,R表示正在运行,E表示已经结束,不需要加入就绪进程的队列。

class PCB{//进程块
public:
  PCB* next;//指针
  string name;//进程名
  int reqtime;//要求运行时间
  int rank;//优先级
  char state;//状态,R running E end
};
PCB* head;
PCB* runningprocess;
PCB P[N];

  在对PCB指针进行“比较”时,需要比较其优先级大小,也需要比较剩余运行时间。

bool cmprank(PCB a, PCB b){//优先级从大到小比较函数
  return a.rank > b.rank;
}
bool cmpreqtime(PCB a, PCB b){
  return a.reqtime > b.reqtime;
}

  利用cnt变量进行计数,记录当前有几个变量没有运行结束。

int cnt=0;

(3)流程图

(4)打印一份源程序并附上注释

1.算法说明

  在main函数中,开始时运行init()置进程数为0,队列head指针为空,正在运行进程为空。运行input()输入进程,输入进程名、优先级、时间,并置状态为“就绪”。将各进程按照优先级排序后,形成队列。打印程序运行时的初值。运行run()函数,对cpu的工作进行模拟。

  初始化代码如下

void init() {
  head = NULL;//进程队列队首
  runningprocess = NULL;//正在运行的进程
  cnt = 0;//进程数
}

  Main函数中,初始化完成、输入完成后,就能模拟cpu进行处理、调度、工作了。

  模拟cpu工作时,每次选优先数最大的一个进程,将其运行一个时间单位并降低优先级后再打印各进程状态。运行完成后对进程按优先数和时间排序,对优先级进行排序时直接调用c++ stl中的algorithm库的sort,并重新按优先级对进程队列进行连接。时间为0的自动退出队列。如此循环直到所有进程运行完成,如流程图所示。

void run(PCB* head, PCB* runningprocess){
  if (cnt == 0) {
    cout << "\n******every pcb ends******\n";
    return;
  }
  cout << "\n##########process" << runningprocess->name << "running##########\n" ;
  runningprocess->reqtime--;//剩余运行时间-1
  runningprocess->rank--;//优先级-1  
  cout << "-----------------every pcb status------------------";
  for (int i = 0; i < cnt; i++)  //显示已就绪进程
    print(&head[i]);
  cout << "\n---------------------------------------------------\n";
  if (runningprocess->reqtime == 0){//某个进程运行结束,打印提示信息
    runningprocess->state = 'E';//赋予结束状态E
    print(runningprocess);
    sort(head, head + cnt, cmpreqtime);//按照进程剩余时间排序,使该结束的进行排在队尾
    cnt--;
  }
  sort(head, head + cnt, cmprank);//按照进程优先级排序
  for (int i = 1; i < cnt; i++) //改变指针位置,当一个进程运行结束后退出队列
    head[i - 1].next = &head[i];
  runningprocess = head;//下一次运行的进程为队首进程
  run(head, runningprocess);//递归调用进程运行函数
}

2.完整代码

#include<iostream>
#include<string>
#include<iomanip>
#include<algorithm>
#define N 5
using namespace std;
class PCB{//进程块
public:
  PCB* next;//指针
  string name;//进程名
  int reqtime;//要求运行时间
  int rank;//优先级
  char state;//状态,R running E end
};
PCB* head;
int cnt=0;
PCB* runningprocess;
PCB P[N];
bool cmprank(PCB a, PCB b){//优先级从大到小比较函数
  return a.rank > b.rank;
}
void print(PCB* pcb) {
  cout << "\nprocess name " << pcb->name <<endl;
  cout << "remaining running time " << pcb->reqtime <<endl;
  cout << "priority rank: " << pcb->rank <<endl;
  cout << "status: " << pcb->state<<endl;
}
bool cmpreqtime(PCB a, PCB b){
  return a.reqtime > b.reqtime;
}
void run(PCB* head, PCB* runningprocess){
  if (cnt == 0) {
    cout << "\n******every pcb ends******\n";
    return;
  }
  cout << "\n##########process" << runningprocess->name << "running##########\n" ;
  runningprocess->reqtime--;//剩余运行时间-1
  runningprocess->rank--;//优先级-1  
  cout << "-----------------every pcb status------------------";
  for (int i = 0; i < cnt; i++)  //显示已就绪进程
    print(&head[i]);
  cout << "\n---------------------------------------------------\n";
  if (runningprocess->reqtime == 0){//某个进程运行结束,打印提示信息
    runningprocess->state = 'E';//赋予结束状态E
    print(runningprocess);
    sort(head, head + cnt, cmpreqtime);//按照进程剩余时间排序,使该结束的进行排在队尾
    cnt--;
  }
  sort(head, head + cnt, cmprank);//按照进程优先级排序
  for (int i = 1; i < cnt; i++) //改变指针位置,当一个进程运行结束后退出队列
    head[i - 1].next = &head[i];
  runningprocess = head;//下一次运行的进程为队首进程
  run(head, runningprocess);//递归调用进程运行函数
}
void init() {
  head = NULL;//进程队列队首
  runningprocess = NULL;//正在运行的进程
  cnt = 0;//进程数
}
void input() {
  for (int i = 0; i < N; i++)//输入各进程状态
  {
    cout << "\nplease input the " << i + 1 << "th process name :\n";
    cin >> P[i].name;
    cout << "\nplease input the rank of the process\n";
    cin >> P[i].rank;
    cout << "\nplease input the required time of the process\n";
    cin >> P[i].reqtime;
    P[i].state = 'R';//初始赋予就绪状态Running
    P[i].next = NULL;//进程指针初始化为空指针
    cnt++;
  }
}
int main(){
  init();
  input();
  sort(P, P + cnt, cmprank);//按照进程优先级排序
  for (int i = 1; i < cnt; i++)//对各指针赋值,形成队列
    P[i - 1].next = &P[i];
  head = &P[0];//头指针赋值
  runningprocess = &P[0];//正在运行的进程赋值
  cout << "\n---------------every pcb init status----------------\n";//打印各进程初始状态
  for (int i = 0; i < cnt; i++)
    print(&P[i]);
  cout << "\n---------------------------------------------------\n";
  run(head, runningprocess);//进程运行
  system("pause");
  return 0;
}

五、运行结果

  说明:初始时输入a进程剩余运行时间2,优先数1。设置b进程剩余运行时间3,优先数5。设置c进程剩余运行时间1,优先数3。设置d进程剩余运行时间2,优先数4。设置e进程剩余运行时间4,优先数2。

在对各进程初始化并连接成队列后,队头指针指向的第一个进程为优先级最大的b进程,第二个进程为d进程,第三个进程为c进程,第四个进程为e进程,第五个进程为a进程。

 初始时选择优先数最大的b进程运行,将其优先数、运行时间-1,如图6所示。在运行后,将其重新插入队列。

 因为b的优先数仍然最大,所以继续运行b进程。在运行后,将其重新插入队列,并按优先数将进程重新排序。

 此时优先数最大的进程为d进程,优先数为4,所以选择运行d进程。在运行后,将其重新插入队列。

 此时优先数最大的进程仍然为d进程,优先数为3,所以选择运行d进程。在运行后,检测到d进程剩余运行时间为0,将其状态置为“E”(完成),并将其退出队列。

 剩下的进程中b进程优先数最大,将其运行完成后检测到剩余时间为0,也将其退出队列,并置其状态为“完成”。

 剩下的进程中c进程优先数最大,将其运行完成后检测到剩余时间为0,也将其退出队列,并置其状态为“完成”。

 剩下的进程中e进程优先数最大,将其运行一次后没有运行完成,运行第二次后仍然没有运行完成,且优先数小于另一个剩下的进程a进程。

 a进程优先级最大,将其运行一次后优先级仍然最大,将其运行第二次后运行完成,置状态为“E”,退出队列。

 队列中只剩下一个进程e进程,将其剩余的时间运行完。由于实验指导书并未规定优先数是否允许为负数,这里每次运行完成时仍然扣除优先级并可以将优先级扣成负数。e进程运行完成后,所有进程运行完成,按照流程图,处理机结束运行。

六、实验感悟



目录
打赏
0
0
0
0
54
分享
相关文章
zabbix7.0.9安装-以宝塔安装形式-非docker容器安装方法-系统采用AlmaLinux9系统-最佳匹配操作系统提供稳定运行环境-安装教程完整版本-优雅草卓伊凡
zabbix7.0.9安装-以宝塔安装形式-非docker容器安装方法-系统采用AlmaLinux9系统-最佳匹配操作系统提供稳定运行环境-安装教程完整版本-优雅草卓伊凡
93 30
使用阿里云操作系统控制台巧解调度抖动
阿里云操作系统控制台是一站式云服务器管理平台,提供性能监控、故障诊断、日志分析、安全管理和资源调度等功能。用户可实时查看CPU、内存等使用情况,快速定位并解决调度抖动等问题。智能诊断工具自动生成优化建议,简化运维流程,降低技术门槛。尽管部分功能仍在优化中,但整体上显著提升了云服务器管理的效率和稳定性。
54 15
操作系统控制台-健康守护我们的系统
阿里云操作系统控制平台作为新一代云端服务器中枢平台,通过创新交互模式重构主机管理体验。用户可通过API、SDK、CLI等方式进行系统管理,采用图形化控制替代传统命令行操作,集智能运维、集群协调、生态扩展于一体,显著提升企业级IT设施管理效能。通过此平台,用户可以轻松实现运维监控、智能助手、扩展插件管理及订阅服务等功能,大幅降低运维复杂度,提高管理效率。
50 11
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
83 5
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
209 23
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
220 2
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
tauri2-vue3-macos首创跨平台桌面OS系统模板
自研Tauri2.0+Vite6+Pinia2+Arco-Design+Echarts+sortablejs桌面端OS管理平台系统。提供macos和windows两种桌面风格模式、自研拖拽式栅格引擎、封装tauri2多窗口管理。
253 3
探索移动应用与系统:从开发到操作系统的深度解析
在数字化时代的浪潮中,移动应用和操作系统成为了我们日常生活的重要组成部分。本文将深入探讨移动应用的开发流程、关键技术和最佳实践,同时分析移动操作系统的核心功能、架构和安全性。通过实际案例和代码示例,我们将揭示如何构建高效、安全且用户友好的移动应用,并理解不同操作系统之间的差异及其对应用开发的影响。无论你是开发者还是对移动技术感兴趣的读者,这篇文章都将为你提供宝贵的见解和知识。
深入理解操作系统:进程调度的奥秘
在数字世界的心脏跳动着的是操作系统,它如同一个无形的指挥官,协调着每一个程序和进程。本文将揭开操作系统中进程调度的神秘面纱,带你领略时间片轮转、优先级调度等策略背后的智慧。从理论到实践,我们将一起探索如何通过代码示例来模拟简单的进程调度,从而更深刻地理解这一核心机制。准备好跟随我的步伐,一起走进操作系统的世界吧!
移动应用与系统:探索开发趋势与操作系统演进####
本文深入剖析了移动应用开发的最新趋势与移动操作系统的演进历程,揭示了技术创新如何不断推动移动互联网生态的变革。通过对比分析不同操作系统的特性及其对应用开发的影响,本文旨在为开发者提供洞察未来技术方向的视角,同时探讨在多样化操作系统环境中实现高效开发的策略。 ####
52 0

热门文章

最新文章