文章目录
Unity模拟操作系统&&按优先数调度算法实现处理器调度(总代码在文末)
众所周知,Unity是一个游戏引擎,它已经是在底层上做了很多封装的结果,那么用Unity写操作系统肯定就是不可能的,但是我这里尝试用Unity模拟一些操作系统中的算法,调度,主要是熟悉Unity开发以及学习C#中的一些算法,话不多说,直入主题----
题目要求
假定系统有5个进程,每个进程用一个PCB来代表。PCB的结构为:
·进程名——如P1~P5。
·指针——按优先数的大小把5个进程连成队列,用指针指出下一个进程PCB的首地址。
·要求运行时间——假设进程需要运行的单位时间数。
·优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
·状态——假设两种状态:就绪和结束,用R表示就绪,用E表示结束。初始状态都为就绪状态。
(2) 开始运行之前,为每个进程确定它的“优先数”和“要求运行时间”。通过键盘输入这些参数。
(3) 处理器总是选择队首进程运行。采用动态改变优先数的办法,进程每运行1次,优先数减1,要求运行时间减1。
(4) 进程运行一次后,若要求运行时间不等于0,则将它加入就绪队列,否则,将状态改为“结束”,退出就绪队列。
(5) 若就绪队列为空,结束,否则转到(3)重复。
要求能接受键盘输入的进程优先数及要求运行时间,能显示每次进程调度的情况,如哪个进程在运行,哪些进程就绪,就绪进程的排列情况。
操作系统中的算法解读
在作业调度中,从后备作业队列中选择若干优先级高的作业调入内存。
在进程调度中,将处理机分配给就绪队列中优先级最高的进程。
优先级(Priority)表示进程的重要性及运行优先性,通常用优先数来衡量。在某些系统中,优先数越大优先级越高;而在另一些系统中,优先数越大优先级越小。
非抢占式优先级调度算法:系统一旦将处理机分配给就绪队列中优先级最高的进程后,该进程便一直运行下去,直到完成或因发生某事件使该进程放弃处理机时,系统才将处理机分配给另一个更高优先级的进程。
抢占式优先级调度算法:将处理机分配给优先级最高的进程,使之运行。在进程运行过程中,一旦出现了另一个优先级更高的进程时,进程调度程序就停止原运行进程,而将处理机分配给新出现的高优先级进程。
也就是说,进程的属性优先级,决定谁先运行,运行结束后改动优先级,然后再找出最高的优先级,此文,优先级数字大的先运行
分析问题
首先,上题中的PCB结构,也就是进程结构,里面有指针,我们这里不用指针,但是我们要达到要求,所以分析一下要求–
要求能接受键盘输入的进程优先数及要求运行时间,能显示每次进程调度的情况,如哪个进程在运行,哪些进程就绪,就绪进程的排列情况。
所以我们需要PCB进程类,类包括优先级,剩余时间,名字这些属性,这些进程还要每隔一段时间排序,这里选择的数据结构是LIST,当然不一定是最优,后面会尝试选择其他容器。
知识点1(本文中能学到的)
IComparable接口
如果一个类实现了 IComparable,那么它就要重写CompareTo方法,这个方法直接决定了如果把这个类装进LIST内,LIST的SORT函数用什么规则比较。
所以我们的进程类要实现这个接口,并且重写CompareTo,让规则变为sort后优先级最高的在LIST前面
类创建代码
public class Courses: System.IComparable<Courses>
{
public Courses(string courseName,int priorityNum,int time)
{
CourseName = courseName;
PriorityNum = priorityNum;
Time = time;
state = State.Ready;
}
//按照PriorityNum排序,此接口方法当返回值大于0的时候,定义的是此对象大,有规则后,List.sort直接按照此规则排序
public int CompareTo(Courses courses)
{
return courses.PriorityNum-this.PriorityNum ;
}
public string CourseName;
public int PriorityNum;
public int Time;
public enum State
{
Ready,
End
}
public State state;
}
知识点2(本文中能学到的)
Prefab预制体的生成位置自定义,生成后的属性代码定义
我们的程序每次运行显示都要动态刷新,那么怎么刷新,就是每次排完序动态生成预制体,那么怎么让预制体内的文字改变呢——
我们的预制体是三个文本框,操作他的方法就是预制体生成的时候,生成到一个Gameobject LIST内,然后取第一个Child,第二个,第三个
刷新函数–
for (int i=0;i<TCourses.Count;i++)
{
Ans.Add(Instantiate(One, T[i].position, transform.rotation, Parent));
Ans[Ans.Count - 1].transform.GetChild(0).GetComponent<Text>().text = "进程名:" + TCourses[i].CourseName.ToString();
Ans[Ans.Count - 1].transform.GetChild(1).GetComponent<Text>().text = "优先数:" + TCourses[i].PriorityNum.ToString();
Ans[Ans.Count - 1].transform.GetChild(2).GetComponent<Text>().text = "剩余时间:" + TCourses[i].Time.ToString();
}
总体实现
代码挂在Canvas上
挂在模拟运行按钮上的函数
public void StartRunButtonPressed()
{
foreach (GameObject Inputs in InputF)
{
if (Inputs.transform.GetChild(0).GetComponent<InputField>().text == "" || Inputs.transform.GetChild(1).GetComponent<InputField>().text == "" || Inputs.transform.GetChild(2).GetComponent<InputField>().text == "")
ErrorPanel.SetActive(true);
else
continue;
}
if (isfirst)
{
foreach (GameObject Inputs in InputF)
{
TCourses.Add(new Courses(Inputs.transform.GetChild(0).GetComponent<InputField>().text, int.Parse(Inputs.transform.GetChild(1).GetComponent<InputField>().text), int.Parse(Inputs.transform.GetChild(2).GetComponent<InputField>().text)));
}
isfirst = false;
}
Simulation();
}
排序刷新函数
public void Simulation()
{
foreach(GameObject a in Ans)
{
Destroy(a);
}
Ans.Clear();
if (TCourses.Count == 0)
{
Debug.LogError(1);
return;
}
TCourses.Sort();
foreach (Courses c in TCourses)
{
if (c.Time == 0)
{
c.state = Courses.State.End;
TCourses.Remove(c);
}
}
TCourses[0].PriorityNum -= 1;
TCourses[0].Time -= 1;
for (int i=0;i<TCourses.Count;i++)
{
Ans.Add(Instantiate(One, T[i].position, transform.rotation, Parent));
Ans[Ans.Count - 1].transform.GetChild(0).GetComponent<Text>().text = "进程名:" + TCourses[i].CourseName.ToString();
Ans[Ans.Count - 1].transform.GetChild(1).GetComponent<Text>().text = "优先数:" + TCourses[i].PriorityNum.ToString();
Ans[Ans.Count - 1].transform.GetChild(2).GetComponent<Text>().text = "剩余时间:" + TCourses[i].Time.ToString();
}
if (TCourses[0].Time == 0)
{
TCourses.RemoveAt(0);
}
}
总函数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//进程数据类型
public class Courses: System.IComparable<Courses>
{
public Courses(string courseName,int priorityNum,int time)
{
CourseName = courseName;
PriorityNum = priorityNum;
Time = time;
state = State.Ready;
}
//按照PriorityNum排序,此接口方法当返回值大于0的时候,定义的是此对象大,有规则后,List.sort直接按照此规则排序
public int CompareTo(Courses courses)
{
return courses.PriorityNum-this.PriorityNum ;
}
public string CourseName;
public int PriorityNum;
public int Time;
public enum State
{
Ready,
End
}
public State state;
}
public class quiz1 : MonoBehaviour
{
public bool isfirst;
public GameObject ErrorPanel;
public GameObject One;
public List<GameObject>Ans;
public Transform Parent;
public List<RectTransform> T;
//存贮所有的进程
public List<GameObject> InputF ;
public List<Courses> TCourses;
void Awake()
{
isfirst = true;
//T = new List<RectTransform>();
TCourses = new List<Courses>();
Ans = new List<GameObject>();
}
public void StartRunButtonPressed()
{
foreach (GameObject Inputs in InputF)
{
if (Inputs.transform.GetChild(0).GetComponent<InputField>().text == "" || Inputs.transform.GetChild(1).GetComponent<InputField>().text == "" || Inputs.transform.GetChild(2).GetComponent<InputField>().text == "")
ErrorPanel.SetActive(true);
else
continue;
}
if (isfirst)
{
foreach (GameObject Inputs in InputF)
{
TCourses.Add(new Courses(Inputs.transform.GetChild(0).GetComponent<InputField>().text, int.Parse(Inputs.transform.GetChild(1).GetComponent<InputField>().text), int.Parse(Inputs.transform.GetChild(2).GetComponent<InputField>().text)));
}
isfirst = false;
}
Simulation();
}
public void Simulation()
{
foreach(GameObject a in Ans)
{
Destroy(a);
}
Ans.Clear();
if (TCourses.Count == 0)
{
Debug.LogError(1);
return;
}
TCourses.Sort();
foreach (Courses c in TCourses)
{
if (c.Time == 0)
{
c.state = Courses.State.End;
TCourses.Remove(c);
}
}
TCourses[0].PriorityNum -= 1;
TCourses[0].Time -= 1;
for (int i=0;i<TCourses.Count;i++)
{
Ans.Add(Instantiate(One, T[i].position, transform.rotation, Parent));
Ans[Ans.Count - 1].transform.GetChild(0).GetComponent<Text>().text = "进程名:" + TCourses[i].CourseName.ToString();
Ans[Ans.Count - 1].transform.GetChild(1).GetComponent<Text>().text = "优先数:" + TCourses[i].PriorityNum.ToString();
Ans[Ans.Count - 1].transform.GetChild(2).GetComponent<Text>().text = "剩余时间:" + TCourses[i].Time.ToString();
}
if (TCourses[0].Time == 0)
{
TCourses.RemoveAt(0);
}
}
}
结果
感觉写的还行的不要吝啬一个赞哟,是对码农最大的鼓励