1.1 实验目的
加深对进程调度的理解,熟悉进程调度的不同算法,比较其优劣性。
1.2 实验内容
假如一个系统中有5个进程,它们的到达时间内如表1所示,忽略I/O以及其他开销时间。若分别按先来先服务(FCFS)、抢占的短作业优先(SJF)、时间片轮转(RR,时间片=1)进行CPU调度,请按照上述三个算法,编程计算出各进程的完成时间内、周转时间、带权周转周期、平均周转周期和平均带权周转时间。
表1 进程到达和需服务时间
进程 |
到达时间 |
服务时间 |
A |
0 |
3 |
B |
2 |
6 |
C |
4 |
4 |
D |
6 |
5 |
E |
8 |
2 |
1.3算法描述
FCFS是先来先服务算法,采用队列的思想,队首入,队尾出,后到的放在队首。
SJF是抢占短作业优先算法,在采取队列的同时要注意当前进程的剩余服务时间和新来进程的服务时间长短,如果新来的更短则进行抢占,否则继续进行,如果该进程进行完则要在队列中挑选最短的作业进行执行。
RR是时间片轮转算法,每一个进程在队列里享受一定的时间片,当时间片用完时,进程将会被放到队首,等待下一时间片的分配。
1.4 实验结果(linux虚拟机运行)
编译指令:#g++ -o process process.cpp
运行指令:./process
1.5 实验小结
FCFS先来先服务并没有太多复杂的放地方,完全可以用数组遍历的方式再加上一个时间参数来方便记录各进程的完成时间,最后每个数据类型都应该是double或者float防止在计算的时候数据出现较大的偏差。SJF短作业抢占时要注意比较新来进程需要服务时间和剩余时间,如果新来更短则抢占,这里要注意的是如果在没有新来进程情况下,队列中的进程需要服务时间都应该比正在进行的进程长,并且在该进程进行完时应该挑选队列里最短的作业进行完成。RR时间片轮转算法最关键的还是判断新来进程和上一秒完成进程谁先放在队列后面,因此理论上讲RR轮转算法计算应该会有两种结果,本代码用两个RR函数分别代表了新来进程优先和上一秒完成进程优先的两种情况。另外,后两种算法都应该注意循环的结束条件,即所有进程完成的判断条件和剩余服务时间的记录。
1.6实验代码
运行时输入:
5
0 3
2 6
4 4
6 5文章来源:https://www.toymoban.com/news/detail-765590.html
8 2文章来源地址https://www.toymoban.com/news/detail-765590.html
/* 运行时输入:
5
0 3
2 6
4 4
6 5
8 2
*/
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define Maxsize 10
typedef struct process {
char name; /*进程名*/
int arrive; /*到达时间*/
int serve; /*服务时间*/
int end; /*结束服务时间*/
int use; /*使用时间(链表专用)*/
struct process* next; /*下一结点(链表专用)*/
}p[Maxsize],pNode;
p pp;
int process;
void FCFS();
void SJF();
void RR();
void RR1();
int main() {
scanf_s("%d", &process);
for (int i = 0; i < process; i++) { /*输入进程信息*/
scanf_s("%d %d", &pp[i].arrive, &pp[i].serve);
pp[i].name = (char)(65 + i);
pp[i].use = 0;
}
FCFS();
SJF();
RR();
RR1();
return 0;
}
void FCFS() {
int time = 0; /*时间参数*/
float avert = 0, avertt = 0; /*平均周转,平均带权周转*/
printf("FCFS:\n进程\t完成时间区间\t周转时间\t带权周转周期\t\n");
for (int i = 0; i < process; i++) {
time += pp[i].serve; /*时间参数计数*/
pp[i].end = time; /*进程结束时间记录*/
printf("%c\t%d-%d\t\t%d\t\t%f\n",pp[i].name, pp[i].arrive, pp[i].end, pp[i].end - pp[i].arrive, (float)(pp[i].end - pp[i].arrive) / pp[i].serve);
avert += pp[i].end - pp[i].arrive; avertt += (float)(pp[i].end - pp[i].arrive) / pp[i].serve;
}
printf("平均周转周期: %f\t平均带权周转时间: %f\n\n", avert / process, avertt / process);
}
void SJF() {
int time = 0; /*时间参数*/
int finish[Maxsize] = { 0 }; /*对应每个进程的完成进度*/
float avert = 0, avertt = 0; /*平均周转,平均带权周转*/
for (int i = 0; i < process; i++) { /*计算需要时间长度方便结束循环*/
time += pp[i].serve;
}
printf("SJF:\n进程\t完成时间区间\t周转时间\t带权周转周期\t\n");
int t = 0;
while (t < time) {
int min=0, mintime = 1e9;
for (int i = 0; i < process; i++) { /*寻找剩余服务时间最短的进程,剩余服务时间=server-finish*/
if (pp[i].arrive <= t&&pp[i].serve-finish[i]<mintime&& pp[i].serve != finish[i]) {
min = i; mintime = pp[i].serve - finish[i];
}
}
finish[min]++;
if (finish[min] == pp[min].serve) { /*进程完成判断*/
pp[min].end = t + 1;
}
t++; /*以1为时间片方便判断是否进行抢占*/
}
for (int i = 0; i < process; i++) {
printf("%c\t%d-%d\t\t%d\t\t%f\n", pp[i].name, pp[i].arrive, pp[i].end, pp[i].end - pp[i].arrive, (float)(pp[i].end - pp[i].arrive) / pp[i].serve);
avert += pp[i].end - pp[i].arrive; avertt += (float)(pp[i].end - pp[i].arrive) / pp[i].serve;
}
printf("平均周转周期: %f\t平均带权周转时间: %f\n\n", avert / process, avertt / process);
}
void RR() {
int time = 0; /*时间参数*/
int finish[Maxsize] = { 0 }; /*对应每个进程的完成进度*/
float avert = 0, avertt = 0; /*平均周转,平均带权周转*/
for (int i = 0; i < process; i++) { /*计算需要时间长度方便结束循环*/
time += pp[i].serve;
}
printf("RR(上一秒完成进程优先):\n进程\n完成时间区间\t周转时间\t带权周转周期\t\n");
int t = 0;
while (true) {
int B = 0; /*结束条件*/
for (int i = 0; i < process; i++) {
if (pp[i].arrive <= t && pp[i].serve != finish[i]) /*判断是否完成和是否到达*/
{
finish[i]++;
t++;
if (pp[i].serve == finish[i])pp[i].end = t; /*单个进程完成判定*/
}
if (t == time) { /*所有进程全部完成判定*/
B = 1; break;
}
}
if (B)break;
}
for (int i = 0; i < process; i++) {
printf("%c\t%d-%d\t\t%d\t\t%f\n", pp[i].name, pp[i].arrive, pp[i].end, pp[i].end - pp[i].arrive, (float)(pp[i].end - pp[i].arrive) / pp[i].serve);
avert += pp[i].end - pp[i].arrive; avertt += (float)(pp[i].end - pp[i].arrive) / pp[i].serve;
}
printf("平均周转周期: %f\t平均带权周转时间: %f\n\n", avert / process, avertt / process);
}
void RR1() {
pNode* front = (pNode*)malloc(sizeof(pNode));
pNode* rear = (pNode*)malloc(sizeof(pNode));
rear = front;
rear->next = NULL;
int time = 0; /*时间参数*/
float avert = 0, avertt = 0; /*平均周转,平均带权周转*/
for (int i = 0; i < process; i++) { /*计算需要时间长度方便结束循环*/
time += pp[i].serve;
}
printf("RR1(新来进程优先):\n进程\n完成时间区间\t周转时间\t带权周转周期\t\n");
int length = 0; /*链表长度*/
int nowtime = 0; /*实际运行时间*/
for (int i = 0; i < process; i++) {
if (pp[i].arrive == 0) {
pNode* p;
p = &pp[i];
p->use = 0;
p->next = NULL;
rear->next = p;
rear = p;
length++;
//printf("%c: %d %d %d %d\n", p->name, p->arrive, p->end, p->serve, p->use);
}
}
while (true) {
for (int i = 0; i < process; i++) {
if (pp[i].arrive-1 == nowtime) {
pNode* p;
p = &pp[i];
p->use = 0;
p->next = NULL;
rear->next = p;
rear = p;
length++;
//printf("%c: %d %d %d %d\n", p->name, p->arrive, p->end, p->serve, p->use);
}
}
front->next->use++;
if (length == 1) {
if (front->next->use == front->next->serve) {
front->next->end = nowtime + 1;
rear = front;
rear->next = NULL;
length = 0;
break;
}
}
else {
if (front->next->use == front->next->serve) {
front->next->end = nowtime + 1;
front->next = front->next->next;
length--;
}
else {
rear->next = front->next;
front->next = front->next->next;
rear = rear->next;
rear->next = NULL;
}
}
nowtime++;
}
for (int i = 0; i < process; i++) {
printf("%c\t%d-%d\t\t%d\t\t%f\n", pp[i].name, pp[i].arrive, pp[i].end, pp[i].end - pp[i].arrive, (float)(pp[i].end - pp[i].arrive) / pp[i].serve);
avert += pp[i].end - pp[i].arrive; avertt += (float)(pp[i].end - pp[i].arrive) / pp[i].serve;
}
printf("平均周转周期: %f\t平均带权周转时间: %f\n\n", avert / process, avertt / process);
}
到了这里,关于操作系统:用C语言实现FCFS(先来先服务),SJF(短作业抢占)和RR(时间片轮转,时间片=1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!