操作系统课程设计——按照时间片轮转法实现处理机调度进程

按照时间片轮转法实现处理机调度程序

  • 设计一个按照时间片轮转法实现处理机调度的程序
    • 课程设计题目及要求
    • 程序中使用的数据结构及主要符号说明
    • 带有注释的源代码
    • 运行程序输出初值及运算结果

设计一个按照时间片轮转法实现处理机调度的程序

课程设计题目及要求

时间片轮转法实现处理机调度的程序设计提示如下:
(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
	}
}

运行程序输出初值及运算结果

###测试①
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第1张图片
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第2张图片
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第3张图片
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第4张图片
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第5张图片
###测试②
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第6张图片
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第7张图片
###测试③
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第8张图片
操作系统课程设计——按照时间片轮转法实现处理机调度进程_第9张图片

你可能感兴趣的:(操作系统课程设计——按照时间片轮转法实现处理机调度进程)