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

}


相关文章
|
18天前
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
11天前
|
消息中间件 安全 算法
深入理解操作系统:进程管理的艺术
【10月更文挑战第38天】在数字世界的心脏,操作系统扮演着至关重要的角色。它不仅是硬件与软件的桥梁,更是维持计算机运行秩序的守夜人。本文将带你走进操作系统的核心——进程管理,探索它是如何协调和优化资源的使用,确保系统的稳定与高效。我们将从进程的基本概念出发,逐步深入到进程调度、同步与通信,最后探讨进程安全的重要性。通过这篇文章,你将获得对操作系统进程管理的全新认识,为你的计算机科学之旅增添一份深刻的理解。
|
15天前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第34天】本文旨在探讨操作系统中至关重要的一环——进程管理及其调度策略。我们将从基础概念入手,逐步揭示进程的生命周期、状态转换以及调度算法的核心原理。文章将通过浅显易懂的语言和具体实例,引导读者理解操作系统如何高效地管理和调度进程,保证系统资源的合理分配和利用。无论你是初学者还是有一定经验的开发者,这篇文章都能为你提供新的视角和深入的理解。
38 3
|
17天前
|
Linux 调度 C语言
深入理解操作系统:进程和线程的管理
【10月更文挑战第32天】本文旨在通过浅显易懂的语言和实际代码示例,带领读者探索操作系统中进程与线程的奥秘。我们将从基础知识出发,逐步深入到它们在操作系统中的实现和管理机制,最终通过实践加深对这一核心概念的理解。无论你是编程新手还是希望复习相关知识的资深开发者,这篇文章都将为你提供有价值的见解。
|
18天前
|
算法 调度 UED
深入理解操作系统的进程调度机制
本文旨在探讨操作系统中至关重要的组成部分之一——进程调度机制。通过详细解析进程调度的概念、目的、类型以及实现方式,本文为读者提供了一个全面了解操作系统如何高效管理进程资源的视角。此外,文章还简要介绍了几种常见的进程调度算法,并分析了它们的优缺点,旨在帮助读者更好地理解操作系统内部的复杂性及其对系统性能的影响。
|
16天前
|
消息中间件 算法 调度
深入理解操作系统:进程管理的艺术
【10月更文挑战第33天】本文旨在揭示操作系统中进程管理的神秘面纱,带领读者从理论到实践,探索进程调度、同步以及通信的精妙之处。通过深入浅出的解释和直观的代码示例,我们将一起踏上这场技术之旅,解锁进程管理的秘密。
21 0
|
18天前
|
算法 Linux 调度
深入理解操作系统之进程调度
【10月更文挑战第31天】在操作系统的心脏跳动中,进程调度扮演着关键角色。本文将深入浅出地探讨进程调度的机制和策略,通过比喻和实例让读者轻松理解这一复杂主题。我们将一起探索不同类型的调度算法,并了解它们如何影响系统性能和用户体验。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇理解操作系统深层工作机制的大门。
26 0
|
19天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
41 0
Vanilla OS:下一代安全 Linux 发行版
|
22天前
|
人工智能 安全 Linux
|
1月前
|
Unix 物联网 大数据
操作系统的演化与比较:从Unix到Linux
本文将探讨操作系统的历史发展,重点关注Unix和Linux两个主要的操作系统分支。通过分析它们的起源、设计哲学、技术特点以及在现代计算中的影响,我们可以更好地理解操作系统在计算机科学中的核心地位及其未来发展趋势。
下一篇
无影云桌面