时间片轮转法实现处理机调度的程序设计提示如下:
(1) 假设系统有n个进程,每个进程用一个进程控制块(PCB)来代表。进程控制块的格式如下表所示,且参数意义也相同。
进程名
链接指针
到达时间
估计运行时间
进程状态
(2) 按照进程到达的先后顺序排成一个循环队列,设一个队首指针指向第一个到达进程的首址。另外再设一个当前运行进程指针,指向当前正运行的进程。
(3) 执行处理机调度时,首先选择队首的第一个进程运行。
(4) 由于本题目是模拟实验,所以对被选中的进程并不实际启动运行,而只是执行如下操作:1)估计运行时间减1;
2)输出当前运行进程的名字。
用这两个操作来模拟进程的一次运行。
(5) 进程运行一次后,以后的调度则将当前指针依次下移一个位置,指向下一个进程,即调整当前运行指针指向该进程的链接指针所指进程,以指示应运行进程,同时还应判断该进程的剩余运行时间是否为0,若不为0,则等待下一轮的运行,若该进程的剩余运行时间为0,则将该进程的状态置为完成状态“C”,并退出循环队列。
(6) 若就绪队列不为空,则重复上述的步骤(4)和(5)直到所有进程都运行完为止。
(7) 在所设计的调度程序中,应包含显示或打印语句,以便显示或打印每次选中进程的名称及运行一次后队列的变化情况。
①
typedef struct pcb //定义进程控制块
{
char pname; //进程名
pcb* next; //链接指针
int arrival; //到达时间
int times; //估计运行时间
char status; //进程状态
}typdef;
②
typedef struct Queue //定义循环队列
{
pcb data; //pcb数据
pcb* prior; //指针指向前一个pcb
pcb* present; //指针指向当前pcb
}Queue, * LinkQueue;
③
pcb process[MAXPROCESS];//进程pcb[]
④
LinkQueue Q //就绪队列
LinkQueue L //暂存队列
#include
#include
#include
const int MAXPROCESS = 8;//生成进程的最大个数
const int MAXARRIVAL = 10;//进程最晚到达时间
const int MAXTIMES = 8;//进程最大估计运行时间
typedef struct pcb //定义进程控制块
{
char pname; //进程名
pcb* next; //链接指针
int arrival; //到达时间
int times; //估计运行时间
char status; //进程状态
}typdef;
typedef struct Queue //定义循环队列
{
pcb data; //pcb数据
pcb* prior; //指针指向前一个pcb
pcb* present; //指针指向当前pcb
}Queue, * LinkQueue;
void insert(Queue* queue, pcb* process)//插入函数
{
if (queue->present == NULL) //如果当前就绪队列为空时
{
queue->present = process;
queue->present->next = process;
queue->prior = process;
queue->prior->next = process;
return;
}
if (queue->present == queue->prior) //当前就绪队列只有一个pcb时
{
queue->prior = process;
queue->prior->next = queue->present;
queue->present->next = queue->prior;
return;
}
else //当就绪队列有两个或两个以上pcb时
{
queue->prior->next = process;
queue->prior = process;
queue->prior->next = queue->present;
}
}
int pop(Queue* queue) //弹出循环队列当前指针所指元素的到达时间
{
if (queue->present == NULL) //当前就绪队列为空时
{
printf("此时队列为空\n");
return 0;
}
int value = -1;
if (queue->present == queue->prior)//当前就绪队列只有一个pcb时
{
value = queue->present->arrival;
queue->present = queue->prior = NULL;
}
else //当前就绪队列有一个以上pcb时
{
value = queue->present->arrival;
queue->prior->next = queue->present->next;
queue->present = queue->present->next;
}
return value;
}
pcb* popm(Queue* queue)//弹出队列当前指针所指元素
{
if (queue->present == NULL)//当前就绪队列为空
{
return NULL;
}
pcb* value;
if (queue->present == queue->prior)//当前就绪队列只有一个pcb
{
value = queue->present;
queue->present = queue->prior = NULL;
}
else //当前就绪队列一个以上pcb时
{
value = queue->present;
queue->prior->next = queue->present->next;
queue->present = queue->present->next;
}
return value;
}
void init(pcb a[], int n)//初始化函数实现随机生成pcb[]的功能
{
char name = 'A';
for (int i = 0; i < n; i++)
{
a[i].pname = name;//赋值进程名
a[i].status = 'M';//status的初始状态设为'M'
a[i].arrival = rand() % MAXARRIVAL;//随机生成进程到达时间
a[i].times = rand() % MAXTIMES+1;//随机生成进程运行时间
name++;
}
}
void sort(pcb m[], int k)//排序函数实现将pcb[]按到达时间从小到大排序的功能
{
pcb t;
for (int i = 0; i < k; i++)
{
t = m[i];
for (int j = i; j < k; j++)
{
if (m[j].arrival < t.arrival)
{
m[i] = m[j];
m[j] = t;
t = m[i];
}
}
}
}
void print(pcb b[], int n)//输出进程pcb[]的内容
{
printf(" 进程的初始化信息\n");//显示随机生成进程的各种信息
printf("进程号\t到达时间\t运行时间\t进程状态\n");
for (int i = 0; i < n; i++)
{
printf("%c\t %d\t %d\t %c\n", b[i].pname, b[i].arrival, b[i].times, b[i].status);
}
}
int main()
{
srand((unsigned)time(0));
int n = rand() % MAXPROCESS + 1;//随机生成的进程个数
pcb process[MAXPROCESS];//进程pcb[]
init(process, n);//初始化pcb[]内容
sort(process, n);//将pcb[]按到达时间进行排序
print(process, n);//输出排序后pcb[]的内容
LinkQueue Q = new Queue;//初始化就绪队列Q
Q->present = Q->prior = NULL;
LinkQueue L = new Queue;//初始化暂存队列L
L->present = L->prior = NULL;
int Time = 0;//Time表示处理机调度此时的时间
int t = 0;//变量t用于表示所有进程的执行状态
for (int i = 0; i < n; i++)//用于检测此时所有进程的状态,当t=0时,所有进程应处于执行完的状态
{
if (process[i].status == 'M')
{
t += 1;
}
}
printf("\n");
printf("-------------------开始执行处理机调度-------------------\n");
pcb* s = NULL;//
//int u =0,z= 0;//u,z用于for循环的变量,即每一次循环从上一次进程到达后的pcb[]里开始寻找,不用每次都从i=0开始寻找
while (t != 0)//进行处理机调度,如果t!=0则代表进程未全部执行完成
{
pcb* g = NULL;//用来表示每个时间点到达的新进程
pcb* a = NULL;//中间量
pcb* c = NULL;//中间量
pcb* e;//用于压入循环队列时的变量
pcb* w;//中间量
for (int u = 0; u < n; u++)
{
if (process[u].arrival == Time)//判断此时间点是否有进程到达,如果有进程到达的话,将其加入循环队列中
{
insert(Q, &process[u]);
g = &process[u];
}
}
if (g == NULL)//当此时没有新进程到达且有未结束执行的进程待压入循环队列
{
if (s)
{
e = popm(L);
do
{
insert(Q, e);
e = popm(L);
} while (e);
}
}
s = NULL;
if (Q->present != NULL)//判断此时循环队列不为空时
{
a = Q->present;//当前指针所指pcb
c = a;//将c指向此时运行的进程pcb
pop(Q);//暂压出循环队列首元素
a->times -= 1;//当前运行时间减1
if (a->times == 0)//此时运行进程的剩余运行时间为0
{
a->status = 'C';//将该进程状态置为完成状态
}
else//此时过程的剩余时间不为0
{
s = a;//要将其重新插入就绪队列
}
}
t = 0;
for (int p = 0; p < n; p++)
{
if (process[p].status == 'M')
{
t += 1;
}
}
printf("此时时间为%d\t", Time);//输出此刻时间点
if (c)
{
printf("此次执行进程号为%c\n", c->pname);
}
else
{
printf("此次没有执行任何进程\n");
}
w = Q->present;
if (w)//此时就绪队列不为空
{
printf("进程号\t到达时间\t剩余时间\t进程状态\n");
}
if (w)
{
do
{
printf("%c\t %d\t %d\t %c\n", w->pname, w->arrival, w->times, w->status);
w = w->next;
} while (w != Q->present);
}
if (!w && s)//当前就绪队列为空但有为暂弹出的pcb时
{
if (s->status == 'M')
{
printf("进程号\t到达时间\t剩余时间\t进程状态\n");
}
}
if (s)//输出本次运行进程相关信息
{
printf("%c\t %d\t %d\t %c\n", s->pname, s->arrival, s->times, s->status);
}
if (s)
{
insert(L, s);//将未结束的进程压入暂存队列
}
Time += 1;//此时时间点+1
}
}