操作系统原理实验2:进程调度(在Ubuntu虚拟机gcc编译环境下

简介: 操作系统原理实验2:进程调度(在Ubuntu虚拟机gcc编译环境下

实验目的与要求

通过一个简单的进程调度模拟程序的实现,加深对各种进程调度算法,进程切换的理解。

实验原理与内容

1、进程调度算法:采用动态最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)。

2、每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:

  1. 进程名----进程标示数ID;
  2. 优先数----Priority,优先数越大优先权越高;
  3. 到达时间----进程的到达时间为进程输入的时间;
  4. 进程还需要运行时间----AllTime,进程运行完毕AllTime =0;
  5. 已用CPU时间----CPUTime;
  6. 进程的阻塞时间StartBlock----表示当进程在运行StartBlock个时间片后,进程将进入阻塞状态;
  7. 进程的阻塞时间StartTime----表示当进程阻塞StartTime个时间片后,进程将进入就绪状态;
  8. 进程状态----State;
  9. 队列指针----Next,用来将PCB排成队列。

3、调度原则

  1. 进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间;
  2. 进程的运行时间以时间片为单位进行计算;
  3. 进程在就绪队列中带一个时间片,优先数加1;
  4. 每个进程的状态可以是就绪R(Ready)、运行R(Run)、阻塞B(Block)、或完成F(Finish)四种状态之一;
  5. 就绪进程获得CPU后都只能运行一个时间片,用已占用CPU时间加1来表示;
  6. 如果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减3,然后把它插入就绪队列等待CPU;
  7. 每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查;
  8. 重复以上过程,直到所要进程都完成为止。

老师给的代码(具有不少错误的):

#include<stdio.h>

#include<stdlib.h>

enum STATE{ Ready=1,Run,Block,Finish };

struct PCB{

int ID; //进程名

int Priority; //优先数

int Time; //到达时间

int AllTime; //进程还需要运行时间

int CPUTime; //已用CPU时间

int StartBlock; //进程的进入阻塞时间

int StartTime; //进程的等待阻塞时间

STATE State; //进程状态

PCB* Next; //队列指针

}*ready=NULL,*p;

void Sort(){

// 建立对进程进行优先级排列函数

PCB *first, *second;

int insert=0;

if(ready==NULL||(p->Priority>ready->Priority)) //优先级最大者,插入队首

{

p->Next=ready;

ready=p;

}

else // 进程比较优先级,插入适当的位置中

{

first=ready;

second=first->Next;

while(second!=NULL)

{

if(p->Priority>second->Priority) //若插入进程比当前进程优先数大

{ //插入到当前进程前面

p->Next=second;

first->Next=p;

second=NULL;

insert=1;

}

else // 插入进程优先数最低,则插入到队尾

{

first=first->Next;

second=second->Next;

}

}

if(insert==0) first->Next=p;

}

}

void Input() {

// 输入进程控制块信息

int i,num;

//clrscr(); /*清屏*/

printf("\n 请输入进程数量:");

scanf("%d",&num);

for(i=0;i<num;i++)

{

p=(PCB*)malloc(sizeof(PCB)); //动态生成

p->ID=i+1;

printf("\n 输入进程%d的信息:\n",p->ID);

printf("\n 程优先数:");

scanf("%d",&p->Priority);

printf("\n 进程需要运行时间:");

scanf("%d",&p->AllTime);  

p->Time=3*i;

p->CPUTime=0;

p->StartBlock=0;

p->StartTime=0;

p->State=Ready;

p->Next=NULL;

printf("\n");

Sort(); /* 调用sort函数*/

}

}

int Length()

{

int l=0; PCB* pr=ready;

while(pr!=NULL)

{

l++;

pr=pr->Next;

}

return(l);

}

void OutPut(PCB * pr) //显示当前进程

{

printf("\n ID \t state \t Priority \t ALLTime \t CPUTime \n");

printf("%d\t",pr->ID);

printf("%d\t",pr->State);

printf("%d\t",pr->Priority);

printf("%d\t",pr->AllTime);

printf("%d\t",pr->CPUTime);

printf("\n");

}

void Check() // 建立进程查看函数

{

PCB* pr;

printf("\n **** 当前正在运行的进程是:\n"); //显示当前运行进程 

OutPut(p);

pr=ready;

printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列状态

while(pr!=NULL)

{

OutPut(pr);

pr=pr->Next;

}

}

void Destroy() //建立进程撤消函数(进程运行结束,撤消进程)

{

printf("\n 进程 [%d] 已完成.\n",p->ID);

free(p);

}

void Running() // 建立进程就绪函数(进程运行时间到,置就绪状态

{

p->CPUTime++;

p->State=Run;

if(p->CPUTime==p->AllTime)

Destroy(); //调用Destroy函数

else

{

(p->Priority)--;

p->State=Ready;

Sort(); //调用sort函数

}

}

void main() //主函数

{

int len,h=0;

char ch;

Input();

len=Length();

while((len!=0)&&(ready!=NULL))

{

ch=getchar();

h++;

printf("\n 执行进程号:%d \n",h);

p=ready;

ready=p->Next;

p->Next=NULL;

p->State=Ready;

Check();

Running();

printf("\n 按任一键继续......");

ch=getchar();

}

printf("\n\n 进程已经完成.\n");

ch=getchar();

}

在老师代码中遇到的问题:

问题1:类型错误,定义进程状态的类型错误

 

解决:所以将STATE State;改为char state

问题2:队列指针错误类错误

 

解决方案:因为直接用gcc编译的代码,无法直接将pcb认为成一个类,所以将pcb* Next改为struct pcb* Next

问题3:因为直接用gcc编译的代码,无法直接将pcb认为成一个类,所以后面输入input函数的动态生成内存空间(p=(struct PCB *)malloc(sizeof(PCB));)会发生错误

 

解决方案:查阅很多资料后,发现只需要定义一下标识符的别名,然后进行使用就好,typedef struct是定义一个标识符及关键字的别名

所以将

struct PCB{

int ID; //进程名

int Priority; //优先数

int Time; //到达时间

int AllTime; //进程还需要运行时间

int CPUTime; //已用CPU时间

int StartBlock; //进程的进入阻塞时间

int StartTime; //进程的等待阻塞时间

STATE State; //进程状态

PCB* Next; //队列指针

}*ready=NULL,*p;

改为:

struct pcb{

int ID; //进程名

int Priority; //优先数

int Time; //到达时间

int AllTime; //进程还需要运行时间

int CPUTime; //已用CPU时间

int StartBlock; //进程的进入阻塞时间

int StartTime; //进程的等待阻塞时间

char State; //进程状态

struct pcb* Next; //队列指针

}*ready=NULL,*p;

typedef struct pcb PCB;

完善可用成功运行的代码:

#include<stdio.h>

#include<stdlib.h>

enum STATE{Ready=1,Run,Block,Finish };

struct pcb{

int ID; //进程名

int Priority; //优先数

int Time; //到达时间

int AllTime; //进程还需要运行时间

int CPUTime; //已用CPU时间

int StartBlock; //进程的进入阻塞时间

int StartTime; //进程的等待阻塞时间

char State; //进程状态

struct pcb* Next; //队列指针

}*ready=NULL,*p;

typedef struct pcb PCB;

void Sort(){

// 建立对进程进行优先级排列函数

PCB* first , * second;

int insert=0;

if(ready==NULL||(p->Priority>ready->Priority)) //优先级最大者,插入队首

{

p->Next=ready;

ready=p;

}

else // 进程比较优先级,插入适当的位置中

{

first=ready;

second=first->Next;

while(second!=NULL)

{

if(p->Priority>second->Priority) //若插入进程比当前进程优先数大

{ //插入到当前进程前面

p->Next=second;

first->Next=p;

second=NULL;

insert=1;

}

else // 插入进程优先数最低,则插入到队尾

{

first=first->Next;

second=second->Next;

}

}

if(insert==0) first->Next=p;

}

}

void Input() {

// 输入进程控制块信息

int i,num;

//clrscr(); /*清屏*/

printf("\n 请输入进程数量:");

scanf("%d",&num);

for(i=0;i<num;i++)

{

p=(struct PCB *)malloc(sizeof(PCB)); //动态生成

p->ID=i+1;

printf("\n 输入进程%d的信息:\n",p->ID);

printf("\n 进程优先数:");

scanf("%d",&p->Priority);

printf("\n 进程需要运行时间:");

scanf("%d",&p->AllTime);  

p->Time=3*i;

p->CPUTime=0;

p->StartBlock=0;

p->StartTime=0;

p->State=Ready;

p->Next=NULL;

printf("\n");

Sort(); /* 调用sort函数*/

}

}

int Length()

{

int l=0;

     PCB* pr=ready;

while(pr!=NULL)

{

l++;

pr=pr->Next;

}

return(l);

}

void OutPut(PCB * pr) //显示当前进程

{

printf("\n ID \t state \t Priority \t ALLTime \t CPUTime \n");

printf("%d\t",pr->ID);

printf("%d\t",pr->State);

printf("%d\t",pr->Priority);

printf("%d\t",pr->AllTime);

printf("%d\t",pr->CPUTime);

printf("\n");

}

void Check() // 建立进程查看函数

{

PCB* pr;

printf("\n **** 当前正在运行的进程是:\n"); //显示当前运行进程

OutPut(p);

pr=ready;

printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列状态

while(pr!=NULL)

{

OutPut(pr);

pr=pr->Next;

}

}

void Destroy() //建立进程撤消函数(进程运行结束,撤消进程)

{

printf("\n 进程 [%d] 已完成.\n",p->ID);

free(p);

}

void Running() // 建立进程就绪函数(进程运行时间到,置就绪状态

{

p->CPUTime++;

p->State=Run;

if(p->CPUTime==p->AllTime)

Destroy(); //调用Destroy函数

else

{

(p->Priority)--;

p->State=Ready;

Sort(); //调用sort函数

}

}

void main() //主函数

{

int len,h=0;

char ch;

Input();

len=Length();

while((len!=0)&&(ready!=NULL))

{

ch=getchar();

h++;

printf("\n 执行进程号:%d \n",h);

p=ready;

ready=p->Next;

p->Next=NULL;

p->State=Ready;

Check();

Running();

printf("\n 按任一键继续......");

ch=getchar();

}

printf("\n\n 进程已经完成.\n");

ch=getchar();

}


相关文章
|
1月前
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
3天前
|
JSON Ubuntu 开发者
ubuntu 22安装lua环境&&编译lua cjson模块
通过上述步骤,可以在 Ubuntu 22.04 系统上成功安装 Lua 环境,并使用 LuaRocks 或手动编译的方式安装 lua-cjson 模块。本文详细介绍了每一步的命令和操作,确保每一步都能顺利完成,适合需要在 Ubuntu 系统上配置 Lua 开发环境的开发者参考和使用。
29 13
|
25天前
|
存储 算法 调度
深入理解操作系统:进程调度的奥秘
在数字世界的心脏跳动着的是操作系统,它如同一个无形的指挥官,协调着每一个程序和进程。本文将揭开操作系统中进程调度的神秘面纱,带你领略时间片轮转、优先级调度等策略背后的智慧。从理论到实践,我们将一起探索如何通过代码示例来模拟简单的进程调度,从而更深刻地理解这一核心机制。准备好跟随我的步伐,一起走进操作系统的世界吧!
|
3天前
|
Java Linux API
[JavaEE]———进程、进程的数据结构、进程的调度
操作系统,进程任务,PCB,PID,内存指针,文件描述符表,进程的调度,并发编程,状态,优先级,记账信息,上下文
|
1月前
|
消息中间件 算法 调度
深入理解操作系统:进程管理与调度
操作系统是计算机系统的核心,负责管理和控制硬件资源、提供用户接口以及执行程序。其中,进程管理是操作系统的重要组成部分,它涉及到进程的创建、调度、同步和通信等方面。本文将深入探讨进程管理的基本概念、进程调度算法以及进程间的同步和通信机制。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程管理的基本技能。
49 11
|
1月前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
操作系统作为计算机系统的核心,其进程管理和调度策略对于系统性能和用户体验至关重要。本文将通过直观的代码示例和浅显易懂的语言,带领读者了解操作系统如何有效管理进程以及常见的进程调度算法。我们将从进程的基本概念出发,逐步深入到进程状态、进程控制块(PCB)的作用,最后探讨不同的调度算法及其对系统性能的影响。无论您是初学者还是有一定基础的开发者,都能从中获得有价值的信息。
|
1月前
|
负载均衡 算法 调度
深入理解操作系统:进程管理与调度
在数字世界的心脏,操作系统扮演着至关重要的角色。它如同一位精明的指挥家,协调着硬件资源和软件需求之间的和谐乐章。本文将带你走进操作系统的核心,探索进程管理的艺术和调度策略的智慧。你将了解到进程是如何创建、执行和消亡的,以及操作系统如何巧妙地决定哪个进程应该在何时获得CPU的青睐。让我们一起揭开操作系统神秘的面纱,发现那些隐藏在日常计算背后的精妙机制。
|
1月前
|
调度 开发者
深入理解操作系统之进程调度
在计算机科学领域,操作系统是核心的一环,它管理着计算机硬件资源,并提供接口供上层软件运行。本文将通过深入浅出的方式,探讨操作系统中至关重要的一个概念——进程调度。我们将从基础理论出发,逐步展开讲解进程调度的原理和实现,并配以实际代码示例,旨在帮助读者更好地理解和掌握这一主题。文章不仅适合初学者建立基础,也适合有一定基础的开发者深化理解。
|
1月前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第40天】在数字世界中,操作系统是连接硬件与软件的桥梁,它管理着计算机资源和提供用户服务。本文将深入探讨操作系统中的进程管理与调度策略,揭示它们如何协调多任务运行,保证系统高效稳定运作。通过代码示例,我们将展示进程创建、执行以及调度算法的实际应用,帮助读者构建对操作系统核心机制的清晰认识。
|
1月前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第34天】本文旨在探讨操作系统中至关重要的一环——进程管理及其调度策略。我们将从基础概念入手,逐步揭示进程的生命周期、状态转换以及调度算法的核心原理。文章将通过浅显易懂的语言和具体实例,引导读者理解操作系统如何高效地管理和调度进程,保证系统资源的合理分配和利用。无论你是初学者还是有一定经验的开发者,这篇文章都能为你提供新的视角和深入的理解。
45 3