五種進程調度的算法實現(三)


實驗要求

完成進程調度的可視化。

包括六種調度算法:

public enum SchdType
    {
        [Description("先來先服務")]
        FCFS,
        [Description("最短作業優先")]
        SJF,
        [Description("最短剩余時間優先")]
        SRTF,
        [Description("最高響應比優先")]
        HRRF,
        [Description("優先級調度")]
        PRIOR,
        [Description("輪轉調度")]
        RR,
    }

設計思路

使用C# WindowsForm易於開發。

  • 調度算法基於LINQ;
  • 所有調度算法采用統一的接口;
  • 用DataGridView呈現和更改初始數據;
  • 用GDI+實現繪圖。

數據結構

初始數據結構:

public class SimpleTask
    {
        [Unique]
        [DefaultValue("Task")]
        [Description("作業名")]
        public string Name { set; get; }

        [DefaultValue(0)]
        [Description("開始時間")]
        public int StartTime { set; get; }

        [DefaultValue(1)]
        [Description("運行時間")]
        public int ExecuteTime { set; get; }

        [DefaultValue(0)]
        [Description("優先級")]
        public int Priority { set; get; }
    }

初始化:

void InitTestData()
        {
            data.Rows.Add(new object[] { "A", 0, 3, 5 });
            data.Rows.Add(new object[] { "B", 2, 6, 2 });
            data.Rows.Add(new object[] { "C", 4, 4, 3 });
            data.Rows.Add(new object[] { "D", 6, 5, 4 });
            data.Rows.Add(new object[] { "E", 8, 2, 1 });
        }

運行時調度結構:

public class SchdRestModel
    {
        public SimpleTask task { set; get; }

        public int rest { set; get; }//剩余運行時間

        public double temp { set; get; }//用於存儲響應比
    }

輸入輸出結構:

public class SimulationResult
    {
        public List<SimpleTask> tasks { set; get; }

        public List<string> cpu_clips { set; get; }
    }

可視化結構:

public class VisualStruct
    {
        public DuringStruct during { set; get; }

        public List<Tuple<int, int>> cpu_clips { set; get; }
    }

    public class VisualData
    {
        public Dictionary<string, VisualStruct> visual { set; get; }

        public List<int> switches { set; get; }
    }

參數設置:

public class SchdSettings
    {
        private static int _TimeSpan = 1;

        public static int TimeSpan { set { _TimeSpan = value; } get { return _TimeSpan; } }

        public static readonly int MaxTimeSpan = 10;
        public static readonly int MinTimeSpan = 1;
    }

    public class VisualSettings
    {
        public static readonly int TimeSpanWidth = 30;
        public static readonly int TaskHeight = 30;
        public static readonly int TaskSpacing = 20;
        public static readonly int TaskBlanking = 20;
        public static readonly int TimeHeight = 20;
        public static readonly int DegreeHeight = 5;
        public static readonly int DispTextWidth = 100;
        public static readonly int Margin = 5;
    }

設計實現

一、接口及抽象類

調度接口:

public interface IProcessSchd
    {
        void ImportData(IEnumerable<SimpleTask> tasks);

        void SetCallback(Action<string> action);

        SimulationResult Simulate();
    }

抽象基類:

public abstract class ProcessSchd : IProcessSchd
    {
        protected IEnumerable<SimpleTask> origin_tasks;
        protected Action<string> action;

        public void ImportData(IEnumerable<SimpleTask> tasks)
        {
            origin_tasks = tasks;
        }

        public void SetCallback(Action<string> action)
        {
            this.action = action;
        }

        public abstract SimulationResult Simulate();
    }

工廠模式構建:

public class SchdFactory
    {
        static public IProcessSchd CreateSchdInstance(SchdType type)
        {
            return Assembly.GetExecutingAssembly().CreateInstance("SimuProcessSchd.Schd" + type.ToString()) as IProcessSchd;
        }
    }

二、通用算法

2.1 通用算法版本一(適用於除輪轉調度以外的五種調度算法)

/// <summary>
        /// 通用調度算法版本一
        /// </summary>
        /// <param name="task">運行時處理隊列</param>
        /// <param name="blocked">是否獨占式調度(非剝奪)</param>
        /// <param name="select">自定義任務競取函數</param>
        /// <returns></returns>
        static public List<string> GetSimuResultDirectV1(IEnumerable<SchdRestModel> task, bool blocked, Func<IEnumerable<SchdRestModel>, int, IEnumerable<SchdRestModel>> select)
        {
            var list = new List<string>();//用於存放結果
            var new_list = task.ToList();//當前任務隊列的拷貝,用於調度
            IEnumerable<SchdRestModel> selected = null;
            for (int i = 0; new_list.Count() > 0; i++)//進行運行時調度,當前隊列為空時結束
            {
                //當規定為可剝奪時,初始化任務競取函數,用於選取下一任務
                if (!blocked || (blocked && selected == null))
                    selected = select(new_list, i);
                if (selected.Count() > 0)//可以選取下一任務
                {
                    var running = selected.First();//取下一任務隊列頭
                    list.Add(running.task.Name);//當前時刻處理該任務並記錄任務名
                    if (running.rest > 1)//當前任務還有剩余運行時間
                    {
                        //當前運行的任務的剩余時間減一
                        new_list.Find(a => a.task.Name == running.task.Name).rest--;
                    }
                    else//當前任務已完成
                    {
                        if (selected != null)
                            selected = null;//清空競取函數
                        //從調度隊列中除去該任務
                        new_list.RemoveAll(a => a.task.Name == running.task.Name);
                    }
                }
                else//已經沒有任務可選取,收尾工作
                {
                    if (selected != null)
                        selected = null;
                    list.Add(null);
                }
            }
            return list;
        }

2.2 通用算法版本二(只適用於輪轉調度)

/// <summary>
        /// 通用調度算法版本二
        /// </summary>
        /// <param name="task">起始的任務隊列</param>
        /// <returns>模擬調度結果</returns>
        static public List<string> GetSimuResultDirectV2(IEnumerable<SchdRestModel> task)
        {
            var list = new List<string>();
            //采用雙隊列,后備和輪轉
            var backup = task.ToList(); // 后備隊列
            var round = new List<SchdRestModel>(); // 輪轉隊列
            //當雙隊列都不為空時,繼續運行,i為時刻
            for (int i = 0; backup.Count > 0 || round.Count > 0; i++)
            {
                SchdRestModel current = null;

                // 檢查后備
                if (round.Count == 0)//當前輪轉隊列為空時,取后備隊列
                {
                    round.AddRange(
                        from x in backup
                        where x.task.StartTime <= i
                        orderby x.task.StartTime//按起始時間
                        orderby x.task.Priority//按優先級
                        select x);
                    backup.RemoveAll(a => a.task.StartTime <= i);//做移動操作,將舊的刪除
                }
                
                // 處理輪轉
                if (round.Count > 0)//輪轉不為空,則有任務
                {
                    current = round.First();//取隊列頭
                    round.RemoveAt(0);//清除
                }

                // 取出隊頭並處理
                if (current != null)
                {
                    var min = Math.Min(current.rest, SchdSettings.TimeSpan);//輪轉時獨占時長的限制
                    current.rest -= min;//減去當前運行時間
                    for (int j = 0; j < min; j++)
                    {
                        list.Add(current.task.Name);//添加運行記錄
                    }
                    if (current.rest <= 0)
                    {
                        current = null;//沒有剩余時間則丟棄
                    }
                    i += min - 1;//時刻表推進,由於for循環對i有自增操作,所以這里減一
                }
                else
                {
                    list.Add(null);//結束標記
                }

                // 再次處理后備
                {
                    round.AddRange(
                        from x in backup
                        where x.task.StartTime <= i + 1
                        orderby x.task.StartTime
                        orderby x.task.Priority
                        select x);
                    backup.RemoveAll(a => a.task.StartTime <= i + 1);
                }

                // 將當前任務放至隊尾
                if (current != null)
                {
                    round.Add(current);
                }
            }
            return list;
        }

三、具體算法

/// <summary>
    /// 先來先服務
    /// </summary>
    public class SchdFCFS : ProcessSchd
    {
        public override SimulationResult Simulate()
        {
            var result = new SimulationResult() { tasks = origin_tasks.ToList() };
            result.cpu_clips = SchdImplHelper.GetSimuResultDirectV1(
                from x in origin_tasks
                orderby x.StartTime
                select new SchdRestModel
                {
                    task = x,
                    rest = x.ExecuteTime,
                },
                true,
                (a, i) =>
                    from x in a
                    where x.task.StartTime <= i
                    select x
                );
            return result;
        }
    }

    /// <summary>
    /// 最短作業優先
    /// </summary>
    public class SchdSJF : ProcessSchd
    {
        public override SimulationResult Simulate()
        {
            var result = new SimulationResult() { tasks = origin_tasks.ToList() };
            result.cpu_clips = SchdImplHelper.GetSimuResultDirectV1(
                from x in origin_tasks
                orderby x.StartTime
                select new SchdRestModel
                {
                    task = x,
                    rest = x.ExecuteTime,
                },
                true,
                (a, i) =>
                    from x in a
                    where x.task.StartTime <= i
                    orderby x.task.ExecuteTime
                    select x
                );
            return result;
        }
    }

    /// <summary>
    /// 最短剩余時間優先
    /// </summary>
    public class SchdSRTF : ProcessSchd
    {
        public override SimulationResult Simulate()
        {
            var result = new SimulationResult() { tasks = origin_tasks.ToList() };
            result.cpu_clips = SchdImplHelper.GetSimuResultDirectV1(
                from x in origin_tasks
                orderby x.ExecuteTime
                select new SchdRestModel
                {
                    task = x,
                    rest = x.ExecuteTime,
                },
                false,
                (a, i) =>
                    from x in a
                    where x.task.StartTime <= i
                    orderby x.rest
                    select x
                );
            return result;
        }
    }

    /// <summary>
    /// 最高響應比優先
    /// </summary>
    public class SchdHRRF : ProcessSchd
    {
        public override SimulationResult Simulate()
        {
            var result = new SimulationResult() { tasks = origin_tasks.ToList() };
            result.cpu_clips = SchdImplHelper.GetSimuResultDirectV1(
                from x in origin_tasks
                orderby x.StartTime
                select new SchdRestModel
                {
                    task = x,
                    rest = x.ExecuteTime,
                },
                true,
                (a, i) =>
                     from y in
                         (from x in a
                         where x.task.StartTime <= i
                         select new SchdRestModel
                         {
                             task = x.task,
                             rest = x.rest,
                             temp = ((double)i - (double)x.task.StartTime) / (double)x.task.ExecuteTime
                         })
                    orderby y.temp descending
                     select y
                );
            return result;
        }
    }

    public class SchdPRIOR : ProcessSchd
    {
        public override SimulationResult Simulate()
        {
            var result = new SimulationResult() { tasks = origin_tasks.ToList() };
            result.cpu_clips = SchdImplHelper.GetSimuResultDirectV1(
                from x in origin_tasks
                orderby x.StartTime
                select new SchdRestModel
                {
                    task = x,
                    rest = x.ExecuteTime,
                },
                false,
                (a, i) =>
                    (from x in a
                     where x.task.StartTime <= i
                     orderby x.task.Priority
                     select x)
                );
            return result;
        }
    }

    public class SchdRR : ProcessSchd
    {
        public override SimulationResult Simulate()
        {
            var result = new SimulationResult() { tasks = origin_tasks.ToList() };
            result.cpu_clips = SchdImplHelper.GetSimuResultDirectV2(
                from x in origin_tasks
                select new SchdRestModel
                {
                    task = x,
                    rest = x.ExecuteTime,
                });
            return result;
        }
    }

運行結果

參見上一篇《五種進程調度的算法實現(二)》結尾處的測試圖。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM