Musterlösung oder so

This commit is contained in:
portnoytmy 2025-06-16 10:12:02 +02:00
parent 469ad9bb65
commit 03ec564fa1
3 changed files with 245 additions and 11 deletions

30
.gitignore vendored Normal file
View file

@ -0,0 +1,30 @@
# Build-Verzeichnisse
build/
bin/
lib/
# CMake-Dateien
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
# Compiled Object files
*.o
*.obj
# Shared objects
*.so
*.dylib
*.dll
# Executables
*.exe
*.out
*.app
# IDE-spezifische Dateien
.vscode/
.idea/
*.swp
*~

25
CMakeLists.txt Normal file
View file

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.10)
project(BS_Praktikum5 VERSION 0.1.0 LANGUAGES CXX)
# Compiler-Optionen
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Warnungen und Debug-Informationen bei Entwicklung aktivieren
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -g")
endif()
# Aktuelles Verzeichnis als Include-Pfad hinzufügen
include_directories(.)
# Quellen sammeln
file(GLOB SOURCES *.cpp)
file(GLOB HEADERS *.h *.hpp)
# Ausführbare Datei erstellen
add_executable(${PROJECT_NAME} ${SOURCES})
# Installation konfigurieren
install(TARGETS ${PROJECT_NAME} DESTINATION bin)

View file

@ -4,9 +4,26 @@
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <sstream> #include <sstream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <iomanip>
std::vector<std::pair<std::string, std::string> > readFile(const std::string &filename) { struct Task {
std::vector<std::pair<std::string, std::string> > instructions; int pid;
std::string filename;
std::vector<std::pair<std::string, std::string>> program;
int pc;
int accu;
int blocked;
int start_tick;
int end_tick;
bool terminated;
int slice_remaining;
};
std::vector<std::pair<std::string, std::string>> readFile(const std::string &filename) {
std::vector<std::pair<std::string, std::string>> instructions;
std::ifstream file(filename); std::ifstream file(filename);
if(!file.is_open()) { if(!file.is_open()) {
std::cerr << "Fehler: Datei " << filename << " konnte nicht geöffnet werden.\n"; std::cerr << "Fehler: Datei " << filename << " konnte nicht geöffnet werden.\n";
@ -15,7 +32,6 @@ std::vector<std::pair<std::string, std::string> > readFile(const std::string &fi
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
// Entferne führende oder trailing Whitespace
if (line.empty()) continue; if (line.empty()) continue;
std::istringstream iss(line); std::istringstream iss(line);
@ -23,13 +39,10 @@ std::vector<std::pair<std::string, std::string> > readFile(const std::string &fi
std::string param; std::string param;
if (!(iss >> command)) { if (!(iss >> command)) {
// Keine gültige Eingabe in dieser Zeile
continue; continue;
} }
// Optionalen Parameter einlesen, falls vorhanden
if (!(iss >> param)) { if (!(iss >> param)) {
// Kein Parameter vorhanden
param = ""; param = "";
} }
@ -39,11 +52,177 @@ std::vector<std::pair<std::string, std::string> > readFile(const std::string &fi
return instructions; return instructions;
} }
// Beispiel zur Nutzung int main(int argc, char* argv[]) {
int main() { if (argc < 2) {
auto result = readFile("init"); std::cerr << "Verwendung: " << argv[0] << " <Zeitscheibenlänge>" << std::endl;
for (const auto &inst : result) { return 1;
std::cout << "Befehl: " << inst.first << " | Parameter: " << inst.second << "\n"; }
int time_slice = std::stoi(argv[1]);
srand(time(0));
std::vector<Task> 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;
} }
return 0; return 0;