Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace Betriebssysteme
- {
- class Program
- {
- static void Main(string[] args)
- {
- /* Prozess | 1 2 3 4 5 6 7 8
- Bearbeitungszeit | 4 5 6 1 2 3 4 2
- Ankunftszeit | 1 1 1 1 1 3 4 5 */
- int[,] prozesse = new int[,] { { 4, 1 }, { 5, 1 }, { 6, 1 }, { 1, 1 }, { 2, 1 }, { 3, 3 }, { 4, 4 }, { 2, 5 } };
- int[,] r = roundRobin(prozesse, 3, 2);
- //int[,] r = firstComeFirstServe(prozesse, 3);
- // Print:
- for (int j = 0; j < r.GetLength(1); j++)
- {
- for (int i = 0; i < r.GetLength(0); i++)
- {
- Console.Write(r[i, j]);
- if (i < r.GetLength(0) - 1)
- Console.Write(", ");
- }
- if (j < r.GetLength(1) - 1)
- Console.Write("\n");
- }
- // Press any key to exit
- Console.ReadKey();
- }
- /// <summary>
- /// Erzeugt eine Belegungstabelle für eine
- /// Prozesstabelle mit Bearbeitungszeit [0]
- /// und eine Ankunftszeit [1] nach FCFS.
- /// </summary>
- /// <param name="p">Prozesstabelle (0-basiert)</param>
- /// <param name="k">Kernanzahl</param>
- /// <returns>Die Belegungstabelle</returns>
- static int[,] firstComeFirstServe(int[,] p, int k)
- {
- int[,] r = new int[0, k]; // Lege Ergebnistabelle an
- int i = 0;
- while (notEmpty(p)) // Solange Prozesse eingetragen werden müssen
- {
- r = ResizeArray<int>(r, Math.Max(r.GetLength(0), i + 1), r.GetLength(1)); // Füge Spalte an Tabelle an falls nötig
- for (int j = 0; j < k; j++)
- {
- if (notEmpty(p) && r[i, j] <= 0) // Wenn Zelle leer
- {
- r = setNext(r, p, i, j); // Fülle sie
- p[r[i, j] - 1, 0] = Int32.MaxValue; // Prozess eingetragen
- }
- }
- i++;
- }
- return r;
- }
- /// <summary>
- /// Erzeugt eine Belegungstabelle für eine
- /// Prozesstabelle mit Bearbeitungszeit [0]
- /// und eine Ankunftszeit [1] nach Round
- /// Robin.
- /// </summary>
- /// <param name="p">Prozesstabelle (0-basiert)</param>
- /// <param name="k">Kernanzahl</param>
- /// <param name="timeSlice">Zeitscheibe</param>
- /// <returns>Die Belegungstabelle</returns>
- static int[,] roundRobin(int[,] p, int k, int timeSlice)
- {
- int[,] r = new int[0, k]; // Lege Ergebnistabelle an
- List<int[]> list = new List<int[]>(); // Lege Prozessqueue an
- int i = 0;
- while (notEmpty(p) || list.Count > 0) // Solange in der Liste oder der Queue noch Prozesse sind
- {
- r = ResizeArray<int>(r, Math.Max(r.GetLength(0), i + 2), r.GetLength(1)); // Erweitere das Array um 1 Spalte
- for (int slice = 0; slice < timeSlice; slice++) // Für jeden Zeitpunkt in diesem Slice
- {
- for (int l = p.GetLength(0) - 1; l > -1; l--) // Füge neue Prozesse in die Queue
- if (p[l, 1] == i + slice + 1)
- {
- list.Reverse();
- list.Add(new int[] { l, p[l, 0] }); // Vorher und nacher wird reversed damit der Prozess am Anfang der Liste steht
- list.Reverse();
- p[l, 0] = Int32.MaxValue; // Lösche Prozess aus Liste
- }
- for (int j = 0; j < k; j++) // Für jeden Kern
- {
- if (list.Count > 0 && r[i + slice, j] <= 0) // Wenn Prozesse in der Queue und Zelle leer
- {
- setNextRR(r, list, i + slice, j, slice == 0); // Fülle Zelle
- }
- }
- }
- i += timeSlice;
- }
- return r;
- }
- /// <summary>
- /// Überprüft ob noch Prozesse bearbeitet werden müssen.
- /// </summary>
- /// <param name="p">Prozesstabelle</param>
- /// <returns>true, wenn es einen nicht (fertig) bearbeiteten Prozess gibt</returns>
- static bool notEmpty(int[,] p)
- {
- for (int i = 0; i < p.GetLength(0); i++)
- if (p[i, 0] != Int32.MaxValue)
- return true;
- return false;
- }
- /// <summary>
- /// Hier wird die nächste Zelle in der Tabelle für
- /// einen bestimmten Kern und einen bestimmten
- /// Zeitpunkt bestimmt, nach FCFS.
- /// </summary>
- /// <param name="r">Die Ergebnistabelle (Das Diagramm)</param>
- /// <param name="p">Die aktuelle Prozessqueue</param>
- /// <param name="t">Der Zeitpunkt (0-basiert)</param>
- /// <param name="k">Der Kern (0-basiert)</param>
- /// <returns>Die veränderte Ergebnistabelle</returns>
- static int[,] setNext(int[,] r, int[,] p, int t, int k)
- {
- int i = -1;
- for (int j = 0; j < p.GetLength(0); j++) // Finde den Prozess p = i mit i minimal
- {
- if (p[j, 1] - 1 <= t) // Nur wenn der Prozess angekommen ist
- if (i < 0 || p[i, 1] > p[j, 1])
- i = j;
- }
- r = ResizeArray<int>(r, Math.Max(r.GetLength(0), t + p[i, 0]), r.GetLength(1)); // Füge für jede Bearbeitungszeit von p eine Spalte an, wenn sie noch nicht existiert
- for (int j = t; j < t + p[i, 0]; j++)
- {
- r[j, k] = i + 1; // Füge p so lange ein bis fertig bearbeitet
- }
- return r;
- }
- /// <summary>
- /// Hier wird die nächste Zelle in der Tabelle für
- /// einen bestimmten Kern und einen bestimmten
- /// Zeitpunkt bestimmt, nach Round Robin.
- /// </summary>
- /// <param name="r">Die Ergebnistabelle (Das Diagramm)</param>
- /// <param name="p">Die aktuelle Prozessqueue</param>
- /// <param name="t">Der Zeitpunkt (0-basiert)</param>
- /// <param name="k">Der Kern (0-basiert)</param>
- /// <param name="firstInSlice">true / false je nachdem ob mit diesem t eine neue Zeitscheibe beginnt</param>
- static void setNextRR(int[,] r, List<int[]> p, int t, int k, bool firstInSlice)
- {
- if (firstInSlice) // Am Anfang müssen wir einen Prozess bestimmen der für diesen Slice geschrieben wird
- {
- int[] pro = bestProcess(p, t == 0 ? -1 : r[t-1,k], k, r.GetLength(1)); // Hole ersten Prozess
- r[t, k] = pro[0] + 1; // Schreibe in Grant Diagramm
- p.Remove(pro); // Lösche aus Warteliste
- if (--pro[1] > 0) // Nun 1 Bearbeitungszeit weniger
- p.Add(pro); // Wenn noch bedarf, schreibe wieder rein
- }
- else // Hier nurnoch den gewählten Prozess wiederholen falls noch nicht abgearbeitet
- {
- int pro = r[t - 1, k];
- if (pro <= 0)
- {
- r[t, k] = pro; // Nichts zu tun
- return;
- }
- int[] pr = null;
- for (int i = 0; pr == null && i < p.Count; i++) // Finde den Prozess in der Queue um herauszufinden ob er fertig bearbeitet ist
- {
- if (p[i][0] == pro - 1)
- pr = p[i];
- }
- if (pr == null)
- {
- r[t, k] = 0; // Nichts zu tun
- return;
- }
- r[t, k] = pr[0] + 1; // Schreibe in Ergebnistabelle
- if (--pr[1] <= 0) // Nun 1 Bearbeitungszeit weniger
- p.Remove(pr); // Lösche aus Warteliste wenn kein Bedarf mehr
- }
- }
- /// <summary>
- /// Wir müssen berücksichtigen, dass der erste Prozess
- /// in der Liste vielleicht nicht der beste ist, den
- /// wir zur Zeit nehmen können. Z.B. Soll immer die
- /// kleinste Zahl zu erst geschrieben werden, außerdem
- /// sollen Kernwechsel minimiert werden.
- /// </summary>
- /// <param name="p">Die aktuelle Prozessqueue</param>
- /// <param name="last">Der Prozess der als letztes in diesem Kern ausgeführt wurde</param>
- /// <param name="kern">Aktueller Kern (0-basiert)</param>
- /// <param name="kernN">Anzahl Kerne</param>
- /// <returns>Der passende Prozess</returns>
- public static int[] bestProcess(List<int[]> p, int last, int kern, int kernN)
- {
- if (kern == kernN - 1)
- return p[0];
- int[] r = null;
- for (int i = 0; i < p.Count && i < kernN-kern; i++)
- {
- if (p[i][0] == last-1)
- return p[i];
- if (r == null || r[0] > p[i][0])
- r = p[i];
- }
- return r;
- }
- /// <summary>
- /// Verändert die Größe eines 2D-Arrays.
- /// Quelle: Internet
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="original"></param>
- /// <param name="rows"></param>
- /// <param name="cols"></param>
- /// <returns></returns>
- static T[,] ResizeArray<T>(T[,] original, int rows, int cols)
- {
- var newArray = new T[rows, cols];
- int minRows = Math.Min(rows, original.GetLength(0));
- int minCols = Math.Min(cols, original.GetLength(1));
- for (int i = 0; i < minRows; i++)
- for (int j = 0; j < minCols; j++)
- newArray[i, j] = original[i, j];
- return newArray;
- }
- /// <summary>
- /// Löscht eine Zeile aus einem Array.
- /// Quelle: Internet
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="originalArray"></param>
- /// <param name="rowToRemove"></param>
- /// <returns></returns>
- public static T[,] TrimArray<T>(T[,] originalArray, int rowToRemove)
- {
- return TrimArray<T>(originalArray, rowToRemove, -1);
- }
- /// <summary>
- /// Löscht eine Zeile und eine Spalte aus einem Array.
- /// Quelle: Internet
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="originalArray"></param>
- /// <param name="rowToRemove"></param>
- /// <param name="columnToRemove"></param>
- /// <returns></returns>
- public static T[,] TrimArray<T>(T[,] originalArray, int rowToRemove, int columnToRemove)
- {
- T[,] result = new T[originalArray.GetLength(0) - 1, originalArray.GetLength(1) - (columnToRemove == -1 ? 0 : 1)];
- for (int i = 0, j = 0; i < originalArray.GetLength(0); i++)
- {
- if (i == rowToRemove)
- continue;
- if (originalArray.GetLength(0) > 1)
- for (int k = 0, u = 0; k < originalArray.GetLength(1); k++)
- {
- if (k == columnToRemove)
- continue;
- result[j, u] = originalArray[i, k];
- u++;
- }
- j++;
- }
- return result;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement