### 操作系统先到先服务算法实现
#### 实验背景与目标
先到先服务(First-Come, First-Served,简称FCFS)是一种简单的进程调度算法,在这种算法下,进程按照它们到达就绪队列的顺序进行执行。本实验旨在通过编写一个模拟程序来深入理解FCFS算法的工作原理及其在操作系统中的应用。
#### 实验目的
1. **理解进程概念**:通过模拟FCFS算法,加深对进程以及进程调度算法的理解。
2. **熟悉FCFS算法**:掌握FCFS算法的基本原理及其在实际编程中的应用。
#### 实验内容
本实验的主要内容包括:
1. **构建模拟环境**:使用VC6创建一个Win32控制台应用程序项目,并命名为“操作系统FCFS实验”。
2. **实现FCFS算法**:编写一个名为`FCFS算法模拟`的C++源文件,用于模拟单处理器系统下的进程调度过程。
3. **功能扩展**:
- 计算并显示每个进程的带权周转时间、平均周转时间以及平均带权周转时间。
- 修改程序以处理进程之间可能存在的时间间隙的情况。
- 改写程序以支持任意顺序的进程到达时间输入,并确保正确的排序。
#### 代码实现分析
根据实验要求,我们将对提供的部分代码进行详细分析。
```c++
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#define N 3 // 定义进程数量为3
struct PCB {
char name[8]; // 进程名称
int arrive_time; // 到达时间
int run_time; // 执行时间
int finish_time; // 完成时间
int zhouzhuan_time; // 周转时间
double daiquan_time; // 带权周转时间
};
int total = 0;
int sumzhouzhuan_time;
double ave_zhouzhuan;
double sumdaiquan_time;
double ave_daiquan;
struct PCB pcb[N], temp;
// 输出函数
void output() {
printf("-------------------------------------------------------------\n");
printf("进程名 到达时间 运行时间 完成时间 周转时间 带权周转时间\n");
printf("-------------------------------------------------------------\n");
for (int i = 0; i < N; i++) {
printf("%4s %2d %2d %2d %2d %.1f\n", pcb[i].name, pcb[i].arrive_time, pcb[i].run_time, pcb[i].finish_time, pcb[i].zhouzhuan_time, pcb[i].daiquan_time);
}
printf("-------------------------------------------------------------\n");
printf("平均 %.1f %.1f\n", ave_zouzhuan, ave_daiquan);
printf("-------------------------------------------------------------\n");
}
// 主函数
void main() {
int i, j;
for (i = 0; i < N; i++) {
printf("请输入进程名\n");
scanf("%s", pcb[i].name);
printf("请输入到达时间:\n");
scanf("%d", &pcb[i].arrive_time);
printf("请输入要运行时间\n");
scanf("%d", &pcb[i].run_time);
}
// 输出已输入的进程信息
for (i = 0; i < N; i++) {
printf("%s %d %d\n", pcb[i].name, pcb[i].arrive_time, pcb[i].run_time);
}
// 进程排序,确保按照到达时间顺序执行
for (i = 0; i < N; i++) {
for (j = i; j < N; j++) {
if (pcb[i].arrive_time > pcb[j].arrive_time) {
// 交换两个进程的信息
strcpy(temp.name, pcb[i].name);
temp.arrive_time = pcb[i].arrive_time;
temp.run_time = pcb[i].run_time;
strcpy(pcb[i].name, pcb[j].name);
pcb[i].arrive_time = pcb[j].arrive_time;
pcb[i].run_time = pcb[j].run_time;
strcpy(pcb[j].name, temp.name);
pcb[j].arrive_time = temp.arrive_time;
pcb[j].run_time = temp.run_time;
}
}
}
// 计算完成时间、周转时间、带权周转时间等指标
for (i = 0; i < N; i++) {
if (i == 0) {
pcb[i].finish_time = pcb[i].arrive_time + pcb[i].run_time;
} else {
pcb[i].finish_time = pcb[i - 1].finish_time + pcb[i].run_time;
}
pcb[i].zhouzhuan_time = pcb[i].finish_time - pcb[i].arrive_time;
pcb[i].daiquan_time = (double)pcb[i].zhouzhuan_time / pcb[i].run_time;
total += pcb[i].run_time;
sumzhouzhuan_time += pcb[i].zhouzhuan_time;
sumdaiquan_time += pcb[i].daiquan_time;
}
ave_zhouzhuan = (double)sumzhouzhuan_time / N;
ave_daiquan = sumdaiquan_time / N;
// 输出最终结果
output();
}
```
#### 实验总结
1. **实现要求1**:通过增加计算每个进程的带权周转时间、平均周转时间和平均带权周转时间的代码,满足了实验要求。这些计算帮助我们更好地评估进程调度的效果。
2. **实现要求2**:为了处理进程间可能存在的时间间隙问题,我们需要在计算完成时间时考虑上一个进程的完成时间和当前进程的到达时间。如果当前进程在上一个进程完成之后才到达,则应等待直到该进程到达后再开始执行。
3. **实现附加题**:通过对进程结构体数组按照到达时间进行排序,我们可以处理任意顺序的进程到达时间输入。这里使用了简单的冒泡排序算法来实现这一功能。
通过本实验的学习,不仅能够加深对FCFS算法的理解,还能提高解决实际问题的能力,尤其是在处理操作系统中的进程调度问题时。