133 lines
4.2 KiB
Markdown
133 lines
4.2 KiB
Markdown
### 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<std::pair<std::string, std::string>> 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
|
|
|