实验 2 处理机调度算法

发布时间 2023-12-13 10:54:24作者: CLLWA


1. 实验任务
1) 回顾课本第三章中介绍过的作业或进程调度算法,包括先来先服务、最短作业优先、时间片轮转、多级队列调度和多级反馈队列调度等,介绍上述调度算法的设计原理并分析各自的特点;
2) 采用高级编程设计语言实现任意一种处理机调度算法;
3) 下面提供了实现先来先服务调度算法的参考代码;结合网络资源分析参考代码是否存在错误(请标注参考代码中核心指令所实现的功能),如果存在,如何修改;参考代码是否有可提升的地方;记录实验结果、分析实验数据并撰写实验报告。

  1. 结构体定义
    • pcb 结构体定义了一个进程控制块,包含了进程的各种信息,如ID、名称、状态、到达和开始时间等。
  2. 全局变量
    • time 记录当前的系统时间或最后一个进程的到达时间。
    • num_process 记录进程的数量。
    • sign_finish 似乎是一个未使用的字符变量。
    • head, p, 和 q 是指向 pcb 结构体的指针,用于管理进程队列。
  3. 函数定义
    • run_fcfs
      • 这个函数用于执行FCFS调度算法。
      • 如果新到达的进程比当前时间更早,则更新当前时间。
      • 打印当前时间和进程的开始信息。
      • 更新进程的开始和结束时间,并计算周转时间和加权周转时间。
      • 打印出这些信息。
    • fcfs
      • 这个函数用于找到下一个要运行的进程。
      • 遍历整个进程队列,找到状态为'R'(准备状态)且最早到达的进程。
      • 调用 run_fcfs 函数运行该进程。
    • inputinfo
      • 这个函数用于从用户输入中获取进程的信息,并初始化进程队列。
      • 为每个进程分配内存空间,并设置相应的字段值。
  4. 主函数
    • 首先打印FCFS调度算法的模拟过程。
    • 调用 inputinfo 函数获取进程信息并初始化进程队列。
    • 调用 fcfs 函数进行调度。
    • 最后打印“调度算法结束”。

FCFS算法的特点如下:

  • (1)有利于长作业,不利于短作业。
  • (2)有利于处理机繁忙的作业,不利于I/O繁忙的作业。

1)问题:这一段代码把printf、scanf输出的内容截断了

解决办法:换到一行里面

2)问题:

解决办法:

运行结果

图一

3)

问题:文字和数据不对齐

解决办法:

在这段代码加上换行符

在这段代码加上制表符

修改文字间距和输出数字间距到合适位置

运行结果

图二

心得感想:

通过对比可知

一)优点:公平、算法实现简单;

二)缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。即,FCFS算法对长作业有利,对短作业不利

图三

图四

图五

代码:

#include<stdio.h>

#include<stdlib.h>

typedef struct PCB{

char ID[3];//用于存储进程的ID。ID的长度为3。

char name[10];//这定义了一个字符数组,用于存储进程的名字。名字的最大长度为10。

char state;

int time_arrive;//表示进程到达的时间。

int time_start;

int time_finish;

int time_service;

float time_turnaround;//这是一个浮点数变量,表示进程的周转时间,即从到达开始到完成的时间。

float time_weightedturnaround;//表示进程的加权周转时间

struct PCB *next;//用于连接或链接到下一个PCB结构体。这样,所有相关的PCB可以通过这个指针链接在一起。

}

pcb;

int time;

int num_process;

char sign_finish;

pcb *head=NULL,*p,*q;

void run_fcfs(pcb* p1){//接受一个指向 pcb 结构体的指针作为参数

if(p1->time_arrive>time){

time=p1->time_arrive;

}//检查传入的进程(由 p1 表示)的到达时间是否大于当前的 time。

//如果上述条件为真,则将当前的 time 更新为进程的到达时间。

p1->time_start=time;

printf("现在的时间是%d,开始运行进程%c!\n",time,p1->name);

time=time+p1->time_service;

p1->state='F'; // the finished state;

p1->time_finish=time;//计算完成时间

p1->time_turnaround=p1->time_finish-p1->time_arrive;

p1->time_weightedturnaround=p1->time_turnaround/p1->time_service;

printf("进程ID\t 到达时间\t 开始时间\t 服务时间\t 完成时间\t 周转时间\t 加权周转时间\n");

printf("%6s%14d%14d%14d%14d%14.1f%14.2f\n",p1->ID,p1->time_arrive,p1->time_start,p1->time_service,p1->time_finish,p1->time_turnaround,p1->time_weightedturnaround);

}

/*

在每次迭代中,查找并运行所有就绪进程中最早到达的那一个,

直到所有进程都运行为止。

*/

void fcfs(){

int i,j,k=1;

int time1;

for(i=0;i<num_process;i++){

p=head;

k=1;

for(j=0;j<num_process;j++){

if(p->state=='R'){

if(k){

q=p;

time1=p->time_arrive;

k=0;

}

if(p->time_arrive<time1){

time1=p->time_arrive;

q=p;

}

}

p=p->next;

}

run_fcfs(q);

}

}

void inputinfo(){//这段代码主要是输入信息

int num,temp;

printf("请输入作业/进程数目:\n");

scanf("%d",&num_process);

printf("请依次输入%d个进程的相关信息,包括:1)进程号;2)进程名;3)到达时间;4)请求服务时间!\n",num_process);

for(num=0;num<num_process;num++){

p=(pcb*)malloc(sizeof(pcb));

temp=num+1;

printf("请输入第%d 个进程的相关信息:\n",temp);

scanf("%s\t%s\t%d\t%d",&p->ID,&p->name,&p->time_arrive,&p->time_service);

if(head==NULL){

head=p;

q=p;

time=p->time_arrive;

}

if(p->time_arrive<time){

time=p->time_arrive;

}

q->next=p;

p->time_start=0;

p->time_finish=0;

p->time_turnaround=0;

p->time_weightedturnaround=0;

p->next=NULL;

p->state='R'; // ready state;

q=p;

}

}

int main(void){

printf("先来先服务(First-Come-First-Served, FCFS)调度算法的模拟过程!\n");

inputinfo();

p=head;

fcfs();

printf("调度算法结束!\n");

}//主函数调用输入信息的函数、先到先服务的函数