操作系统实验一 处理器调度

实验一 处理器调度

一、实验目的与要求

本实验目的是模拟在单处理器情况下处理器调度,加深了解处理器调度的工作。
要求是从优先级调度和时间片轮转法调度算法中选取一个进行实验。

二、程序中使用的数据结构及符号说明

假设系统中有五个进程,用PCB结构体表示,如表1所示。
在这里插入图片描述
表1、PCB结构体
这5个进程都存访在一个数组中。PCB结构体自带next指针,所以PCB结构体自带头指针、用链表实现的队列结构,队列头指针为head。PCB的name表示进程名,假设五个进程的进程名分别是P1,P2,P3,P4,P5。reqtime表示要求运行时间。rank表示优先级,调度时总是选取优先数大的进程先执行。state表示状态,可假设有两种状态,“就绪”状态和“结束”状态,五个进程的初始状态都为“就绪”状态,用“R”表示,当一个进程运行结束后,它的状态变为“结束”,用“E”表示。
在对PCB指针进行比较时需要比较其优先级大小,也需要比较剩余运行时间。
利用cnt变量进行计数,记录当前有几个变量没有运行结束。

三、流程图

在这里插入图片描述

四、实验测试结果及结果分析

在这里插入图片描述
分析:初始化输入P1进程,优先级为1,要求运行时间为2;P2进程,优先级为5,要求运行时间为3;P3进程,优先级为3,要求运行时间为1;P4进程,优先级为4,要求运行时间为2;P5进程,优先级为2,要求运行时间为4。将五个进程的状态均设为R状态。
在对各进程初始化并连接成队列后,队头指针指向的第一个进程为优先级最大的是P2,第二个是P4,第三个是P3,第四个是P5,第五个是P1。
在这里插入图片描述
初始化时选择优先级最高的P2进程先运行,将其优先级和运行时间-1,在运行后将其重新放入队列。
在这里插入图片描述

因为P2的优先级仍是最大的,所以继续运行进程P2。在运行后将其插入队列,并按优先级重新排列。
在这里插入图片描述
此时优先级最高的P4进程,运行P4,将其优先级和时间-1,在运行后将其插入队列。
在这里插入图片描述
此时优先级最高的仍是P4进程,运行P4,优先级和时间-1之后,检测到P4运行时间为0,故结束进程,将其状态置为E,并退出队列。
在这里插入图片描述
剩下的进程中P2进程优先级最大,运行P2,将其优先级、时间减1,剩余时间为0,将其退出队列,状态设为E。
在这里插入图片描述
剩余进程中P3优先级最高,运行P3,将其优先级和时间-1,剩余时间为0,结束进程,退出队列,状态置为E。
在这里插入图片描述
剩下的进程中P5进程优先数最大,将其运行一次后没有运行完成,运行第二次后仍然没有运行完成,且优先数小于另一个剩下的进程P1进程。
在这里插入图片描述
P1进程优先级最大,将其运行一次后优先级仍然最大,将其运行第二次后运行完成,置状态为“E”,退出队列。
在这里插入图片描述
队列中只剩下一个进程P5进程,将其剩余的时间运行完。由于实验指导书并未规定优先数是否允许为负数,这里每次运行完成时仍然扣除优先级并可以将优先级扣成负数。P5进程运行完成后,所有进程运行完成,按照流程图,处理机结束运行。

五、实验小结

在一个按优先数调度算法实现处理器调度的进程中,各个进程块按照优先级大小有序排列在队列中,并根据优先级前后依次运行,每运行完一个进程后,又重新按照优先级进行排序,选取最高优先级进程运行。直到当该进程的系统要求运行时间为0时,才将其退出队列,状态置为结束。

附件:含比较详细注释说明的源程序清单
下面是用C++编写的源程序代码:

#include<iostream>
#include<iomanip>
#include<string>
#include<algorithm>
#define N 5    //五个进程块
using namespace std;
class PCB { //进程块
public:
	PCB* next;//指针
	string name;//进程名
	int reqtime;//要求运行时间
	int rank;//优先级
	char state;//状态  R表示就绪 E表示结束
};
PCB* head;
int cnt = 0;
PCB* runningprocess;
PCB P[N];
bool cmprank(PCB a, PCB b) //比较优先级
{
	return a.rank > b.rank;
}
void print(PCB* pcb) //显示打印
{
	cout << "\nprocess name " << pcb->name << endl;
	cout << "remaining running time " << pcb->reqtime << endl;
	cout << "priority rank: " << pcb->rank << endl;
	cout << "status: " << pcb->state << endl;
}
bool cmpreqtime(PCB a, PCB b)
{
	return a.reqtime > b.reqtime;
}
void run(PCB* head, PCB* runningprocess)
{
	if (cnt == 0)
	{
		cout << "\n******every pcb ends******\n";
		return;
	}
	cout << "\n#########process" << runningprocess->name << "running########\n";
	runningprocess->rank--;  //优先级-1
	runningprocess->reqtime--; //要求运行时间-1
	cout << "---------every pcb status----------";
	for (int i = 0; i < cnt; i++)//显示已就绪进程
	{
		print(&head[i]);   //选队首进程运行
	}
	cout << "\n--------------------------------\n";
	if (runningprocess->reqtime == 0) //某个进程运行结束
	{
		runningprocess->state = 'E';
		print(runningprocess);
		sort(head, head + cnt, cmpreqtime);//按照进程剩余时间排序,使结束的进程排在队尾
		cnt--;
	}
	sort(head, head + cnt, cmprank);//按照进程优先级排序
	for (int i = 1; i < cnt; i++)
	{
		head[i - 1].next = &head[i]; //改变指针位置,当一个进程运行结束后退出队列
	}
	runningprocess = head;//下一次运行的进程为队首进程
	run(head, runningprocess);
}
void init() {
	head = NULL; //进程队列队首
	runningprocess = NULL;  //正在运行的程序
	cnt = 0;  //进程数
}
void input() {
	for (int i = 0; i < N; i++)
	{
		cout << "\nplease input the " << i + 1 << "th process name :\n";
		cin >> P[i].name;
		cout << "\nplease input the rank of the process\n ";
		cin >> P[i].rank;
		cout << "\nplease input the reqtime of the process\n ";
		cin >> P[i].reqtime;
		P[i].state = 'R';
		P[i].next = NULL;
		cnt++;

	}
}
int main()
{
	init();
	input();
	sort(P, P + cnt, cmprank);
	for (int i = 1; i < cnt; i++)
	{

		P[i - 1].next = &P[i];
	}
	head = &P[0];
	runningprocess = &P[0];
	cout << "\-------------every pcb initial status--------------\n";
	for (int i = 0; i < cnt; i++)
	{
		print(&P[i]);
	}
	cout << "\n-----------------------------------------------------";
	run(head, runningprocess);
	system("pause");
	return 0;
}
  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
理解操作系统实验处理器调度的代码需要先了解操作系统调度算法的基本原理和实现方法。 在操作系统中,调度算法决定了如何分配CPU资源给正在运行的进程或线程,以及如何在不同的进程或线程之间进行切换。常见的调度算法包括先来先服务(FCFS)、短作业优先(SJF)、时间片轮转(RR)等。其中,时间片轮转算法是一种基于时间片的抢占式调度算法操作系统实验中的处理器调度代码就是基于这种算法实现的。 下面是处理器调度代码的解释: ```c void scheduler() { struct proc *p; int i; for(;;) { // 遍历所有进程,找到可运行的进程 sti(); // 允许中断 acquire(&ptable.lock); // 获取ptable锁 for (i = 0, p = ptable.proc; i < NPROC; i++, p++) { if (p->state != RUNNABLE) { continue; } // 找到可运行的进程,切换上下文,开始运行 curenv = p->env; p->state = RUNNING; swtch(&cpu->scheduler, curenv->env_pgdir); // 运行结束,切换回调度器 curenv = NULL; p->state = RUNNABLE; } release(&ptable.lock); // 释放ptable锁 } } ``` 这段代码包含了一个无限循环,每次循环会遍历所有进程,找到可运行的进程并切换上下文开始运行。具体来说,它的执行过程如下: 1. 遍历所有进程,找到可运行的进程。当进程处于RUNNABLE状态时,说明它已经准备好运行,可以被调度器调度执行。 2. 为了避免竞争条件,需要先获取ptable锁。由于是抢占式调度算法,所以在遍历进程的过程中需要允许中断(sti())。 3. 找到可运行的进程后,就可以切换上下文,开始运行。这里使用了汇编语言的swtch()函数来实现上下文的切换。swtch()函数会保存当前CPU寄存器的状态,并加载新进程的上下文。 4. 运行结束后,切换回调度器。此时,当前进程的状态被设置为RUNNABLE,等待下一次被调度执行。 5. 最后,释放ptable锁,继续进行下一轮调度。 需要注意的是,这段代码只是处理器调度算法的核心代码,还需要在其他地方调用它。比如,在进程创建、进程终止、进程睡眠和进程唤醒等事件发生时,都需要调用处理器调度函数scheduler()。这样可以保证操作系统中的所有进程都能被正确地调度执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Conn_w

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

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

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

打赏作者

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

抵扣说明:

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

余额充值