diff --git a/README.md b/README.md deleted file mode 100644 index f125f62..0000000 --- a/README.md +++ /dev/null @@ -1,133 +0,0 @@ -### Erklärung des Programms und seiner Funktionsweise - -#### 1. Grundlegende Struktur -Das Programm simuliert einen präemptiven Scheduler nach dem Round-Robin-Prinzip für einen Mikrocontroller. Es verwaltet mehrere Tasks (Prozesse), die aus Dateien gelesen werden und abwechselnd Rechenzeit erhalten. - -#### 2. Wichtige Komponenten -- **Task-Struktur**: Repräsentiert einen Prozess - ```cpp - struct Task { - int pid; // Prozess-ID - std::string filename; // Dateiname des Tasks - std::vector> program; // Befehlsliste - int pc; // Program Counter - int accu; // Akkumulator-Wert - int blocked; // Verbleibende Blockierungszeit - int start_tick; // Startzeitpunkt - int end_tick; // Endzeitpunkt - bool terminated; // Status ob beendet - int slice_remaining; // Verbleibende Zeitscheibenzeit - }; - ``` - -#### 3. Ablauf des Programms - -**A. Initialisierung** -```cpp -auto init_program = readFile("init"); // Liest init-Datei OHNE .txt -Task init_task = { - next_pid++, // PID 0 - "init", // Dateiname - init_program, // Programmcode - 0, // PC startet bei 0 - 0, // Akku startet bei 0 - 0, // Nicht blockiert - 0, // Start bei Tick 0 - -1, // Ende noch nicht bekannt - false, // Noch nicht terminiert - time_slice // Volle Zeitscheibe -}; -tasks.push_back(init_task); -``` - -**B. Hauptschleife - Der Scheduler** -```cpp -while (!all_terminated) { - // 1. Suche nächsten ausführbaren Task (Round-Robin) - // 2. Führe Task aus (so lange Zeitscheibe reicht) - // 3. Verarbeite Blockierungszeiten - // 4. Prüfe auf Terminierung -} -``` - -**C. Task-Ausführung** -Für jeden Befehl: -```cpp -if (command == "LOAD") { - current_task->accu = std::stoi(param); -} else if (command == "ADD") { - current_task->accu += std::stoi(param); -} else if (command == "SUB") { - current_task->accu -= std::stoi(param); -} else if (command == "READ") { - current_task->accu = rand() % 4096; // Zufallswert 0-4095 - current_task->blocked = 2; // 2 Takte blockieren -} else if (command == "EXE") { - // NEU: Direkt param verwenden OHNE .txt - std::string filename = param; - auto new_program = readFile(filename); - // Neuen Task erstellen und hinzufügen -} else if (command == "T") { - current_task->terminated = true; -} -``` - -**D. Besondere Logik** -- **Blockierung**: Bei `READ` wird der Task für 2 Takte blockiert -- **EXE-Befehl**: Startet neuen Task mit eigenem Programm -- **Zeitscheibe**: Task läuft maximal `time_slice` Befehle am Stück -- **IDLE**: Wenn alle Tasks blockiert sind - ```cpp - std::cout << current_tick << "\tIDLE" << std::endl; - ``` - -**E. Statistik am Ende** -Ausgabe für jeden Task: -```cpp -PID Task Start Ende Verweilzeit Akku -0 init 0 12 13 7 -1 file_a 3 8 6 19 -... -``` - -#### 4. Durchgeführte Änderungen -Ihre Anpassungen sind hier besonders wichtig: -```cpp -// Vorher: "init.txt" -> Jetzt: "init" -auto init_program = readFile("init"); - -// Vorher: param + ".txt" -> Jetzt: direkt param -std::string filename = param; -auto new_program = readFile(filename); -``` - -**Begründung**: -- Die Aufgabenstellung gibt Dateien ohne `.txt`-Erweiterung vor (init, file_a, etc.) -- Die Funktion `readFile` versucht direkt den übergebenen Namen zu öffnen -- Ohne Änderung würde das Programm nach nicht existierenden Dateien suchen (z.B. "file_a.txt" statt "file_a") - -#### 5. Beispielablauf -Für init.txt mit: -``` -LOAD 5 -ADD 3 -EXE file_a -``` - -1. Tick 0: Lädt `LOAD 5` in init-Task -2. Tick 1: Führt `ADD 3` aus (Akku=8) -3. Tick 2: Startet neuen Task aus file_a -4. Abwechselnde Ausführung beider Tasks - -#### 6. Besondere Szenarien -- **Alle Tasks blockiert**: - - Scheduler gibt "IDLE" aus - - Blockierungszeiten werden dekrementiert -- **EXE in mehreren Tasks**: - - Neue Tasks werden sofort zur Ausführung hinzugefügt - - Können vor dem Eltern-Task terminieren -- **Zeitscheibe zu Ende**: - - Task wird unterbrochen (präemptiv) - - Zustand (PC, Akku) wird gespeichert - - Nächster Task in Round-Robin-Reihenfolge kommt dran - diff --git a/einlesen.cpp b/einlesen.cpp index 4883f9f..9487db0 100644 --- a/einlesen.cpp +++ b/einlesen.cpp @@ -1,228 +1,47 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "task.h" +#include -struct Task { - int pid; - std::string filename; - std::vector> program; - int pc; - int accu; - int blocked; - int start_tick; - int end_tick; - bool terminated; - int slice_remaining; -}; +using namespace std; -std::vector> readFile(const std::string &filename) { - std::vector> instructions; - std::ifstream file(filename); +vector > readFile(const string &filename) { + vector > instructions; + ifstream file(filename); if(!file.is_open()) { - std::cerr << "Fehler: Datei " << filename << " konnte nicht geöffnet werden.\n"; + cerr << "Fehler: Datei " << filename << " konnte nicht geöffnet werden.\n"; return instructions; } - std::string line; - while (std::getline(file, line)) { + string line; + while (getline(file, line)) { + // Entferne führende oder trailing Whitespace if (line.empty()) continue; - std::istringstream iss(line); - std::string command; - std::string param; + istringstream iss(line); + string command; + string param; if (!(iss >> command)) { + // Keine gültige Eingabe in dieser Zeile continue; } + // Optionalen Parameter einlesen, falls vorhanden if (!(iss >> param)) { + // Kein Parameter vorhanden param = ""; } - instructions.push_back(std::make_pair(command, param)); + instructions.push_back(make_pair(command, param)); } return instructions; } -int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Verwendung: " << argv[0] << " " << std::endl; - return 1; - } - int time_slice = std::stoi(argv[1]); - srand(time(0)); - - std::vector tasks; - int next_pid = 0; - int current_tick = 0; - - // Initialen Task aus init erstellen - auto init_program = readFile("init"); - if (init_program.empty()) { - std::cerr << "Fehler: init konnte nicht gelesen werden." << std::endl; - return 1; - } - Task init_task = { - next_pid++, - "init", - init_program, - 0, - 0, - 0, - 0, - -1, - false, - time_slice - }; - tasks.push_back(init_task); - - // Header ausgeben - std::cout << "Tick\tPID\tTask\tPC\tAccu\tInstr" << std::endl; - - int last_executed_index = -1; - bool all_terminated = false; - - while (!all_terminated) { - all_terminated = true; - bool found_runnable = false; - int start_index = (last_executed_index + 1) % tasks.size(); - int current_index = start_index; - Task* current_task = nullptr; - - do { - Task& task = tasks[current_index]; - if (!task.terminated && task.blocked == 0) { - current_task = &task; - found_runnable = true; - last_executed_index = current_index; - break; - } - current_index = (current_index + 1) % tasks.size(); - } while (current_index != start_index); - - if (found_runnable) { - while (current_task->slice_remaining > 0 && !current_task->terminated && current_task->blocked == 0) { - // Hole Befehl - auto& instruction = current_task->program[current_task->pc]; - std::string command = instruction.first; - std::string param = instruction.second; - - // Ausgabe des aktuellen Zustands - std::cout << current_tick << "\t" - << current_task->pid << "\t" - << current_task->filename << "\t" - << current_task->pc << "\t" - << current_task->accu << "\t" - << command; - if (!param.empty()) { - std::cout << " " << param; - } - std::cout << std::endl; - - // Führe Befehl aus - if (command == "LOAD") { - current_task->accu = std::stoi(param); - } else if (command == "ADD") { - current_task->accu += std::stoi(param); - } else if (command == "SUB") { - current_task->accu -= std::stoi(param); - } else if (command == "READ") { - current_task->accu = rand() % 4096; - current_task->blocked = 2; - } else if (command == "EXE") { - std::string filename = param; - auto new_program = readFile(filename); - if (!new_program.empty()) { - Task new_task = { - next_pid++, - param, - new_program, - 0, - 0, - 0, - current_tick + 1, - -1, - false, - time_slice - }; - tasks.push_back(new_task); - } - } else if (command == "T") { - current_task->terminated = true; - current_task->end_tick = current_tick; - } - - // PC erhöhen, außer bei Terminierung - if (command != "T") { - current_task->pc++; - if (current_task->pc >= current_task->program.size()) { - current_task->terminated = true; - current_task->end_tick = current_tick; - } - } - - // Blockierungszeit für andere Tasks dekrementieren - for (auto& task : tasks) { - if (task.blocked > 0) { - if (&task == current_task && command == "READ") { - // Nicht dekrementieren - } else { - task.blocked--; - } - } - } - - // Zeitscheibe verbrauchen - current_task->slice_remaining--; - current_tick++; - - // Bei Blockierung oder Terminierung Schleife verlassen - if (current_task->blocked > 0 || current_task->terminated) { - break; - } - } - - // Zeitscheibe zurücksetzen - current_task->slice_remaining = time_slice; - } else { - // Kein lauffähiger Task (IDLE) - std::cout << current_tick << "\tIDLE" << std::endl; - for (auto& task : tasks) { - if (task.blocked > 0) { - task.blocked--; - } - } - current_tick++; - } - - // Prüfen, ob noch aktive Tasks existieren - for (const auto& task : tasks) { - if (!task.terminated) { - all_terminated = false; - break; - } - } - } - - // Statistik ausgeben - std::cout << "\nStatistik:" << std::endl; - std::cout << "PID\tTask\tStart\tEnde\tVerweilzeit\tAccu" << std::endl; - for (const auto& task : tasks) { - int turnaround = task.end_tick - task.start_tick + 1; - std::cout << task.pid << "\t" - << task.filename << "\t" - << task.start_tick << "\t" - << task.end_tick << "\t" - << turnaround << "\t\t" - << task.accu << std::endl; +// Beispiel zur Nutzung +int main() { + auto result = readFile("init"); + for (const auto &inst : result) { + cout << "Befehl: " << inst.first << " | Parameter: " << inst.second << "\n"; } return 0; diff --git a/task.cpp b/task.cpp new file mode 100644 index 0000000..222621f --- /dev/null +++ b/task.cpp @@ -0,0 +1,15 @@ +#include + +Task::Task(int pid, + const std::string &name, + const std::vector> &program) +{ + this->pid=pid; + this->name=name; + this->program=program; + this->pc=0; + this->acc=0; + this->blockTicks=0; + this->active=true; +} + diff --git a/task.h b/task.h new file mode 100644 index 0000000..b0f775e --- /dev/null +++ b/task.h @@ -0,0 +1,28 @@ +#ifndef TASK_H +#define TASK_H + +#include +#include +#include +#include +#include +#include +#include + +class Task +{ +public: + Task()=delete; + Task(int pid, const std::string &name, const std::vector> &program); +private: + int pid, + pc, + acc, + blockTicks; + std::string name; + std::vector> program; + bool active; +}; + + +#endif //TASK_H