移臂调度及调度算法 C#实现
在磁盘盘面上,0磁道在盘面的外部;号数越大,磁道越靠近盘片的中心。
常用的移臂调度算法有先来先服务算法、最短寻找时间优先算法、电梯调度算法和单向扫描调度算法。
先来先服务算法:
不考虑访问者要求访问的物理位置,而只是考虑访问者提出访问请求的先后次序。

最短寻找时间优先算法
总是从等待访问者中挑选寻找时间最短的那个请求先执行,先不管访问者到来的先后顺序。

电梯调度算法
从移臂当前位置开始沿着臂的方向去选择离当前移动臂最近的那个柱访问者,如果沿臂的方向无请求者,就改变臂的方向再选择。
算法上实现需分移动臂从里到外移动、移动臂从外向里移动。
移动臂从外向里移动(正向),柱面号从小到大,可理解为电梯移动从下到上。

移动臂从里到外移动(逆向),柱面号从大到小,可理解为电梯移动从上到下。

单向扫描调度算法
不考虑访问者的等待先后顺序,总是从0号柱面开始向里道扫描,然后再返回0号柱面,再次进行扫描。
(在这里代码实现我就从第一个访问柱面的开始向里道扫描)

C#代码实现:
根据输入的柱面号访问序列,不同算法的服务顺序和移动总量。
环境:

do { Console.WriteLine("请选择其中一个移臂调度算法的编号:"); Console.WriteLine("1:先来先服务算法(FCFS)"); Console.WriteLine("2:短作业优先算法(SJF)"); Console.WriteLine("3:磁盘扫描/电梯算法(大,正向,从下到上)"); Console.WriteLine("4:磁盘扫描/电梯算法(小,逆向,从上到下)"); Console.WriteLine("5:单向扫描调度算法"); string inStr = Console.ReadLine(); Console.WriteLine("请输入需要访问的柱面号,逗号隔开");//空格 \u0020 string strList = Console.ReadLine(); if (string.IsNullOrWhiteSpace(strList)) { Console.WriteLine("你输入的柱面号为空。"); } string[] strArr = strList.Split('\u002C'); if (strArr == null || strArr.Count() <= 0) { Console.WriteLine("你输入的柱面号为空或者输入异常。"); } List<int> list = new List<int>(); try { foreach (string str in strArr) { list.Add(int.Parse(str)); } list.Distinct(); } catch (Exception ex) { Console.WriteLine("请输入正确的数字。"); } if (list == null || list.Count <= 0) { Console.WriteLine("你输入的柱面号为空。"); return; } if (list.Count == 1) { Console.WriteLine("你输入至少两个柱面号。"); return; } switch (inStr) { case "1": Console.WriteLine(@"你选择了算法{0}", inStr); FCFS(list); break; case "2": Console.WriteLine(@"你选择了算法{0}", inStr); SJF(list); break; case "3": Console.WriteLine(@"你选择了算法{0}", inStr); ScanUp(list); break; case "4": Console.WriteLine(@"你选择了算法{0}", inStr); ScanDown(list); break; case "5": Console.WriteLine(@"你选择了算法{0}", inStr); OneWayScan(list); break; default: Console.WriteLine("请输入正确的算法编号。"); break; } Console.WriteLine("按q退出,其他键继续。"); if(Console.ReadLine().ToString().ToLower().Equals("q")) { break; } } while (true); //先来先服务 void FCFS(List<int> list) { int mNum = 0;//移动总量 for (int i = 1; i < list.Count; i++) { mNum+=Math.Abs(list[i]-list[i-1]);//当前磁头与上一个访问过的磁头的差值 } Console.WriteLine(@"服务顺序为:{0}", string.Join(",", list)); Console.WriteLine(@"移动总量为:{0}", mNum); } //短作业优先 void SJF(List<int> list) { int mNum = 0;//移动总量 int firstNum = list[0];//当前磁头位置 List<int> newList = new List<int>(); newList.Add(firstNum);//先记录当前磁头位置 list.Sort();//排序 int firthIndex = list.FindIndex(a=>a.Equals(firstNum)); int len=list.Count; int left = firthIndex - 1; int right = firthIndex + 1; while (left>=-1 && right<=len) { int toLeft = 0; int toRight =0; if (left >= 0) { toLeft = Math.Abs(list[left] - firstNum); //当前磁头跟小的磁头(取最近的)的差值 } if (right < len) { toRight = Math.Abs(list[right] - firstNum);//当前磁头跟大的磁头(取最近的)的差值 } if(toLeft>0 && (toLeft < toRight|| toRight==0)) { //先访问小的 newList.Add(list[left]); firstNum = list[left]; mNum += toLeft; left--; }else if(toRight>0 && (toRight< toLeft || toLeft==0)) { //先访问大的 newList.Add(list[right]); firstNum = list[right]; mNum += toRight; right++; } else { left--; right++; } } Console.WriteLine(@"服务顺序为:{0}", string.Join(",", newList)); Console.WriteLine(@"移动总量为:{0}", mNum); } //磁盘扫描/电梯算法(大,正向) void ScanUp(List<int> list) { int mNum = 0;//移动总量 int firstNum = list[0];//当前磁头位置 List<int> newList = new List<int>(); newList.Add(firstNum);//先记录当前磁头位置 list.Sort(); int firthIndex = list.FindIndex(a => a.Equals(firstNum)); int len = list.Count; for (int i = firthIndex+1; i < len; i++)//正向 { mNum +=(list[i] - firstNum); //当前磁头跟最近的的磁头的差值 firstNum =list[i]; newList.Add(firstNum); } for (int i = firthIndex - 1; i >=0; i--)//逆向 { mNum += Math.Abs(list[i] - firstNum); //当前磁头跟最近的的磁头的差值 firstNum = list[i]; newList.Add(firstNum); } Console.WriteLine(@"服务顺序为:{0}", string.Join(",", newList)); Console.WriteLine(@"移动总量为:{0}", mNum); } //磁盘扫描/电梯算法(小,逆向) void ScanDown(List<int> list) { int mNum = 0;//移动总量 int firstNum = list[0];//当前磁头位置 List<int> newList = new List<int>(); newList.Add(firstNum);//先记录当前磁头位置 list.Sort(); int firthIndex = list.FindIndex(a => a.Equals(firstNum)); int len = list.Count; for (int i = firthIndex - 1; i >= 0; i--)//逆向 { mNum += Math.Abs(list[i] - firstNum); //当前磁头跟最近的的磁头的差值 firstNum = list[i]; newList.Add(firstNum); } for (int i = firthIndex + 1; i < len; i++)//正向 { mNum += (list[i] - firstNum); //当前磁头跟最近的的磁头的差值 firstNum = list[i]; newList.Add(firstNum); } Console.WriteLine(@"服务顺序为:{0}", string.Join(",", newList)); Console.WriteLine(@"移动总量为:{0}", mNum); } //单向扫描 void OneWayScan(List<int> list) { int mNum = 0;//移动总量 int firstNum = list[0];//当前磁头位置 List<int> newList = new List<int>(); newList.Add(firstNum);//先记录当前磁头位置 list.Sort(); int firthIndex = list.FindIndex(a => a.Equals(firstNum)); int len = list.Count; for (int i = firthIndex + 1; i < len; i++)//正向 { mNum += (list[i] - firstNum); //当前磁头跟最近的的磁头的差值 firstNum = list[i]; newList.Add(firstNum); } //从0开始, if (firthIndex>0) { //从里转到外面的0磁道位置 mNum += firstNum; firstNum = 0; newList.Add(0); for (int i = 0; i < firthIndex; i++)//再次从外到里 { mNum += Math.Abs(list[i] - firstNum); //当前磁头跟最近的的磁头的差值 firstNum = list[i]; newList.Add(firstNum); } } Console.WriteLine(@"服务顺序为:{0}", string.Join(",", newList)); Console.WriteLine(@"移动总量为:{0}", mNum); }
测试数据:100,55,58,39,18,90,160,115,38,184
结果:


浙公网安备 33010602011771号