操作系统原理实验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();

}


相关文章
|
6月前
|
Ubuntu 开发工具
Ubuntu 22.04 aarch64版本操作系统下编译ZLMediaKit教程
通过上述步骤,你可以在Ubuntu 22.04 aarch64版本上成功编译ZLMediaKit,这是一个相对简单而直接的过程,但可能会遇到一些需要根据具体系统环境和要求调整的地方。
878 0
|
9月前
|
Ubuntu 虚拟化 Windows
无影云电脑选择哪个操作系统Windows server 2019还是Ubuntu?
在选择阿里云无影云电脑的操作系统时,Windows Server 2019 和 Ubuntu 各有优势。Windows适合依赖微软生态的企业级应用,提供图形化界面和高安全性;Ubuntu则轻量、经济,适合开源工具链和容器化部署。根据应用场景、资源占用、安全性、开发效率及成本考量,选择最适合的系统。条件允许下,可采用混合方案满足多样化需求。
|
8月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
264 0
|
12月前
|
Web App开发 安全 Linux
【独家揭秘2025】VMware Workstation Pro虚拟机:免费安装教程大放送,一键解锁操作系统模拟神器!
VMware Workstation Pro 是由威睿(VMware)公司开发的一款功能强大的桌面虚拟化软件,允许用户在同一台物理计算机上同时运行多个操作系统,如Windows、..
1276 2
【独家揭秘2025】VMware Workstation Pro虚拟机:免费安装教程大放送,一键解锁操作系统模拟神器!
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
365 6
|
消息中间件 算法 调度
深入理解操作系统:进程管理与调度
操作系统是计算机系统的核心,负责管理和控制硬件资源、提供用户接口以及执行程序。其中,进程管理是操作系统的重要组成部分,它涉及到进程的创建、调度、同步和通信等方面。本文将深入探讨进程管理的基本概念、进程调度算法以及进程间的同步和通信机制。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程管理的基本技能。
223 11
|
存储 算法 调度
深入理解操作系统:进程调度的奥秘
在数字世界的心脏跳动着的是操作系统,它如同一个无形的指挥官,协调着每一个程序和进程。本文将揭开操作系统中进程调度的神秘面纱,带你领略时间片轮转、优先级调度等策略背后的智慧。从理论到实践,我们将一起探索如何通过代码示例来模拟简单的进程调度,从而更深刻地理解这一核心机制。准备好跟随我的步伐,一起走进操作系统的世界吧!
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
操作系统作为计算机系统的核心,其进程管理和调度策略对于系统性能和用户体验至关重要。本文将通过直观的代码示例和浅显易懂的语言,带领读者了解操作系统如何有效管理进程以及常见的进程调度算法。我们将从进程的基本概念出发,逐步深入到进程状态、进程控制块(PCB)的作用,最后探讨不同的调度算法及其对系统性能的影响。无论您是初学者还是有一定基础的开发者,都能从中获得有价值的信息。
|
负载均衡 算法 调度
深入理解操作系统:进程管理与调度
在数字世界的心脏,操作系统扮演着至关重要的角色。它如同一位精明的指挥家,协调着硬件资源和软件需求之间的和谐乐章。本文将带你走进操作系统的核心,探索进程管理的艺术和调度策略的智慧。你将了解到进程是如何创建、执行和消亡的,以及操作系统如何巧妙地决定哪个进程应该在何时获得CPU的青睐。让我们一起揭开操作系统神秘的面纱,发现那些隐藏在日常计算背后的精妙机制。
|
调度 开发者
深入理解操作系统之进程调度
在计算机科学领域,操作系统是核心的一环,它管理着计算机硬件资源,并提供接口供上层软件运行。本文将通过深入浅出的方式,探讨操作系统中至关重要的一个概念——进程调度。我们将从基础理论出发,逐步展开讲解进程调度的原理和实现,并配以实际代码示例,旨在帮助读者更好地理解和掌握这一主题。文章不仅适合初学者建立基础,也适合有一定基础的开发者深化理解。