广州大学课程设计–时间片轮转法
操作系统课程设计
要求:书写课程设计报告,报告中应该包含如下内容:
(1)课程设计题目及内容
(2)程序中使用的数据结构及主要符号说明
(3)程序流程图和带有注释的源程序
(4)执行程序名,并打印程序运行时的初值和运算结果
(5)实验结果分析,实验收获和体会
(6)实验的改进意见和建议。以下六个题目任选一题
题目一:设计一个按照时间片轮转法实现处理机调度的程序 时间片轮转法实现处理机调度的程序设计提示如下:
(1)假设系统有n个进程,每个进程用一个进程控制块(PCB)来代表。进程控制块的格式如下表所示,且参数意义也相同。
进程名 链接指针 到达时间 估计运行时间 进程状态(2)按照进程到达的先后顺序排成一个循环队列,设一个队首指针指向第一个到达进程的首址。另外再设一个当前运行进程指针,指向当前正运行的进程。
(3)执行处理机调度时,首先选择队首的第一个进程运行。
(4)由于本题目是模拟实验,所以对被选中的进程并不实际启动运行,而只是执行如下操作:
1)估计运行时间减1;
2)输出当前运行进程的名字。
用这两个操作来模拟进程的一次运行。
(5)进程运行一次后,以后的调度则将当前指针依次下移一个位置,指向下一个进程,即调整当前运行指针指向该进程的链接指针所指进程,以指示应运行进程,同时还应判断该进程的剩余运行时间是否为0,若不为0,则等待下一轮的运行,若该进程的剩余运行时间为0,则将该进程的状态置为完成状态“C”,并退出循环队列。
(6)若就绪队列不为空,则重复上述的步骤(4)和(5)直到所有进程都运行完为止。
(7)在所设计的调度程序中,应包含显示或打印语句,以便显示或打印每次选中进程的名称及运行一次后队列的变化情况。
思路
- [Ⅰ] 先建立链式循环队列,然后按照到达时间从小到大排序
- [Ⅱ] 将排好序的队列输入到RR算法
- [Ⅲ] 将未结束的进程的运行时间轮流减一,若有的进程结束了则标记,直至所有进程运行时间为0。
一、程序流程图
二、源代码
// 课设_时间片轮转法_处理机调度.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#include<ctime>
using namespace std;
#define Length 10
int n;
int Round = 0;//轮转数
struct PCB//一个头指针,无数据,下一个为头,rear一直指向尾
{
char Name[Length];
PCB* next;
int ArriveTime;//到达时间
int RunTime;//运行时间
char state;//状态(A为未完成态,C为完成态)
}*head;//头
void Creat(PCB* c)
{
srand((unsigned)time(NULL));
PCB* l, * s;
c = (PCB*)malloc(sizeof(PCB));
c->next = NULL;
l = c;//头节点
printf("请输入总进程数:");
scanf_s("%d", &n);
printf("随机生成\t序号\t初始化进程(进程名'\'到达时间'\'估计运行时间)\n");
for (int i = 0; i < n; ++i)
{
s= (PCB*)malloc(sizeof(PCB));
s->next = NULL;
/*printf("%d\t", i);
scanf_s("%s", &s->Name,sizeof(s->Name));
scanf_s("%d", &s->ArriveTime);
scanf_s("%d", &s->RunTime);*/
s->Name[0] = char(i + 65);
for (int j = 1; j < Length; ++j)
{
s->Name[j] = NULL;
}
s->ArriveTime = rand() % 10;
s->RunTime = rand()%10+1;
s->state = 'A';//未运行
l->next = s;
if (i == 0)
head = s;
l = l->next;
}
//rear = l;
l->next = head;
printf("\n");
}
void Output(PCB* c)
{
if (n == 0)
{
exit(1);
}
PCB* l;
l = c;
printf("名字\t到达时间\t估计运行时间\t状态\n");
do
{
if (l->state != 'C')//该进程未结束
{
printf("%s\t", l->Name);
printf("%d\t\t", l->ArriveTime);
printf("%d\t\t", l->RunTime);
//cout<<l->state<<endl;
printf("%c\n", l->state);
l = l->next;
}
else
l = l->next;
} while (l != head);
printf("\n");
}
void Output2(PCB* c,int time)//输出运行队列
{
PCB* l;
l = c;
printf("名字\t到达时间\t估计运行时间\t状态\n");
do
{
if (l->state != 'C'&&l->ArriveTime<=time)//该进程未结束
{
printf("%s\t", l->Name);
printf("%d\t\t", l->ArriveTime);
printf("%d\t\t", l->RunTime);
//cout<<l->state<<endl;
if (l->RunTime == 0)
{
printf("C\n");
}
else
{
printf("%c\n", l->state);
}
l = l->next;
}
else
l = l->next;
} while (l != head);
printf("\n");
}
void SortPCB(PCB* c)
{
PCB* l,*tmp,*s;
tmp=(PCB*)malloc(sizeof(PCB));
l = c;
printf("--------------------------根据到达时间排序--------------------------\n");
for(int i=0;i<n;++i)
{
s = l->next;
for(int j=0;j<n-1;++j)
{
if (s->ArriveTime > l->ArriveTime)//冒泡
{
for (int i = 0; i < Length; ++i)
{
tmp->Name[i] = l->Name[i];
}
tmp->ArriveTime = l->ArriveTime;
tmp->RunTime = l->RunTime;
tmp->state = l->state;
for (int i = 0; i < Length; ++i)
{
l ->Name[i] = s->Name[i];
}
l->ArriveTime = s->ArriveTime;
l->RunTime = s->RunTime;
l->state = s->state;
for (int i = 0; i < Length; ++i)
{
s->Name[i] = tmp->Name[i];
}
s->ArriveTime = tmp->ArriveTime;
s->RunTime = tmp->RunTime;
s->state = tmp->state;
}
s = s->next;
}
l = l->next;
}
}
void RR(PCB *c)//时间片轮转法
{
printf("--------------------------时间片轮转法--------------------------\n");
int m = n;//剩余进程数
PCB* l;
l = c;
while (l->RunTime > 0)
{
printf("Round:\t%d",Round);
//把就绪队列里面到达时间的PCB加入运行队列
if (l->ArriveTime <= Round)
{
printf("--正在运行%s", l->Name);
printf("进程\n");
l->RunTime--;
Output2(c,Round);
if (l->RunTime == 0)//结束了
{
l->state = 'C';
m--;
printf("进程%s已经结束,被删除\n", l->Name);
}
/*else
{
printf("--当前没有进程运行\n");
}*/
int count = 0;
while (l->next->ArriveTime > Round&&count!=m)//跳过未到到达时间的进程且还有到了到达时间的队列
{
l = l->next;
count++;
}
/* 测试样例
1 3 2
2 3 1
3 0 1
4 0 5
5 10 2
*/
l = l->next;
}
else
{
printf("--当前无进程运行\n");
}
Round++;
while (m && l->RunTime == 0)
{
l = l->next;//跳过已经结束的进程
}
}
printf("--------------------------END--------------------------\n");
}
int main()
{
printf("-----------------------------LSZNB-----------------------------\n");
PCB*c = (PCB*)malloc(sizeof(PCB));
Creat(c);
Output(head);
SortPCB(head);
Output(head);
RR(head);
}
三、运行结果
举个简单的例子
A 0 2
B 0 2
C 2 3
那么顺序应该是A->B->A(A退出)->B(退出)->C->C->C(退出)
这里就展示一个简单(随机生成的,不是上面那个)的例子,数量太多不好截屏
四、实验结果分析
- 因为算法比较简单,值得注意的地方就是要考虑数据结构(PCB)的初始化。
- 能进一步了解到进程的运作模式。
- 这类题目的难度较低,答辩可能会轻松些但是得分的上限不会很高。