操作系统:用C语言实现FCFS(先来先服务),SJF(短作业抢占)和RR(时间片轮转,时间片=1)

本文通过编程实现FCFS(先来先服务)、SJF(抢占短作业优先)和RR(时间片轮转)三种进程调度算法,对给定的5个进程进行调度模拟,计算并比较各算法下的完成时间、周转时间、带权周转周期等指标。实验结果显示,不同算法在效率和公平性上存在差异,有助于深入理解这些调度策略的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

8 2

/* 运行时输入:
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);
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淬炼之火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值