操做系統學習一:.NetCore 實現模擬多道程序設計的簡單處理機調用

前言

道程序設計中,常常是若干個進程同時處於就緒狀態,爲了使系統中的各進程有條不紊地運行,必須選擇某種調度策略,以選擇一個進程佔用處理機。本次實驗設計一個模擬單處理機調度的算法,以加深對處理機調度算法的理解。算法

要求

  1. 按照時間片輪轉算法設計模擬調度程序。
  2. 輸出進程的調度過程。

思路分析

因爲本實驗是按照處理機調度算法模擬實現處理機的調度,與真正的處理機調度過程並不徹底相同,好比沒有實現中斷(時間片設爲1),進程的運行也不是真正的運行,而是在屏幕上打印其運行時間等。因此要以文件的形式給出進程的信息,文件信息可參考以下:微信

進程ID  到達時間     估計運行時間     優先級
0        0             3               2
1        2             6               4
2        4             4               0
3        6             5               3
4        8             2               1

如下是實驗的大體思路:dom

  1. 創建三個隊列:PCB隊列,就緒隊列,完成隊列。

PCB隊列:保存將進入系統的進程。(因爲沒有實現中斷,因此將進入系統運行的進程必須在程序運行前給出)。
就緒隊列:到達進程進入系統的時間,將該進程放入就緒隊列,等待調度。
完成隊列:將「運行」完的進程放入完成隊列。ide

  1. 進程運行過程是在屏幕上打印相關信息。

使用輪轉算法調度的進程應打印的信息包括:進程佔用處理機序列,該進程每次佔用處理機的開始時間與結束時間。this

  1. 統計出進程的週轉時間T和帶權週轉時間W。

流程圖

實現代碼

  1. ProcessControlBlock.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OperatingSystemExperiment.Exp1 {
    enum ProcessStatus {
        Ready,
        Run,
        Finish
    }

    /// <summary>
    /// 進程控制塊 PCB
    /// </summary>
    class ProcessControlBlock {
        /// <summary>
        /// 進程號
        /// </summary>
        public int ID;

        /// <summary>
        /// 進程狀態
        /// </summary>
        public ProcessStatus Status;

        /// <summary>
        /// 進程到達時間
        /// </summary>
        public int ArriveTime;

        /// <summary>
        /// 估計運行時間
        /// </summary>
        public int Time;

        /// <summary>
        /// 已運行時間
        /// </summary>
        public int RunTime = 0;

        /// <summary>
        /// 等待時間
        /// </summary>
        public int WaitTime;

        /// <summary>
        /// 優先級
        /// </summary>
        public int Priority;

        /// <summary>
        /// 連接指針
        /// </summary>
        public ProcessControlBlock Next;

        /// <summary>
        /// 開始時間
        /// </summary>
        public int StartTime;

        /// <summary>
        /// 結束時間
        /// </summary>
        public int FinishTime;

        public void Run()
        {
            this.Status = ProcessStatus.Run;

            if (RunTime >= Time) {
                this.Status = ProcessStatus.Finish;
                return;
            }

            this.RunTime++;
        }

        public void Wait()
        {
            this.WaitTime++;
        }

        public override string ToString() => String.Format("{0} {1} {2}", ID, StartTime, FinishTime);
    }
}
  1. CentralProcessUnit.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace OperatingSystemExperiment.Exp1 {
    class CentralProcessUnit {
        private List<ProcessControlBlock> PCBList = new List<ProcessControlBlock>();
        private Queue<ProcessControlBlock> FinishQueue = new Queue<ProcessControlBlock>();
        private Queue<ProcessControlBlock> ReadyQueue = new Queue<ProcessControlBlock>();

        public CentralProcessUnit()
        {
            LoadPcbList();
        } 

        /// <summary>
        /// 生成進程列表
        /// </summary>
        /// <param name="count">進程數量</param>
        public static void GenerateProcessList(int count)
        {
            var processListFile = Path.Combine(Environment.CurrentDirectory, "process_list.txt");
            var writer = new StreamWriter(processListFile);
            var rnd = new Random(DateTime.Now.Millisecond);
            for (var i = 0; i < count; i++) {
                var runTime = rnd.Next(1, 10);
                writer.WriteLine("{0} {1} {2} {3}", i, Math.Pow(2, i), runTime, rnd.Next(0, 4));
            }

            writer.Close();
        }

        /// <summary>
        /// 加載PCB列表
        /// </summary>
        private void LoadPcbList()
        {
            var processListFile = Path.Combine(Environment.CurrentDirectory, "process_list.txt");
            var reader = new StreamReader(processListFile);
            while (!reader.EndOfStream) {
                var line = reader.ReadLine();
                var procInfo = line.Split(' ');
                PCBList.Add(new ProcessControlBlock {
                    ID = int.Parse(procInfo[0]),
                    ArriveTime = int.Parse(procInfo[1]),
                    Time = int.Parse(procInfo[2]),
                    Priority = int.Parse(procInfo[3])
                });
            }
        }

        /// <summary>
        /// CPU運行
        /// </summary>
        public void Run()
        {
            var times = 0;
            while (true) {
                // 若是全部進程運行完,則退出循環
                if (FinishQueue.Count == PCBList.Count) {
                    break;
                }

                // 遍歷全部進程列表
                foreach (var p in PCBList) {
                    // 根據進程到達時間斷定是否有新進程加入,而後將進程狀態設置爲就緒
                    if (p.ArriveTime == times++) {
                        Console.WriteLine("時間:{0},進程 {1} 到達", times, p.ID);
                        p.Status = ProcessStatus.Ready;
                    }

                    // 講就緒狀態進程加入就緒列表
                    if (p.Status == ProcessStatus.Ready) {
//                        Console.WriteLine("時間:{0},進程 {1} 加入就緒列表", times, p.ID);
                        ReadyQueue.Enqueue(p);
                    }

                    // 若是就緒隊列爲空則進入下一次循環
                    if (ReadyQueue.Count == 0) {
//                        Console.WriteLine("時間:{0},沒有就緒進程,進入下一個循環", times);
                        continue;
                    }

                    // 從就緒隊列中取出一個進程運行
                    var currentProcess = ReadyQueue.Dequeue();
                    Console.WriteLine("時間:{0},運行進程 {1}", times, p.ID);
                    currentProcess.Run();

                    // 將運行完畢進程加入完成列表
                    if (currentProcess.Status == ProcessStatus.Finish) {
                        Console.WriteLine("時間:{0},進程 {1} 運行完畢,總運行時間:{2}", times, p.ID, p.RunTime);
                        FinishQueue.Enqueue(currentProcess);
                    }
                    else
                        currentProcess.Status = ProcessStatus.Ready;
                }
            }
        }
    }
}
  1. Main.cs
namespace OperatingSystemExperiment.Exp1
{
    public class Main
    {
        public static void Run()
        {
            CentralProcessUnit.GenerateProcessList(5);
            new CentralProcessUnit().Run();
        }
    }
}

運行結果

  • 生成的process_list.txt內容:
0 1 8 3
1 2 3 1
2 4 8 0
3 8 6 3
4 16 4 1
  • 控制檯輸出

時間:1,運行進程 0
時間:2,運行進程 1
時間:3,運行進程 2
時間:4,運行進程 3
時間:5,運行進程 4
時間:6,運行進程 0
時間:7,運行進程 1
時間:8,運行進程 2
時間:9,進程 3 到達
時間:9,運行進程 3
時間:10,運行進程 4
時間:11,運行進程 0
時間:12,運行進程 1
時間:13,運行進程 2
時間:14,運行進程 3
時間:15,運行進程 4
時間:16,運行進程 0
時間:17,運行進程 1
時間:17,進程 1 運行完畢,總運行時間:3
時間:18,運行進程 2
時間:19,運行進程 3
時間:20,運行進程 4
時間:21,運行進程 0
時間:23,運行進程 2
時間:24,運行進程 3
時間:25,運行進程 4
時間:25,進程 4 運行完畢,總運行時間:4
時間:26,運行進程 0
時間:28,運行進程 2
時間:29,運行進程 3
時間:31,運行進程 0
時間:33,運行進程 2
時間:34,運行進程 3
時間:34,進程 3 運行完畢,總運行時間:6
時間:36,運行進程 0
時間:38,運行進程 2
時間:41,運行進程 0
時間:41,進程 0 運行完畢,總運行時間:8
時間:43,運行進程 2
時間:43,進程 2 運行完畢,總運行時間:8spa

About


瞭解更多有趣的操做請關注個人微信公衆號:DealiAxy
每一篇文章都在個人博客有收錄:blog.deali.cn設計

相關文章
相關標籤/搜索