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

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

一、实验内容

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

二、实验目的

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

三、实验题目

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

 (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进程运行完成后,所有进程运行完成,按照流程图,处理机结束运行。

六、实验感悟



目录
相关文章
|
17天前
|
安全 前端开发 Android开发
探索移动应用与系统:从开发到操作系统的深度解析
在数字化时代的浪潮中,移动应用和操作系统成为了我们日常生活的重要组成部分。本文将深入探讨移动应用的开发流程、关键技术和最佳实践,同时分析移动操作系统的核心功能、架构和安全性。通过实际案例和代码示例,我们将揭示如何构建高效、安全且用户友好的移动应用,并理解不同操作系统之间的差异及其对应用开发的影响。无论你是开发者还是对移动技术感兴趣的读者,这篇文章都将为你提供宝贵的见解和知识。
|
19天前
|
存储 算法 调度
深入理解操作系统:进程调度的奥秘
在数字世界的心脏跳动着的是操作系统,它如同一个无形的指挥官,协调着每一个程序和进程。本文将揭开操作系统中进程调度的神秘面纱,带你领略时间片轮转、优先级调度等策略背后的智慧。从理论到实践,我们将一起探索如何通过代码示例来模拟简单的进程调度,从而更深刻地理解这一核心机制。准备好跟随我的步伐,一起走进操作系统的世界吧!
|
18天前
|
人工智能 搜索推荐 Android开发
移动应用与系统:探索开发趋势与操作系统演进####
本文深入剖析了移动应用开发的最新趋势与移动操作系统的演进历程,揭示了技术创新如何不断推动移动互联网生态的变革。通过对比分析不同操作系统的特性及其对应用开发的影响,本文旨在为开发者提供洞察未来技术方向的视角,同时探讨在多样化操作系统环境中实现高效开发的策略。 ####
18 0
|
1月前
|
消息中间件 算法 调度
深入理解操作系统:进程管理与调度
操作系统是计算机系统的核心,负责管理和控制硬件资源、提供用户接口以及执行程序。其中,进程管理是操作系统的重要组成部分,它涉及到进程的创建、调度、同步和通信等方面。本文将深入探讨进程管理的基本概念、进程调度算法以及进程间的同步和通信机制。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程管理的基本技能。
45 11
|
25天前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
操作系统作为计算机系统的核心,其进程管理和调度策略对于系统性能和用户体验至关重要。本文将通过直观的代码示例和浅显易懂的语言,带领读者了解操作系统如何有效管理进程以及常见的进程调度算法。我们将从进程的基本概念出发,逐步深入到进程状态、进程控制块(PCB)的作用,最后探讨不同的调度算法及其对系统性能的影响。无论您是初学者还是有一定基础的开发者,都能从中获得有价值的信息。
|
24天前
|
负载均衡 算法 调度
深入理解操作系统:进程管理与调度
在数字世界的心脏,操作系统扮演着至关重要的角色。它如同一位精明的指挥家,协调着硬件资源和软件需求之间的和谐乐章。本文将带你走进操作系统的核心,探索进程管理的艺术和调度策略的智慧。你将了解到进程是如何创建、执行和消亡的,以及操作系统如何巧妙地决定哪个进程应该在何时获得CPU的青睐。让我们一起揭开操作系统神秘的面纱,发现那些隐藏在日常计算背后的精妙机制。
|
27天前
|
测试技术 Android开发 开发者
移动应用与系统:涵盖移动应用开发、移动操作系统等相关话题####
本文深入探讨了移动应用开发的全过程,包括需求分析、设计、编码、测试以及发布等关键步骤。同时,还对当前主流的移动操作系统进行了简要介绍,并分析了它们之间的差异和各自的优势。通过实际案例,展示了移动应用开发的挑战与解决方案,旨在为读者提供一份全面的移动应用开发指南。 ####
|
26天前
|
调度 开发者
深入理解操作系统之进程调度
在计算机科学领域,操作系统是核心的一环,它管理着计算机硬件资源,并提供接口供上层软件运行。本文将通过深入浅出的方式,探讨操作系统中至关重要的一个概念——进程调度。我们将从基础理论出发,逐步展开讲解进程调度的原理和实现,并配以实际代码示例,旨在帮助读者更好地理解和掌握这一主题。文章不仅适合初学者建立基础,也适合有一定基础的开发者深化理解。
|
29天前
|
人工智能 Android开发 数据安全/隐私保护
移动应用与系统:探索现代移动应用开发及操作系统的演变与未来趋势###
本文旨在深入探讨现代移动应用开发及移动操作系统的演变历程,并分析其未来的发展趋势。通过梳理移动应用从早期的简单工具到如今的多功能平台的转变过程,以及主流移动操作系统如iOS和Android的发展路径,本文揭示了技术创新如何不断推动移动生态系统的进步。此外,文章还讨论了当前面临的挑战及潜在的解决方案,为开发者和研究人员提供有价值的参考。 ###
|
17天前
|
5G 数据安全/隐私保护 Android开发
移动应用与系统:探索开发趋势与操作系统革新####
本文深入剖析当前移动应用开发的最新趋势,涵盖跨平台开发框架的兴起、人工智能技术的融合、5G技术对移动应用的影响,以及即时应用的发展现状。随后,文章将探讨主流移动操作系统的最新特性及其对开发者社区的影响,包括Android的持续进化、iOS的创新举措及华为鸿蒙OS的崛起。最后,还将讨论移动应用开发中面临的挑战与未来的发展机遇,为读者提供全面而深入的行业洞察。 ####