This commit is contained in:
David Schirrmeister
2024-12-05 13:53:10 +01:00
parent 2339530e42
commit 73e1392286
57 changed files with 7 additions and 0 deletions

View File

@ -0,0 +1,29 @@
# Betriebssysteme heute
## Einsatzgebiete
- Desktop / Laptop
- Heim- und Büroanwendungen
- Eingebettete Systeme
- Industrieautomation, Fahrzeuge, etc.
- Mobilgeräte
- Smartphones, Tablets, etc.
- Server
- Datacenter, Großrechner, Cloud- / Grid-Computing
## Vielfältige Peripherie
- WLAN, Bluetooth, 3G/5G/5G
- CD, DVD, HDD, SSD, Flash-Memory, USB-Storage
- LCD-/OLED-Displays, Touchscreens
- Keyboard, Mouse, Touchpad
- Drucker, Scanner
- GPS
- Gyroskop
- ...
## Schnittstellen
Zur Vereinfachung der Programmierung existieren spezielle vom Betriebssystem bereitgestellte Funktionen (Systemaufrufe) bspw. für:
- Prozesse
- Dateisystem
- Ein-/Ausgabe
- ...
Standardisierung ([POSIX](06_prozessstruktur.md#posix-api) ermöglicht Portierung von Anwendungen über Plattform-Grenzen hinweg

View File

@ -0,0 +1,75 @@
# Betriebssystemkerne
> Gute **Architektur** sagt und _warum_ etwas getan wurde.
> Nicht _wie_ und nicht _wann_ und _wer_.
## Der Betriebssystemkern
- Enthält grundlegende Funktionen des Betriebssystems
- Systemaufrufe
- Benutzerverwaltung
- Prozessverwaltung inklusive Ausführungsreihenfolge ([Scheduling](06_prozessstruktur.md#zeitliche-ausf-hrung-von-prozessen))
- Interprozesskommunikation
- Prozessumschalter ([Dispatcher](06_prozessstruktur.md#zeitliche-ausf-hrung-von-prozessen))
- Gerätetreiber
- [Speicherverwaltung](06_prozessstruktur.md#prozesse-im-speicher)
- Dateisysteme zur Verwaltung von Dateien auf Speicherlaufwerken
- Ist die Schnittstelle zur Hardware des Computers
- Funktionalitäten im BS-Kern haben vollen Hardwarezugriff
- Funktionalitäten laufen als Prozess im Adressraum des Kerns
- Funktionalitäten müssen nicht zwingend im Kern positioniert sein, sie können auch über Dienste bereitgestellt werden (Architektur)
## Übersicht Betriebssystem
![image_17.png](image_17.png)
### Betriebssystemkern
- Der **Kernel-Bereich** ist privilegiert
### Die Anwendungsschicht
- Der **User-Bereich** ist nicht privilegiert, kann aber darauf aufbauende Funktionalitäten bereitstellen
- Zugriff auf die Hardware erfolgt alleinig durch die im _Kernel_ bereitgestellten Funktionalitäten (System-Calls)
## Kernarten
### Monolitische Kerne
Ein Monolith enthält alle Funktionalitäten eines Betriebssystems
| Pro | Con |
|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| Bessere **Ausführungsgeschwindigkeit** da weniger _Prozesswechsel_ notwendig sind | Abgestürzte Komponenten des Kerns können nicht separat neu gestartet werden -> können das gesamte BS zum Absturz bringen |
| Durch jahrelange Entwicklungstätigkeit ist eine gewachsene **Stabilität** vorhanden | |
### Minimale Kerne (Microkernel)
Hier befinden sich nur die nötigsten Funktionen im Kernel
| Pro | Con |
|--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| Alle weiteren Funktionalitäten laufen als _Dienste_ bzw. _Server_ im User-Modus | Abgestürzte Komponenten des Kerns können nicht separat neu gestartet werden -> können das gesamte BS zum Absturz bringen |
| Ausgelagerte Funktionalitäten sind leichter austauschbar, bietet bessere _Stabilität_ und _Sicherheit_ | |
### Hybride Kerne
Enthalten Komponenten, die, aus Geschwindigkeitsgründen, zusätzlich in den Kernel aufgenommen werden
| Pro | Con |
|-------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| höhere Geschwindigkeit als minimale Kerne | keine klare Definition, was in den Kernel integiert wird |
| höhere Stabilität als monolithische Kerne | Systeme differieren stark -> kann zu einer fehlenden Unterstützung der Hardware- und Software-Hersteller führen |
### Vergleich monolithischer Kern / minimaler Kern
![image_18.png](image_18.png)
## Alternative Architekturen
_Flaschenhals_ alle bestehenden Systeme liegt in ihren Schichtenmodellen
- Anwendung hat _keinen direkten Zugriff auf Hardware_
- _Kommunikation und Datenfluss_ wird über Bibliotheken und deren Kernel abgewickelt
- _Zugangskontrolle_ weiterhin über Bibliotheken und Kernel
## Programmierschnittstellen
**Systemaufruf (System Call)** ist eine API, die es ermöglicht auf Dienste und Ressourcen des BS zuzugreifen
- Implementierung von Systemaufrufen hängt stark von _Hardware_, _Architektur_, _BS_ ab
- ![image_19.png](image_19.png)
- Wann werden die benutzt?
- Berechtigungen, Ressourcenverwaltung, Kommunikation mit Hardware, Prozesssteuerung, Netzwerkkommunikation, Zeitverwaltung
- Nutzung eines direkten Systemaufrufs **nicht empfehlenswert**
- Software ist schlecht portierbar
- Auf Funktionen von Bibliotheken zurückgreifen
- befinden sich mit entsprechenden Wrapper-Funktionen logisch zwischen Benutzer- und BS-Kern

View File

@ -0,0 +1,65 @@
# Prozesszustände
- Bereit (Ready)
- Laufend (Running)
- Blockiert (Blocked)
- Beendet (Terminated)
## 2-Zustands-Modell
![image.png](image.png)
Prozesse, die untätig werden, werden in einer Warteschlange gespeichert
- Wird nach Priorität / Wartezeit sortiert
![image_1.png](image_1.png)
#### Pro
- Einfach realisierbar
#### Contra
- Annahme, dass Prozesse jederzeit zur Ausführung bereit sind
- Es gibt blockierte Prozesse
- Wartet auf Ein-/Ausgabe
- Wartet auf Ergebnis eines anderen Prozesses
- Wartet auf Reaktion eines Benutzers
## 3-Zustands-Modell
### Ereignisbezogene Warteschlangen
![image_3.png](image_3.png)
- Für jedes Ereignis, auf welches ein Prozess wartet, gibt es eine Warteschlange
- Tritt das Ereignis ein, werden alle Prozesse der WS in die WS mit den *ready* Prozessen überführt
![image_2.png](image_2.png)
## 5-Zustands-Modell
Anzahl der ausführbaren Prozesse *limitieren*, um Speicher zu sparen
- Zwei weitere Zustände:
- **new (new)**
- Prozesse, deren PCB das Betriebssystem bereits erzeugt hat, aber noch nicht in der Warteschlange sind
- **beendet (exit)**
- Abgearbeitete oder abgebrochene Prozesse, deren PCB und Eintrag noch nicht aus der Prozesstabelle entfernt wurden
![image_4.png](image_4.png)
## 6-Zustands-Modell
Falls nicht genügend physischer Hauptspeicher für alle Prozesse:
- **Auslagerungsspeicher (Swap)**
- Zustand: **suspendiert (suspended)**
- dadurch steht den Prozessen in den Zuständen _rechnend_ und _bereit_ mehr Hauptspeicher zur Verfügung
![image_5.png](image_5.png)
## 7-Zustands-Modell
![image_6.png](image_6.png)
## Zustands-Modell von Linux
- ähnlich wie [7-Zustands-Modell](#7-zustands-modell)
- Zustand _rechnend_:
- **benutzer rechnend (user running)**
- Prozesse im Benutzermodus
- **kernel rechnend (kernel running)**
- Prozesse im Kernel-Modus
- Zustand _beendet (exit)_ = _Zombie_
- ist fertig abgearbeitet
- Eintrag in der Prozesstabelle existiert noch bis Elternprozess den Rückgabewert abgefragt hat#
![image_7.png](image_7.png)

View File

@ -0,0 +1,75 @@
# Prozessstruktur
## Prozessdarstellung
- Umfasst [_Zustände_](05_prozesszustaende.md) und _Struktur_ eines laufenden Programms
- Grundlegende Komponenten, die die _Speicherrepräsentation_ eines Prozesses vorhanden sein können
- Systemumgebung
- Stack
- Heap
- BSS (Block Started by Symbol)
- Datensegment
- Codesegment
- ![image_8.png](image_8.png)
Beispiel: Terminalbefehl **- size**
- ![image_9.png](image_9.png)
## Prozesse im Speicher
- ![image_10.png](image_10.png)
- Ablage im physischen Speicher erfolgt in nicht fortlaufender Weise durch den virtuellen Speicher
- nicht zwangsläufig ständig im Hauptspeicher
## Erzeugung von Prozesskopien
- Systemaufruf **fork** unter Linux/Unix
- Erzeugung einer _identischen Kopie_ eines Prozesses
- aufrufender Prozess: _Elternprozess (Parent Process)_
- neuer Prozess: _Kind-Prozess_ (Child Process)
- hat gleichen _Programmcode_ und _Befehlszähler_
- verweist auf gleiche Zeile im Programmcode
- Speicherbereiche von Kind- und Elternprozess streng getrennt
- ![image_11.png](image_11.png)
## Erzeugung von neuen Prozessen
- Systemaufruf **exec**
- Ersetzt bestehenden Prozess durch einen anderen
- neuer Prozess erbt PID des aufrufenden Prozesses
- ![image_12.png](image_12.png)
- Soll aus einem Prozess (_bspw. Kommandozeilen-Interpreter (Shell)_) heraus ein Programm gestartet werden:
- _fork_ -> _exec_
- ![image_13.png](image_13.png)
## Übersicht Erzeugung/Verkettung/Vergabelung
![image_14.png](image_14.png)
## Beenden von Prozessen
Arten des Beendens:
- Normales Beenden (freiwillig, im Code definiert)
- Beenden aufgrund eines Fehlers (freiwillig, im Code definiert)
- Beenden aufgrund eines schwerwiegenden Fehlers (unfreiwillig, durch BS)
- Beenden durch einen anderen Prozess (unfreiwillig)
Unix Befehl: **kill** erstellt einen Wrapper um BS-Aufruf _kilL()_
- ist auf jedem Unix als alleinstehende Anwendung vorhanden (_/bin/kill_)
## Zeitliche Ausführung von Prozessen
- **Scheduler** ist wichtige Komponente des Betriebssystems
- Zuständig für Zuweisung von CPU-Ressourcen an laufenden Prozessen
- Hauptaufgabe: _Reihenfolge_ festlegen
- **Dispatcher**: Umsetzung der Scheduling-Entscheidungen
- Implementierung der Entscheidung
- Wechsel des _Kontrollflusses_ von einem laufenden Prozess zu einem anderen
- Einleiten des Umschaltens durch einen _Timer-Interrupt_
- Interrupt wird periodisch ausgelöst und startet entsprechende Softwareroutine
- ![image_15.png](image_15.png)
- ![image_16.png](image_16.png)
## POSIX-API
_Portable Operating System Interface_
- Standard, der von der IEE(_Institute of Electrical and Electronics Engineers_) entwickelt wurde
- Definiert Schnittstelle zwischen Anwendung und Betriebssystem
- erleichtert Portabilität von Software zwischen verschiedenen Unix BS
- bspw:
- fork, wait/waitpid, sleep, getpid/getppid/setpgid, execl/execv/execve, kill, ...

View File

@ -0,0 +1,161 @@
# Prozesssynchronisation
## Warum überhaupt Synchronisation?
- mehrere Prozesse arbeiten in einem System koordiniert und in einer bestimmten Reihenfolge/zeitlichen Abfolge
- Multitasking- /Multiprozessor-System
- mehrere Prozesse gleichzeitig / parallel
- Prozesse interagieren miteinander
- Zugriff auf gemeinsame Ressourcen
- Warten auf Operationen (_Wait and Signal_)
- Kritischer Abschnitt (_Critical Section_)
- Rennbedingungen (_Race Conditions_)
- Mutex (_Mutex Lock_)
- Semaphore
- Deadlocks und Ressourcenkonflikte
- Interprozesskommunikation (_IPC_)
## Signale
- dienen als Mechanismus für die Kommunikation
- zwischen Prozessen
- zwischen Betriebssystem und Prozessen
- Signal ist eine Benachrichtigung and ein Prozess, dass Ereignis aufgetreten ist
### Zweck
- Behandlung von Ausnahmen
- Kommunikation von Ereignissen
- Steuerung von Prozessen
- Ermöglicht
- Implementierung von asynchronen Benachrichtigungen
- Behandlung von außergewöhnlichen Ereignissen
### Beispiel
Terminalbefehl **- man signal**
![image_83.png](image_83.png)
### Signalhandler
- Funktion/Codeabschnitt, welcher _onSignal_ ausgeführt wird
#### Was passiert beim Aufruf eines Signalhandlers
- Prozess wird bei Eintreffen eines Signals angehalten
- Prozesszustand wird gesichert
- Signalhandler wird aufgerufen
- darf beliebige Systemaufrufe veranlassen (_sollte sie aber nicht_)
- Bei Beendigung des Signalhandlers
- Prozess läuft weiter wo er unterbrochen wurde
## Warten
### Aktives Warten (Polling)
- Prozess prüft ob Bedingung erfüllt ist
- _bspw. in Schleifenstrukturen_
```c++
while (!Bedingung){
//aktives Warten
}
```
### Passives Warten
- Prozess wird in Wartezustand versetzt
- wird reaktiviert, wenn Bedingung erfüllt wurde
- währenddessen können andere Prozesse auf der CPU laufen
```c++
wait_for_condition(); //Prozess geht in Wartezustand
//Irgendwann Reaktivierung
resume_execution();
```
## Sperren
- Koordiniert Zugriff auf gemeinsame Ressourcen durch mehrere Prozesse oder Threads
- Nur ein Prozess/Thread gleichzeitig
- Dateninkonsistenzen oder Rennbedingungen werden vermieden
## Mutex (Mutual Exclusion)
- Sperre, welche exklusiven Zugriff auf Ressource steuert
- Prozess sperrt/entsperrt vor/nach Zugriff auf Ressource
### Nutzung
- Dateizugriffe
- Netzwerkkommunikation
- Zugriff auf gemeinsam genutzte Datenstrukturen
- Hardware
## Semaphores
- Ähnlich wie Mutex, nur zusätzlich mit Kommunikation durch [Signale](#signale)
## Mutex vs Semaphore
Befehle mit [POSIX API](06_prozessstruktur.md#posix-api)
### Mutex
- **pthread_mutex_t** _Datentyp für Mutex_
- **pthread_mutex_init** _Erzeugen eines Mutexobjekts_
- **pthread_mutex_unlock** _Entsperren_
- **pthread_mutex_lock** _Sperren_
- **pthread_mutex_trylock** _Versuchendes Sperren_
- **pthread_mutex_destroy** _Löschen des Mutexobjekts_
### Semaphore
- **sem_t** _Datentyp für Semaphor_
- **sem_init** _Initialisieren eines Semaphors (notwendig)_
- **sem_post** _up Operation: Semaphor um 1 erhöhen_
- **sem_wait** _down Operation: Semaphor um 1 vermindern oder blockieren_
- **sem_trywait** _wie sem_wait, aber Aufruf kehrt zurück, falls sem_wait blockieren würde_
- **sem_timedwait** _wie sem_wait, aber mit time-out, falls blockiert_
- **sem_getvalue** _Wert des Semaphors auslesen_
- **sem_destroy** _Löschen eines Semaphors_
### Was nimmt man jetzt?
> Hängt von Anforderungen und Charakteristiken des spezifischen Anwendungsfalls ab
>
> Es ist wichtig, Synchronisationsmechanismen sorgfältig zu verwenden,
> um sicherzustellen, dass kritische Abschnitte effizient und sicher koordiniert werden
- **Praktisches Anwendungsbeispiel: Siehe Praktikum 4**
- Postverteilungszentrum bestückt Verteiler der Post
- Konfliktsituationen:
- wer wird jetzt grad bestückt?
- wie viele kann man gleichzeitig bedienen?
- Wann ist ein Verteiler voll?
- Welcher Postbote darf zuerst an den Briefkasten dran?
- Mutex - Briefkasten freigegeben / gesperrt
- Muss geklingelt werden (bspw. Einschreiben)
- Semaphore - weil es muss benachrichtigt werden
## Deadlock
(Stillstand / Blockade) ist eine Situation, bei der zwei oder mehr Prozesse auf unbestimmte Weise blockiert sind, weil sie auf die Freigabe von Ressourcen warten
### Entstehungsbedingungen von Deadlocks
- **Gegenseitiger Ausschluss**
- Mindestens eine Ressource muss exklusiv für immer nur einen Prozess sein
- **Warte-Zustand**
- Prozess hält eine Ressource und wartet bis er die nächste kriegt
- **Nicht-Preemption**
- Ressourcen können nicht zwangsweise (_sondern nur freiwillig_) von Prozess/Thread entzogen werden
- **Zyklus in den Wartebeziehungen**
- Kette von Prozessen/Threads
- P1 wartet auf Ressource von P2, P2 auf P3, ..., PN auf P1
### Erkennung von Deadlocks
_Betriebsmittelgraf_ (Ressource Allocation Graph)
- Modelliert _Zuteilung und Freigabe_ von Ressourcen zwischen Prozessen
![image_84.png](image_84.png)
- Falls es mehrere Instanzen einer Ressource gibt
- **matrizen-basiertes Verfahren**
- Ressourcenvektor
- Belegungsmatrix
- Anforderungsmatrix
- Ressourcenrestvektor
#### Beispiel Erkennung von Deadlocks
![image_85.png](image_85.png)
![image_86.png](image_86.png)
### Livelock
- Form der Blockierung von 2 oder mehr Prozessen, welche aber ständig zwischen mehreren Zuständen wechseln und ihnen nicht entkommen können
- Bspw.:
- 2 Personen kommen sich auf dem Gang entgegen und weichen die ganze Zeit in die gleiche Richtung aus
- Deadlock:
- Personen stehen gegenüber und warten bis der andere beiseite geht, was nicht passiert

View File

@ -0,0 +1,73 @@
# Threads
- **Kleinste ausführbare Einheit** innerhalb eines Prozesses
- ermöglichen **flexiblere**, **reaktionsschnellere** und **effizientere** Programmierung
- müssen sorgfältig überwacht werden, um Probleme zu vermeiden
- bspw. [Deadlocks](07_Prozesssynchronisation.md#deadlock) oder Rennbedingungen
## Threads vs Prozesse
| **Merkmal** | **Thread** | **Prozess** |
|-------------------------------------------------|-----------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| Definition | Kleinste ausführbare Einheit innerhalb eines Prozesses | Unabhängiges Programm in Ausführung |
| Ressourcenzuweisung | Teilen denselben Adressraum & Ressourcen innerhalb eines Prozesses | Haben eigenen Adressraum und separate Ressourcen |
| Kommunikation | direkter Zugriff auf gemeinsame Daten<br/>erfordert synchronisierte Mechanismen | erfordert aufwändige Mechanismen wie [IPC](09_Interprozesskommunikation.md) |
| [Synchronisation](07_Prozesssynchronisation.md) | benötigt Synchronisationsmechanismen um Rennbedingungen zu vermeiden | Isoliert voneinander, weniger Rennbedingungen,<br/>aber schwerere Synchronisation zwischen Prozessen |
| Overhead | **geringerer Overhead** | höherer Overhead, da separate Adressräume und Ressourcen |
| Ressourcennutzung | **effiziente Nutzung innerhalb desselben Prozesses** | höherer Ressourcenverbrauch aufgrund separater Adressräume |
| Erstellung und Terminierung | **schnellere Erstellung und Terminierung**<br/>Terminierung beeinflusst nur den spezifischen Thread | Langsamere Erstellung und Terminierung<br/>Beenden eines Prozesses beendet alle seine Threads |
| Fehlerisolierung | Scheitern eines Threads kann gesamten Prozess beeinträchtigen | **Isoliert**, Scheitern beeinflusst keine anderen Prozesse |
- Thread wird auch als _Aktivitätsträger_ oder _leichtgewichtiger Prozess_ benannt
- ist immer Teil eines Prozesses
- Prozess kan viele Threads gleichzeitig enthalten
- werden unabhängig voneinander (_ähnlich Prozesse_) abgearbeitet
- Prozess besteht bei Erzeugung aus einem Thread
- wird impliziert mit dem Prozess erzeugt
| **Thread** | **Prozess** |
|-----------------------------------------|-------------------------------------|
| Leichter Prozess | Programm in Ausführung |
| Gehört zu Prozess | Vollständig isoliert |
| gemeinsamer Speicher | eigener Speicher |
| geringer Ressourcenverbrauch | hoher Ressourcenverbrauch |
| niedriger Zeitbedarf bei Kontextwechsel | hoher Zeitbedarf bei Kontextwechsel |
> Abarbeitung von Threads ist ca. 10-100 mal schneller im Vergleich zur Verarbeitung
> von Prozessen.
>
> Threads nutzen den gleichen Adressraum, was die Kommunikation erleichtert
## Erzeugung von neuen Threads
- Sehr einfach
- Code eines Threads ist eine **normal definierte Funktion**, die wieder andere Funktionen aufrufen kann
- werden von Systemaufrufen gestartet
- Systemaufruf bekommt die Threadfunktion als Parameter übergeben
## Threads implementieren
- Threads sind i.d.R. im Kern implementiert, ähnlich wie Prozesse
- Threads haben dieselben Zustände wie Prozesse, Bedeutung der Zustände ist identisch
- Kann in vielen Programmiersprachen und Systemen realisiert werden
- bspw. _C, C++, C#, Java, Python, Swift, ..._
### Befehle mit [POSIX API](06_prozessstruktur.md#posix-api)
- **pthread_create** - Erzeugen eines Threads
- **pthread_exit** - Beenden eines Threads
- **pthread_join** - Warten auf Ende eines Threads
- **pthread_yield** - Aufgaben der CPU
## Fork-Join-Modell
- Paradigma für die parallele Programmierung
- Erstellen von Threads (**fork**) und Zusammenführen von Threads (**join**)
- wird gerne in rekursiven Algorithmen verwendet
- große Aufgabe kann in kleinere Teilaufgaben zerlegt werden
- Jeder Thread kann sich auf eine Teilaufgabe konzentrieren
- Ergebnisse werden die Ergebnisse kombiniert
![image_157.png](image_157.png)
## FORK
> Durch den Aufruf der Funktion **fork()** in einem Programm werden Threads ebenso wie der
> gesamte Adressraum des Prozesses kopiert
>
> Es entsteht eine exakte Kopie des aufrufenden Prozesses, einschließlich aller Threads und deren Zustände

View File

@ -0,0 +1,151 @@
# Interprozesskommunikation (IPC)
- Mechanismen und Techniken, die es Prozessen ermöglichen miteinander zu kommunizieren
- auf demselben Computer / über ein Netzwerk hinweg
- Ist grundsätzlich wichtig, wenn Prozesse
- zusammenarbeiten
- Daten austauschen
- miteinander interagieren
- Wahl der Methodik hängt von Anforderung der Anwendung ab
- Effizienz
- Datenvolumen
- Sicherheit
- Komplexität
## Synchrone IPC
- Prozess, bei dem der Absender eines [Signals](07_Prozesssynchronisation.md#signale)/Nachricht auf eine Bestätigung oder eine Antwort vom Empfänger wartet
- stellt sicher, dass
- Absender und Empfänger synchronisiert sind
- Ereignisse/Aufgaben sind abgeschlossen bevor andere anfangen
- ![image_158.png](image_158.png)
## Asynchrone IPC
- Prozesse, bei dem der Absender nicht auf sofortige Antwort wartet
- Absender setzt Ausführung fort, während Empfänger verarbeitet und ggf. später antwortet
- ![image_159.png](image_159.png)
## Mechanismen
- [Shared Memory](#shared-memory)
- [Dateien](#dateien)
- [Message Queues](#message-queues)
- [Pipes](#pipes)
- [Promises (Futures)](#promises-futures)
- [Sockets](#sockets)
- [Semaphoren](07_Prozesssynchronisation.md#semaphores)
- [Mutexe](07_Prozesssynchronisation.md#mutex-mutual-exclusion)
- [Condition Variables](#condition-variables)
- [Remote Procedure Call (RPC)](#remote-procedure-call-rpc)
### Shared Memory
- ermöglicht mehreren Prozessen auf denselben _physischen Speicherbereich_ zuzugreifen
- Austausch von Daten effizient ohne explizite Kommunikation
- Speicherbereich wird im RAM erstellt
- Kann von beteiligten Systemen gelesen und beschrieben werden
- müssen sich selbst koordinieren
#### Linux-Systemaufrufe Shared Memory
- **shmget** - Segment erzeugen oder auf bestehendes Zugreifen
- **shmat** - Segment an anderen Prozess anhängen
- **shmdt** - Segment von Prozess lösen/freigeben
- **shmctl** - Status eines Segments abfragen/ändern/löschen
### Dateien
- Prozesse können auf gemeinsame Dateien zugreifen
- Zugriff kann langsamer als andere [IPC-Mechanismen](#mechanismen) sein
- Darauf muss man achten:
- Zugriffsrechte korrekt setzen um Sicherheit zu gewährleisten
- geeignete [Synchronisationsmechanismen](07_Prozesssynchronisation.md#mutex-vs-semaphore) nutzen
### Message Queues
- besonders nützlich, wenn strukturierte Daten zwischen Prozessen ausgetauscht werden
- Struktur muss zwischen Prozessen vereinbart werden
- Verwendung von [Semaphoren](07_Prozesssynchronisation.md#semaphores) kann erforderlich sein, damit Zugriff auf Queue ordnungsgemäß funktioniert
#### Linux-Systemaufrufe Message Queues
- **msgget** - MQ erzeugen / auf bestehende zugreifen
- **msgsnd** - Nachricht in MQ schicken
- **msgrcv** - Nachricht aus MQ empfangen
- **msgctl** - Status einer MQ abfragen/ändern/löschen
### Pipes
- ermöglichen, dass Output eines Prozesses direkt als Input eines anderen Prozesses dient
- sind unidirektional
- gibt Möglichkeiten 2 Pipes zu erstellen → bidirektionale Kommunikation
- haben begrenzte Puffergröße
- zu viele Daten in der Pipe
- blockieren des Schreibprozesses
- arbeiten nach FIFO Prinzip (_First In First Out_)
#### Erstellung von Pipes mit [POSIX API](06_prozessstruktur.md#posix-api)
- **pipe** - Pipe mit zwei Endpunkten erzeugen
- **popen** - Prozess starten (benutzt [fork](08_Threads.md#fork)) und Pipe zum Prozess öffnen
- **pclose** - Mit popen geöffnete Pipe schließen
- **mkfifo** - Named Pipe erzeugen
- **open** - Named Pipe öffnen
- **close** - (Named) Pipe schließen
- **read** - aus (Named) Pipe lesen
- **write** - in (Named) Pipe schreiben
#### Pipes in der Shell
- werden verwendet um 2 oder mehr Befehle zu kombinieren
- Ausgabe eines Befehls fungiert als Eingabe für anderen Befehl
- Ausgabe dessen = Eingabe für den nächsten ...
- Kann temporäre Verbindung zwischen 2 oder mehr Befehlen/Programmen/Prozessen sein
- _Filter_
- Kommandozeilenprogramme, die weitere Verarbeitung übernehmen
- "I" - anonyme Pipe
- bspw. _ps ax | less_
- ">" - benannte Pipe
- bspw. _mkfifo myPipe ls > myPipe_
### Promises (Futures)
- Konzept für _asynchrone Programmierung_
- Programm wartet auf Ergebnis/Rückmeldung einer asynchronen Operation
- blockiert dabei NICHT Haupt-Thread
- Wird oft verwendet in
- _JavaScript, Python, Frameworks wie Javas CompletableFuture_
- ![image_160.png](image_160.png)
### Sockets
- Verwendung geeignet, wenn
- Kommunikation zwischen verschiedenen Rechnern erforderlich ist
- verbindungsorientierte Kommunikation (_bspw. TCP_) erwünscht ist
- Falls über Internet
- Sicherheitsaspekte müssen berücksichtigt werden
- bspw. Verschlüsselung
#### Erstellung von Sockets mit [POSIX API](06_prozessstruktur.md#posix-api)
- **socket** - Socket erzeugen
- **socketpair** - Zwei Sockets erzeugen, ähnlich [pipe](#pipes)
- **read, recv** - Aus Socket lesen
- **write, send** - In Socket schreiben
- **close** - Socket schließen
- **select** - warten auf Socketaktivität
- **poll** - warten auf Socketaktivität
- _send_ und _recv_ können beliebig lange dauern
- können Prozesse/Threads blockieren
→ Einsetzen von _select_
- Dient als [Multiplexer](MU0Rechner.md#multiplexer) für mehrere Sockets (_File-Descriptors: fdts_)
[![How one thread listens to many sockets with select in C](http://i3.ytimg.com/vi/Y6pFtgRdUts/hqdefault.jpg)](https://www.youtube.com/watch?v=Y6pFtgRdUts)
### Condition Variables
- Dienen Synchronisation von Threads in einem Multithreading-Kontext
- Threads werden informiert, dass Bedingung erfüllt / Ressource verfügbar ist
- Normalerweise auf Threads innerhalb desselben Prozesses beschränkt
- nicht direkt für IPC zwischen verschiedenen Prozessen nutzbar
### Remote Procedure Call (RPC)
- Programm kann Funktion/Prozedur auf einem entfernten Rechner/Adressraum ausführen, als wäre sie lokal vorhanden
- abstrahiert Netzwerkkommunikation
- ermöglicht Entwicklern sich auf Logik ihrer eigenen Anwendungen zu konzentrieren
- Verschiedene Implementierungen von TPC existieren für verschiedene Plattformen / Programmiersprachen

View File

@ -0,0 +1,145 @@
# Scheduling
Prozess, wie das Betriebssystem die Ausführung von Aufgaben (Prozessen, Threads, ...) plant und verwaltet
- Hauptziel: Effiziente Nutzung der Systems
- Erfüllung der Anforderungen des Systems und des Benutzers
- Kritisches Element im BS-Design
- direkter Einfluss auf Leistung, Benutzererfahrung
## Aufgaben eines Schedulers
- **Prozessorzuweisung**
- welcher Prozess als nächstes?
- **Prozessorwechsel**
- Wechsel von einem laufenden Prozess zu einem anderen
- **Prioritätszuweisung**
- Bestimmt Priorität von Prozessen → wichtige Aufgaben werden bevorzugt behandelt
- **Warteschlangenmanagement**
- Verwaltung der Warteschlangen mit Prozessen
## Entscheidungsverfahren
- **CPU-Auslastung**
- Maximierung der CPU-Auslastung
- **Durchsatz**
- Anzahl abgeschlossene Aufgaben pro Zeit
- **Wartezeit**
- Minimierung der Wartezeit der Prozesse in der Warteschlange
- **Umlaufzeit**
- Gesamtzeit die ein Prozess benötigt um abgeschlossen zu werden
- **Antwortzeit**
- Zeit zwischen der Anforderung eines Benutzers und der ersten Reaktion des Systems
## Nicht präemptives Scheduling
- Art von Prozessorscheduling beo dem der laufende Prozess nicht unterbrochen werden kann
- bis CPU-Zeitscheibe vollständig oder andere Blockierungsbedingung
- Eingesetz in
- einfache Systeme, Batch-Verarbeitung-Umgebungen
- Vorhersagbarkeit, einfache Implementierung wichtiger als schnelle Reaktion auf Benutzerinteraktion
## Präemptives Scheduling
- Betriebssystemkern kann Kontrolle über CPU von einem laufenden Prozess übernehmen
- kann anderem Prozess CPU-Zeit zuweisen, _falls best. Bedingungen erfüllt_
## Prioritätengesteuertes Scheduling
- Ausführungsreihenfolge der Prozesse hängt von deren Priorität ab
- Jeder Prozess kriegt bestimmte Prio
- Scheduler nimmt Prozess mit höchster Prio
- es gibt präemptive und nicht präemptive Ansätze
- Wird in Echtzeitsystemen und vielen anderen verwendet
- wichtige oder zeitkritische Aufgaben werden bevorzugt behandelt
## Zeitscheiben-Scheduling
- spezielle Form des [präemptiven Schedulings](#pr-emptives-scheduling)
- Jeder Prozess wird für eine festgelegte Zeitscheibe auf dem Prozessor ausgeführt
- sobald abgelaufen → nächster Prozess
- wiederholt sich zyklisch
- Wird verwendet in
- _Mehrbenutzersystemen_
## Weitere Scheduling-Strategien
- First Come First Served
- Shortest / Longest Process next
- Shortest / Longest Remaining Time next
- Highest Response Ratio next
- Earliest Deadline next
- [Fair-Share-Scheduling](#scheduling-unter-linux)
- Multilevel-Scheduling
- ...
## Scheduling unter Linux
![image_161.png](image_161.png)
[![Youtube: Linux Completely Fair Scheduler](http://i3.ytimg.com/vi/2UYuWWX3SMc/hqdefault.jpg)](https://www.youtube.com/watch?v=2UYuWWX3SMc)
### Completely Fair Scheduler (CFS)
- faire Verteilung der CPU-Ressourcen zwischen verschiedenen Prozessen oder Threads
- erstmals in Linux im Kernel 2.6.23
- Bemühung **bessere Leistung** und **Gerechtigkeit** bei Verteilung von Ressourcen in Mehrbenutzersystemen
- Implementierungen und genutzte Algorithmen können variieren
### Grundprinzipien des CFS
- **Fairness**
- jeder ausführbare Prozess sollte proportional zur Anzahl der CPU-Ressourcen, die er benötigt, bedient werden
- **Keine festen Zeitscheiben**
- Ausführungszeit wird dynamisch an Prozesse angepasst
- **Gewichtungen**
- Prozesse mit höherem "Gewicht" erhalten größere Zeiteinteilung an CPU
- **Virtual Runtime**
- Gewicht und Ausführungszeit → vRuntime
- Prozesse mit kürzerer vRuntime priorisiert
- Entscheidungsstruktur: [Rot-Schwarz-Baum](https://de.wikipedia.org/wiki/Rot-Schwarz-Baum)
- ![image_162.png](image_162.png)
### Beispiel Funktionsweise des CFS
![image_163.png](image_163.png)
- Neue Prozesse können während Latenz des Schedulers eingefügt werden
- **vruntime** wird initialisiert mit minimaler Laufzeit (**min_vruntime**)der bereits vorhanden Tasks
- weil jetzt ein zusätzlicher Task da ist, wird allen vorhandenen Tasks automatisch anteilig weniger Laufzeit zugeteilt
- ![image_164.png](image_164.png)
> Manchmal möchte man die Priorität eines Prozesses verändern. Sie kann mit **nice** gesetzt werden
> und mit **renice** angepasst werden
>
> Jeder Prozess kann einen [nice-Wert](#nicewert) von -20 bis 19(20) haben. Standard ist 0
### Berechnung der Gewichtung (CFS)
- **1024/1,25<sup>[niceWert](#nicewert)</sup>**
- Falls [niceWert](#nicewert) abnimmt, steigt Gewicht an
- Zeitscheibe ist proportional zur Gewichtung dividiert durch Gesamtgewichtung aller Prozesse
- ![image_165.png](image_165.png)
#### Beispiel
- 131 Tasks (nice = 0) → Gewicht w = 1024
- 20 Tasks (nice = -20) → Gewicht w = 88817,84
- Alle Tasks mit nice=0 belegen ca. 7% der CPU
- $131*1024 / (131*1024 + 20*88817,84) → ca. 7%$
- tun i.d.R nichts → genug runtime
- Alle Tasks mit $nice = -20$ belegen ca. 93% der CPU
### niceWert
Befehle mit [POSIX-API](06_prozessstruktur.md#posix-api)
- **setpriority** - niceLevel eines Prozesses setzen
- **getpriority** - niceLevel eines Prozesses lesen
## Real-Time Scheduling
- zielt darauf ab, dass Prozesse oder Aufgaben spezifische zeitliche Anforderungen erfüllen
- Bsp.:
- Dekodierung von Bildern eines Videostreams
- 30 Bilder / Sekunde
- Jedes Bild muss in 1/30s dekodiert und angezeigt werden
- in **harten Echtzeitsystemen** müssen Aufgaben ihre zeitlichen Anforderungen strikt und zuverlässig erfüllen
- bspw. Flugzeug, medizinische Geräte, ...
- _Scheduling-Algorithmen_
- Rate Monotonic Scheduling (RMS)
- Earliest Deadline First (EDF)
- in **weichen Echtzeitsystemen** sind zeitliche Anforderung auch wichtig, aber Versäumnis ist nicht katastrophal
- bspw. Multimediale Anwendungen, Spiele
- _Scheduling-Algorithmen_
- Weighted Fair Queuing (WFQ)
- Proportional Share Scheduling

View File

@ -0,0 +1,62 @@
# Energieeffizienz
## Energieverwaltung
- Frequenzskalierung der CPU
- Spannungs- und Frequenzanpassung
- [Stromsparmodi](#stromsparmodi-und-profile)
- Bildschirmhelligkeit und -abschaltung
- [Energieeffizientes Scheduling](#energieeffizientes-scheduling)
- [I/O Effizienz](#i-o-effizienz)
- Wärme- und Lüftermanagement
- [Netzwerkmanagement](#netzwerkmanagement)
- Energieprofile und -richtlinien
- Advanced Configuration and Power Interface (ACPI)
## Prozessor- und Gerätesteuerung
- Strategien und Mechanismen, um _Leistung und Energieeffizienz_
- von CPUs und anderen Hardwarekomponenten zu optimieren
- Moderne Betriebssysteme
- integrierte Mechanismen zur Steuerung von Hardwarekomponenten
## Energieeffizientes Scheduling
- CPU-Energieeffizienz maximieren durch Verteilung von Prozessen auf CPU-Kernen
- Kernzusammenlegung
- Dynamisches Kernabschalten
- Aufgabenplanung basierend auf Prozessoreigenschaften
- Scheduling basierend auf Workload Charakteristiken
- Adaptive Scheduling-Richtlinien
- Anpassung an Hardware-Topologie
## I/O-Effizienz
- Optimierung von Ein- und Ausgabeoperationen
- Effiziente Nutzung von Ressourcen und Reduzierung des Energieverbrauchs
- Batching von I/O-Operationen
- Asynchrone I/O
- Pufferung von Daten
- Intelligente Catching-Strategien
- Effizientes Dateisystem-Layout
- Adaptive Datenkompression
## Leistungsüberwachung und -profiling
- Bewertung und Analyse der Leistung eines Computers
- Engpässe identifizieren
- Ressourcennutzung optimieren
- Effizienz steigern
- Im Wesentlichen Werkzeuge für SysAdmins, Entwickler, Ingenieure
- Leistung von Computern und Anwendungen verstehen
- Bottlenecks beheben
## Netzwerkmanagement
- Planung, Implementierung, Überwachung, Optimierung von Netzwerkinfrastrukturen
- zusätzlich: Lastenausgleich, Netzwerkprotokolle & -standards
## Optimierung von Hintergrundprozessen
- Gewährleistung von Gesamtleistung, Stabilität, Effizienz
- Priorisierung
- Ressourcenzuweisung
- Zeitgesteuerte Ausführung
- Intelligente Aktivierung
- Parallelisierung
- Caching
## Stromsparmodi und -profile
- Funktionen müssen entsprechend der Anforderungen und Nutzungsmuster angepasst werden.

View File

@ -0,0 +1,90 @@
# Virtualisierung
> Technologie, die es ermöglicht mehrere virtuelle Instanzen auf einem einzigen
> physischen System auszuführen
>
> Spielt eine entscheidende Rolle bei der effizienten Nutzung von Ressourcen, der Erhöhung von
> Flexibilität und Skalierbarkeit sowie der Verbesserung der Verfügbarkeit von Anwendungen und Daten
## Vorteile der Virtualisierung
- **Ressourceneffizienz**
- mehrere VMs können auf einem physischen Server laufen
- **Isolation**
- VMs sind voneinander isoliert
- verbessert Stabilität und Sicherheit
- **Snapshot- und Wiederherstellungsfunktion**
- **Portabilität**
- VMs können auf verschiedenen physischen Servern verschoben und ausgeführt werden
## Virtualisierungstypen
### Hypervisor-basierte Virtualisierung
- [Hypervisor](https://www.youtube.com/watch?v=LMAEbB2a50M) (~Virtual Machine Monitor)
- wird direkt auf Hardware ausgeführt
- ermöglicht Ausführung mehrerer Betriebssysteme als VMs
#### Typ 1 (Bare-Metal-Hypervisor)
- direkte auf Hardware installiert
- benötigt kein Host-Betriebssystem
- _bspw.: VMware ESXi, Microsoft Hyper-V_
#### Typ 2 (Hosted-Hypervisor)
- Läuft auf Host-Betriebssystem
- _bspw: VMware Workstation, Oracle VirtualBox_
### Container-Virtualisierung
- Container teilen sich Kernel des Host-Betriebssystems
- bieten leichtgewichtige Möglichkeit Anwendungen zu isolieren und auszuführen
## Partitionierung von VMs
- Aufteilung einer _physischen oder virtuellen Ressource_ in mehrere logische Einheiten (Partitionen)
- ![image_248.png](image_248.png)
- können unterschiedliche Betriebssysteminstanzen/Anwendungen beherbergen
- Vorteile u.a. Ressourcenisolierung, verbesserte Sicherheit, bessere Verwaltbarkeit
## Hardware-Emulation
- Nachbildung oder Simulation von Hardware auf einer anderen Hardware- oder Softwareplattform
- Replikation von Hardware-Komponenten, Geräten oder ganzen Systemen auf einer virtuellen Ebene
- ![image_249.png](image_249.png)
- **Entwicklung neuer Hardware**
- Simulation von Hardware-Designs bevor tatsächliche Hardware erstellt wird
- **Fehlerbehebung und Debugging**
- Identifizierung von Fehlern in Hardware-Komponenten oder -Systemen
- **Testen von Software**
### Hardware-Emulator vs. Simulator
| **Emulator** | **Simulator** |
|-----------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
| Reproduziert Verhalten der tatsächlichen Hardware genau | Ahmt Verhalten von Hardware nach |
| arbeitet auf niedriger Ebene, indem er Hardwarekomponenten genau nachbildet | Arbeitet auf höherer Ebene, Konzentration auf Funktionalität statt exakter Nachbildung |
## Anwendungsvirtualisierung
- Einzelne anwendung in virtueller Umgebung ausführen, die alle benötigten Komponenten bereitstellt
- ![image_250.png](image_250.png)
- virtuelle Maschine befindet sich zwischen Anwendung und Betriebssystem
- _bspw.: Java Virtual Machine (JVM)_
## Betriebssystem-Virtualisierung
- [Container](https://www.youtube.com/watch?v=TvnZTi_gaNc) laufen unter ein und demselben BS-Kern
- mehrere abgeschottete, identische Systemumgebungen
- ![image_251.png](image_251.png)
- bei Start einer VM wird im Gegensatz kein zusätzliches BS gestartet
- Erzeugung isolierte Laufzeitumgebung
## Vollständige Virtualisierung
- Hypervisor bietet einer VM eine komplette virtuelle PC-Umgebung inkl. eigenem BIOS
- ![image_252.png](image_252.png)
- Gast-BS erhält eigene VM mit virtuellen Ressourcen
- Prozessor(en)
- Hauptspeicher
- Laufwerke
- Netzwerkkarten
- etc.
- Kern der Lösung ist Virtueller Maschinen-Monitor (VMM)
- Aufgabe ist Zuweisung der Hardwareressourcen an VMs
## Virtualisierungslösungen
- [docker](https://www.docker.com)
- [vmware](https://www.vmware.com)
- [virtualbox](https://www.virtualbox.org)
- [getutm (mac)](https://mac.getutm.app)

View File

@ -0,0 +1,96 @@
# Speicherverwaltung
## Speicherhierarchie
### Registers
- schnellste und kleinste Form des Speichers
- direkt in Prozessor
- Speicherung temporärer Daten und Zwischenergebnisse
### Cache
- kleinerer, schnellerer Speicher
- zwischen Register und RAM
### Hauptspeicher (RAM)
- physischer Speicher
- Prozessor kann direkt zugreifen
### Virtueller Speicher
- langsamerer Speicher
- Erweiterung des RAMs
## Speicheradressierung
- Prozess, durch den ein Computer auf den physischen/virtuellen Speicher zugreift
| **Physische Adressierung** | **Logische Adressierung** |
|---------------------------------------------------------------|----------------------------------------------|
| direkter Zugriff auf bestimmten Speicherort im physischen RAM | Adresse von Prozess generiert |
| physische Adresse = tatsächliche Adresse des Speicherorts | wird später in physische Adresse umgewandelt |
| | **Virtuelle Adressierung** |
## Speicherpartitionierung
- Aufteilung des physischen Speichers in logische Abschnitte
- können von verschiedenen Teilen des Systems genutzt werden
- Mögliche Zwecke:
- Betriebssystemcode
- Anwendungsdaten
- Temporäre Variablen
- ...
### Statische Partitionierung
![image_281.png](image_281.png)
- Aufteilung in Partitionen gleicher / unterschiedlicher Größe
- im Idealfall möglichst passgenau
- möglichst wenig interne Fragmentierung
- Falls unterschiedliche Größe
- BS verwaltet Warteschlange
- | eigene für jede Partition | eine für alle |
|--------------------------------------------------------|---------------|
| :( bestimmte Partitionen werden seltener/nie verwendet | |
- Nachteil:
- zwangsläufig interne Fragmentierung
- sehr ineffizient
![image_282.png](image_282.png)
## Dynamische Partitionierung
- BS weist jedem Prozess eine zusammenhängende Partition zu
- mit exakt benötigter Größe
- dabei auch Fragmentierung
- Darstellung des Speichers durch BS als verkettete Liste
- Kennzeichnung, ob frei/belegt
- Startadresse
- Länge
- Zeiger auf nächsten Eintrag
- Unterschiedliche Zuteilungskonzepte
- wie sucht/findet das BS einen freien Speicherbereich
- **First Fit**
- sucht bei jeder Anforderung ab Anfang des Adressraums
- **Next Fit**
- sucht ab letzter Zuweisung
- **Best Fit**
- Sucht immer den freien Bereich, der am besten zur Anforderung passt
- am wenigsten Fragmentierung
- ![image_450.png](image_450.png)
## Buddy-Speicherverwaltung
- Ziel: Fragmentierung von Speicherblöcken minimieren
- wird oft in BS und in der Verwaltung von Speicher-Pools verwendet
- basiert auf
- Blöcke gleicher Größe als Buddies zusammenfassen
- effizienter Speicherzugriff/-freigabe ermöglichen
### Erstellung
- Am Anfang ein Bereich, der gesamten Speicher abdeckt
- Sobald ein Prozess Speicherplatz anfordert
- Speicherkapazität zur nächsthöheren Zweierpotenz aufrunden
- entsprechenden, freien Bereich suchen
- Falls nicht existent
- Nach Bereich doppelter Größe suchen
- in zwei Teile teilen (Buddies)
- eine Hälfte wird anfordernden Prozess zugewiesen
- ![image_283.png](image_283.png)
- Linux verwendet für Zuweisung von Speicherseiten zu Prozessen
- Informationen in _/proc/buddyinfo_
- ![image_284.png](image_284.png)

View File

@ -0,0 +1,109 @@
# Speicherabstraktion
> Idee, dass Anwendungen und Benutzer nicht direkt mit physischem Speicher interagieren müssen.
> Sie können stattdessen auf einer höheren, abstrakten Ebene arbeiten
>
> Ermöglicht einfachere, flexiblere Verwendung des Speichers, da Details der physischen Speicherhardware
> vor Benutzer und Anwendung verborgen werden.
## Adressräume
- Gesamter Bereich von Speicheradressen, welcher durch System/Prozess verwendet werden kann
- ermöglicht Beschränkung des Zugriffs auf bestimmte Speicherbereiche
- Sicherheit & Integrität gewährleisten
- unautorisierten Speicherzugriff verhindern
## Relokation
- Jede Anwendung bekommt eigenen Adressraum des physischen Speichers
- Dafür Spezialregister in der CPU
- ermöglichen laden von Programmen in den Speicher ohne Relokation
- **Basisregister**
- Startadresse des Programms
- **Limitregister**
- Länge des Programms
- **Nachteil:**
- Bei jedem Speicherzugriff Addition und Vergleich ausführen
- Addition benötigt wegen Carry-Bit lange
- _Vergleich ist fine_
> In der Praxis ist die benötigte RAM-Menge oft größer als der physische Speicher
## Swapping
- Prozesse zwischen primären Speicher(RAM) und sekundären Speicher (Festplatte) austauschen
- Entlastung des RAM durch Auslagerung nicht benötigter Prozesse
- Kann Leistung beeinträchtigen
- Zugriff auf sekundären Speicher dauert länger
- ![image_285.png](image_285.png)
> Sehr erfolgversprechend, da normale SATA nur Max-Übertragungsgeschwindigkeit von einigen 100MB/s hat
>
> → es dauert Sekunden, um ein 1GB-Programm aus-/einzulagern
## Virtual Memory
- Virtueller Speicher ermöglicht mehr Speicher zu verwenden als vorhanden ist
- Physischer Speicher und ein Teil der Festplatte werden als virtueller Speicher behandelt
- BS kann effizienten Gebrauch von begrenzten RAM machen
- Prozesse und Daten dynamisch zwischen physischem Speicher und sekundärem Speicher verschieben
- Gesamtleistung optimieren :)
-
## Dynamischer Speicher
- Speicherplatz, der zur Laufzeit eines Programms dynamisch angefordert, freigegeben wird
- Speicherplatz während Laufzeit variieren
- bietet Flexibilität
- Programme können während Ausführung an sich ändernde Anforderungen reagieren
- müssen nicht im Voraus Speicherplatz reservieren
- Wird oft im Heap reserviert
- Heap wird meist für lokale Variablen, Funktionsaufrufe verwendet
- ermöglicht Heap dynamische Zuweisung von Speicherplatz
- Programmierer ist für Freigabe von Speicherplatz verantwortlich
- vernachlässigte Freigabe kann zu Speicherlecks führen
- einige Programmiersprachen haben eine automatische Speicherverwaltung (_Garbage Collection_)
- ![image_286.png](image_286.png)
## Paging
- Speicherverwaltungstechnik
- Virtueller Speicher wird in kleine, gleichgroße Blöcke (_Seiten_) unterteilt
- Können dann in physischem Speicher / Festplatte ausgelagert werden ([Swapping](#swapping))
- Adressen werden mithilfe von Indizierung, Basisregistern und Segmentregistern generiert
- = virtuelle Adresse, bildet virtuellen [Adressraum](#adressr-ume)
- virtueller Adressraum besteht aus Einheiten fester Größe
- werden _Seitenrahmen (page frame)_ genannt
- Beispiel:
- ![image_287.png](image_287.png)
- Seiten und Seitenrahmen sind hier 4KB
- normalerweise von 512 Byte - 1GB
- Present-/Absent-Bit zeigt an, ob Seiten physisch im Speicher vorhanden sind
- Greift Programm auf einen Speicherbereich zu, der noch nicht in den Speicher geladen wurde
- Seitenfehler (_page fault_) wird ausgelöst
- BS gibt einen Seitenrahmen im Speicher frei
- BS lädt entsprechende Seite in jetzt freien Seitenrahmen
- Befehl wird nochmal ausgeführt
- ![image_288.png](image_288.png)
- Muss schnell gehen, da es sonst zu Engpass wird
- Meist < 0,2 ns
- Jeder Prozess hat eigenen Adressraum
- benötigt eigene Seitentabelle
## Memory Management Unit (MMU)
- virtuelle Adresse, die von Prozessen/Programmen verwendet werden in physische Adressen umwandeln
- mithilfe von Seitentabellen oder anderen Mechanismen
- Schlüsselelement des Speichermanagements
- zentrale Rolle bei Implementierung von Funktionen
- wie virtuellem Speicher und Paging
- ![image_289.png](image_289.png)
- 16Bit Adresse wird in 4-Bit-Seitennummer und 12Bit Offset zerlegt
- 4 Bit 16 Seiten
- 12 Bit 4096 Byte adressierbar
- ![image_290.png](image_290.png)
- [YouTube: _Virtuelle Speicherverwaltung mit MMU_](https://www.youtube.com/watch?v=QPL-xJ6ePqQ)
## Translation Lookaside Buffer
- Assoziativer Speicher (TLB) für schnellere Adressumwandlung der MMU
- Puffert Seitenzugriffe
- ermöglicht direkteren Zugriff auf wichtige Informationen der Speichertabelle
- ohne Zugriff auf Seitentabelle
- enthält nur wenige Einträge
- Schnelle Suche
- Arbeitet als Cache für MMU

View File

@ -0,0 +1,29 @@
# Bibliotheken
## Gemeinsame Bibliotheken
- In jedem modernen System vorhanden
- bspw. I/O-, Grafikbibliotheken
- Statt an jedes Programm statisch binden
- _shared libraries_
- Bsp.:
- normales Programm benutzt 20-50MB an Grafik- und Benutzungsschnittstellenfunktionen
- hunderte solcher Programme
- viel Speicher, RAM verschwendet
- BS hat keine Möglichkeit um zu schauen, ob eine gemeinsame Nutzung infrage käme
- Falls Programm mit gemeinsamen Bibliotheken verbunden
- **Binder (_Linker_)** schließt _Stub-Routine_ ein
- statt aktueller Funktionsaufrufe
- Gemeinsame Bibliotheken gleichzeitig wie Programm / beim ersten Aufruf ihrer Funktion laden
- abhängig vom System
- Falls durch anderes Programm bereits geladen
- Muss nicht nochmal! :)
- Wird nicht auf einmal in den Speicher eingelesen
- Bei Bedarf Seite für Seite
- Keine Funktionen im RAM, die nicht gebraucht werden
- Ausführbare Dateien bleiben klein
- Falls Fehler in Bibliothek
- Beheben
- Nicht alle Programme neu übersetzen

View File

@ -0,0 +1,310 @@
# Dateisysteme
## Warum Dateisysteme
- Neben Verwaltung des Hauptspeichers und Cache
- Verwaltung des Massenspeichers (bspw. SSD, Festplatte)
- Organisation der Ablage von Dateien
- Dateisysteme verwalten die Namen und Attribute (Metadaten) der Dateien
- Bilden einen Namensraum
- Hierarchie von Verzeichnissen und Dateien
## Dateien
- Datei dient der Abstraktion
- Bietet Möglichkeit Informationen auf einer Platte zu speichern/lesen
- Nutzer müssen Details der Speicherung verborgen bleiben
- _Wo_ und _Wie_
- Wichtigstes Merkmal ist Art und Weise wie verwaltete Objekte benannt werden
- Wenn Prozess Datei erzeugt, vergibt er ihr einen Namen
- Bei einigen Systemen (bspw UNIX)
- Dateiendungen lediglich Konventionen, die vom Betriebssystem nicht erzwungen
- Datei _file.txt_ kann Textdatei sein, Name dient mehr dazu den User zu erinnern
- Andererseits könnte ein C-Compiler darauf bestehen, dass Eingabedateien Endung ".c" haben
- Für BS ist das egal
- Dateien können in verschiedenster Art und Weise strukturiert sein
- **Bytefolge**
- **Datensätze**
- **Baumstrukturen**
- In den meisten Fällen werden Dateien als Bytefolgen angesehen
- Maximum an Flexibilität
- Interpretation der Inhalte erfolgt auf Anwendungsebene
## Sequenzieller Dateizugriff
- Prozess kann alle Bytes oder Datensätze einer Datei nacheinander lesen
- Überspringen oder Zugriffe außerhalb der Reihenfolge nicht möglich
- Sequenzielle Dateien konnten zurückgespult werden
- können so oft wie nötig gelesen werden
## Wahlfreier Dateizugriff
- Mit Einführung der Platte als Speichermedium
- Möglichkeit die Bytes oder Datensätze in beliebiger Reihenfolge auslesen
- über Schlüssel statt Positionsangabe zugreifen
- Dateien, bei denen das geht = Dateien mit _wahlfreiem Zugriff_ (random access file)
- sind heute Voraussetzung für viele Anwendungen
- bspw. für Datenbanksysteme
## Dateiattribute
- Eigenschaften / Metadaten
- Können von BS / Dateisystem verwaltet werden
- enthalten Größe, Erstellungsdatum, Zugriffsrechte ...
## Dateioperationen
### Create
- Datei wird ohne Datum erzeugt
- Entstehung der Datei ankündigen und eigene Attribute festlegen
### Delete
- Wird eine Datei nicht länger benötigt, muss sie gelöscht werden
### Open
- Bevor eine Datei benutzt werden kann, muss ein Prozess sie öffnen
- Open ermöglicht Laden in Arbeitsspeicher
### Close
- Freigeben des internen Tabellenspeichers
### Read
- Daten werden aus Datei gelesen
- Bytes von der aktuellen Position
- Aufrufer muss angeben wie viele Daten benötigt werden
- Puffer für Daten zur Verfügung stellen
### Write
- Wenn aktuelle Position an Ende der Datei
- Dateigröße erhöht sich
- Befindet sich Position in der Mitte der Datei
- vorhandene Daten werden überschrieben
### Append
- Eingeschränkte Form von [Write](#write)
### Seek
- Bei Dateien mit wahlfreiem Zugriff
- Von wo Daten holen?
- Seek positioniert Dateizeiger an einer bestimmten Stelle in der Datei
- Danach lesen/schreiben an Position
### Rename
- Name der Datei ändern
- nicht zwingend notwendig
- normalerweise in eine neue Datei mit anderem Namen umkopieren
- alte löschen
### Get attributes
### Set attributes
## Verzeichnisse
- Verzeichnissystem mit nur einer Ebene ist angemessen für sehr einfache Anwendungen
- ![image_338.png](image_338.png)
- **absolute Pfadnamen**
- Gesamter Pfad von Wurzel bis Datei
- **relative Pfadnamen**
- In Verbindung mit dem Konzept des Arbeitsverzeichnisses
- ./
- aktuelles Verzeichnis
- ../
- übergeordnetes Verzeichnis
- ![image_339.png](image_339.png)
## Verzeichnisoperationen
### Create (Verzeichnis)
### Delete (Verzeichnis)
- Es kann immer nur ein leeres Verzeichnis gelöscht werden
- (., .. dürfen enthalten sein)
### Opendir
- Um beispielsweise alle Dateien in einem Verzeichnis aufzulisten
### Closedir
### Readdir
- Aufruf gibt nächsten Eintrag eines geöffneten Verzeichnisses zurück
### Rename (Verzeichnis)
### Link
- Durch Technik des Verlinkens können Dateien in mehr als einem Verzeichnis vorkommen
- Spezifiziert eine vorhandene Datei und erzeugt Verbindung von dieser Datei zu dem Namen
### Unlink
- Verzeichniseintrag wird entfernt
- Falls nur in einem Verzeichnis → [löschen](#delete)
## Implementierung
- BIOS liest MBR ein, führt aus
- MBR-Programm
- lokalisiert aktive Partition
- liest ersten Block (Boot-Block)
- führt aus
- lädt BS, das in Partition gespeichert ist
- Dateisystem enthält häufig noch Superblock
- enthält alle _Schlüsselparameter_ des Dateisystems
- **Magische Zahl**
- identifiziert Typ des DS
- **Anzahl der Blöcke**
- **Weitere administrative Schlüsselinformationen**
- wird bei Start in den Speicher geladen
- Danach
- **Freie Blöcke**
- Bitmap oder Liste von Zeigern
- **I-Nodes**
- Feld von Datenstrukturen
- Jede beinhaltet Informationen über je eine Datei
- **Wurzelverzeichnis**
- Spitze des Dateibaums
- ![image_340.png](image_340.png)
## Methoden zur Belegungsverkettung
### Zusammenhängende Belegung
- Einfachstes Belegungsschema
- Speicherung als zusammenhängende Menge von Plattenblöcken
- Jede Datei beginnt mit neuem Block
- ![image_351.png](image_351.png)
- | Vorteile | Nachteile |
|-----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| Einfach zu implementieren<br/>Lokalisierung der Dateiblöcke basiert auf zwei Zahlen | Im Laufe der Zeit wird die Platte fragmentiert |
| hervorragende Leseleistung<br/>Gesamte Datei kann mit einer Operation von der Platte gelesen werden | ![image_352.png](image_352.png) |
- In manchen Situationen praktikabel
- CD-ROM
- alle Dateigrößen sind bekannt, werden sich niemals während Gebrauch ändern
- DVD
- Kann als eine Datei gespeichert werden
- meistens ~4 1GB Dateien
### Verkettete Listen
- Jede Datei ist verkettete Liste von Plattenblöcken
- Erstes Wort = Zeiger auf den nächsten
- Rest = Daten
- ![image_353.png](image_353.png)
- | Vorteile | Nachteile |
|-------------------------------------------------------------------------|--------------------------------------------------------------------|
| Kein verlorener Speicherplatz durch Fragmentierung | sequenzielles Lesen zwar schnell, wahlfreier Zugriff sehr langsam |
| | Für Verzeichniseintrag ist Plattenadresse des ersten Blocks ausreichend | Um Auf Block n zuzugreifen müssen n-1 Blöcke vorher gelesen werden |
### File Allocation Table (FAT)
- Zeiger jedes Plattenblocks in einer Tabelle im Arbeitsspeicher
- | Vorteile | Nachteile |
|------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|
| Gesamter Block steht für Daten zur Verfügung | Gesamte Tabelle muss durchgehend im Speicher sein |
| Obwohl Kette verfolgt werden muss, kann das im RAM ohne Zugriffe auf Platte geschehen | Bei einer !TB Festplatte mit einer Blockgröße von 1KB benötigt die Tabelle 1Mia*3Byte ~ 3GB des RAM |
| Es reicht für Verzeichniseintrag einen einzigen ganzzahligen Wert des Startblocks zu speichern | |
### I-Nodes (Index Node)
- Datenstruktur, die Informationen über eine Datei oder ein Verzeichnis auf einem Dateisystem enthält
- Jede/s Datei/Verzeichnis ist durch einen eindeutigen I-Node identifiziert
- | Vorteile | Nachteile |
|--------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| I-Node muss nur im Speicher sein, solange Datei geöffnet ist | Jeder Node kann nur begrenzte Anzahl von Plattenadressen<br/>Sobald das Limit erreicht ist, müsste man die letzte Adresse als Zeiger auf den nächsten Node nehmen |
| Feld, das die I-Nodes enthält benötigt nur n*k Byte | |
- ![image_354.png](image_354.png)
## Dateinamen
- Keine festgelegte Länge
- variable Dateinamenlängen verwalten?
- ![image_355.png](image_355.png)
- Nachteil:
- Lücke variabler Länge
- entsteht, wenn eine Datei entfernt wird und nächste Lücke nicht genau passt
- Es ist möglich Verzeichniseinträge zu verschieben
- ![image_356.png](image_356.png)
- Für alle Dateinamen nur feste Längen zulassen
- Gemeinsam auf einem Heap am Ende des Verzeichnisses speichern
- Vorteil:
- nach Entfernen einer Datei passt nächste immer rein
- Heap muss mitverwaltet werden :/
- Lineare Suche → sehr langsam
- Verwendung einer Hashtabelle in jedem Verzeichnis
- Vorteil einer viel schnelleren Suche
- Nachteil: komplizierte Verwaltung
- Zwischenspeichern der Resultate vorangegangener Suchen
## Gemeinsam genutzte Dateien
- ![image_357.png](image_357.png)
- Probleme:
- ![image_358.png](image_358.png)
- Enthält Verzeichnis Plattenadressen, dann muss Kopie der Adressen im Verzeichnis B angelegt werden
- Wenn B/C Daten an Datei anhängen
- neue Blöcke werden nur im Verzeichnis, in dem Änderung stattfand, aufgelistet
- Zweck gemeinsamer Verwendung verfehlt
### Symbolische Links
- Enthält Pfadnamen zur gewünschten Datei
- Wenn B Datei liest, sucht BS direkt im angegebenen Pfad
- | Vorteil | Nachteile |
|--------------------------------------------------------|--------------------------------------------------------------------------------------------|
| Dateien auf entfernten, vernetzten Maschinen verlinken | zusätzlicher Aufwand<br/>eigener Plattenblock für Pfad |
| | Datei mit Pfadnamen muss gelesen werden, Pfad analysieren, Komponente bis I-Node verfolgen |
| | Falls in Unterverzeichnissen wird Datei evtl. mehrfach gefunden |
| | Bei Einspielung auf anderen Computer → Link wird zur Kopie der selben Datei |
## Log-basiertes Dateisystem (LFS)
- Schreibzugriffe sind effizienter als Lesezugriffe
- Schreibleistungs- und Fragmentierungsprobleme überwinden
- Schreibvorgänge werden protokolliert
- Mit schnelleren CPUs, größerem RAM wächst Platten-Cache schneller
- Viele Lesezugriffe direkt aus Platten-Cache
- Ohne Festplattenzugriffe
- Meiste Plattenzugriffe = Schreibzugriffe :)
- Probleme
- Schreibzugriffe meist in Stückchen → ineffektiv
- Abhängig von
- Spurwechselzeit ([seek](#seek) time)
- Latenzzeit (latency)
- Kommando-Latenz (controller overhead)
- Inkonsistenzen bei Systemabstürzen
- Lösungsansatz
- Alle noch ausstehenden im Speicher gepufferten Schreibaufträge regelmäßig sammeln
- An Ende des Logs schreiben
- Einzelnes Segment kann in beliebiger Reihenfolge I-Nodes, Verzeichnisblöcke und Datenblöcke enthalten
- Am Anfang Zusammenfassung über Inhalt
- Probleme Lösungsansatz
- Log wird ohne Reorganisation immer größer
- Bereinigungsvorgang wird benötigt
- Über alle Vorgänge Protokoll zu führen erfordert logistischen Aufwand
- LFS sind hochgradig inkompatibel zu bestehenden Dateisystemen
- können Inkonsistenz bei Systemabstürzen nicht abfangen
## Journaling
- mit Grundgedanken von [LFS](#log-basiertes-dateisystem-lfs) Robustheit DS erhöhen
- Log ist Protokoll über geplante Aktionen
- Bei Systemabsturz vor Beendigung einer geplanten Arbeit
- Bei Neustart im Log nachschauen, was gerade vor sich ging
- Vorgang sauber beenden
- Beispiel:
- _NTFS_, _ext3_, _macOS Extended_
- Für zusätzliche Zuverlässigkeit
- Datenbankkonzept der atomaren Transaktion
- Gruppe von Aktionen klammern
- Anfangstransaktion (begin transaction)
- Endtransaktion (end transaction)
- Dateisystem weiß, das es alle eingeklammerten oder keine ausführen muss
- ACID-Eigenschaften
- **Atomarität (Atomicity)**
- Transaktion wird als Ganzes behandelt
- alle oder keine Operationen in Transaktion ausführen
- Wenn eine fehlschlägt Rest rückgängig machen
- **Konsistenz (Consistency)**
- Transaktionen werden von einem in einen andern konsistenten Zustand überführt
- Nach Abschluss einer erfolgreichen Transaktion
- DB in Zusatnd, der Integritätsregeln entspricht
- **Isolation (Isolation)**
- mehrere gleichzeitige Transaktionen unabhängig, gleichzeitig ausführen
- **Dauerhaftigkeit (Durability)**
- einmal abgeschlossene Transaktion dauerhaft in DB gespeichert
- Änderung auch nach Systemabsturz / Neustart erhalten
## Virtuelle Dateisysteme (VFS)
- ![image_359.png](image_359.png)
- Abstraktionsschicht im BS
- dient zur Vereinheitlichung der Dateisysteme und deren Zugriffsmethoden
- Anwendungen können auf Dateien zugreifen
- ohne auf Details der zugrunde liegenden physischen Dateisysteme zu achten
- erleichtert Portabilität, flexiblere Verwaltung der Dateisystemressourcen
- Wenn System hochgefahren
- Wurzeldateisystem beim VFS registrieren
- Liste der Adressen von Funktionen dem VFS zur Verfügung stellen
- Entweder lange Aufruftabelle oder eine Tabelle pro VFS-Objekt
- VFS legt im RAM V-Nodes an
- weitere Dateisysteme jetzt oder während Ausführung

View File

@ -0,0 +1,65 @@
# Plattenspeicherverwaltung
## Mögliche Strategien
**Speicherung von einer Datei mit n Byte**
- n aufeinanderfolgende Byte auf der Platte reservieren
- Problem
- Datei muss möglicherweise auf Platte verschoben werden, wenn sich Größe ändert
- **Datei wird in eine bestimmte Anzahl von (nicht unbedingt) zusammenhängenden Blöcken aufgeteilt**
- Verschiebung relativ schnell
### Wie groß die Blöcke?
- Sektoren, Spuren und Zylinder Kandidaten
- geräteabhängig
- große Blockgröße → Platzverschwendung
- kleine Datei braucht trotzdem viel Platz
- kleine Blockgröße → Zeitverschwendung
- mehr Plattenzugriffe, rotationsbedingte Wartezeiten
- Reduzierung Performanz
### Überblick über Anzahl freier Blöcke?
#### Verkettete Liste von Plattenblöcken
![image_360.png](image_360.png)
#### Bitmap
![image_361.png](image_361.png)
- Was macht man jetzt?
- man benötigt Daten über Verwendung, um besten Algorithmus zu finden
- Falls viele freie Blöcke aufeinanderfolgen
- In der Liste statt Blöcken Folgen von Blöcken
- Jeder Block bekommt 8/16/32 Bit Zähler über nachfolgende freie Blöcke
- leere Platte definiert durch 2 Zahlen
- Adresse erster freier Block
- Anzahl der folgenden freien Blöcke
- Immer ein Block von Zeigern im Speicher
- Beim Löschen einer Datei
- Blöcke werden freigegeben
- ![image_362.png](image_362.png)
- Um Anwender davon abzuhalten, zu viel Speicher in Beschlag zu nehmen
- disk quota
- SysAdmin weist jedem Benutzer einen max. Anteil an Dateien und Blöcken zu
- BS behält Kontrolle
- ![image_363.png](image_363.png)
- Wenn sich Benutzer anmeldet
- Soft-Limit übertreten?
- Warnung
- Sobald Warnung einmal zu oft ignoriert
- Sperre, SysAdmin muss entsperren
## Sicherung von Dateisystemen
- Wiederherstellung meist sehr schwierig, zeitintensiv / unmöglich
- Sicherheitskopie braucht lange, viel Platz
- Alles oder nur einen Teil sichern?
- Nochmal sichern, wenn sich seit letztem Mal nix geändert hat?
- Daten komprimieren?
### Ansätze
#### Physische Sicherung (physical dump)
- Beginnt mit Block 0 der Festplatte
- Alle Blöcke der Reihe nach auf das Medium
- Programm sehr einfach
### Logische Sicherung (logical dump)
- Beginnt mit einem oder mehreren Verzeichnissen
- vorher festgelegt
- sichert rekursiv alle dort vorhandenen Daten
- die sich seit gewissem Bezugsdatum geändert haben

View File

@ -0,0 +1,63 @@
# Klausur
## Themenbereiche
- 4 Stück mit je 20 Punkten
**1. Kernel**
- Was ist ein Kernel
- Was für Varianten
- Warum ist das so
**2. Prozesse**
- Wie funktionieren die
- Wie sind sie aufgebaut
- Wer verwaltet sie
- Wie werden sie verwaltet
**3. Interprozesskommunikation / Scheduling**
- IPC
- Scheduling
- Was ist das
- Was macht das
**4. Speicherverwaltung / Virtualisierung**
- VM / Container
- Virtueller Speicher
- Wie funktioniert das
- Was macht Speicherverwaltung generell
- Konzepte
- Was wird da so gemacht
### Keine Spickzettel :/
## Kommt nicht dran
- Energieeffizienz
- Dateisysteme
- Plattenspeicherverwaltung
- Und alles was da oben nicht steht :)
## Altklausur WiSe 2324
**Aufgabe1:**
1. Beschreiben Sie Betriebssysteme
2. Grundlegende Funktionalitäten von Kernel
3. Unterschied von monolithische und minimale Kernel grafisch darstellen.
4. Grundsätzlich m.. Bottleneck von verschiedenen Betriebssystem-Varianten
**Aufgabe2:**
1. Beschreiben Sie die Kontrollstruktur von Prozessen blah blah, welche Informationen bekommt man blah blah
2. Unterschied zwischen Thread und Fork() im Zusammenhang mit nebenläufigen Programme
3. 8-Zustandsdiagramm von Linux
4. Beschreiben Sie die Funktion von Signalen im BS/Prozess?
**Aufgabe3:**
1. Beschreiben Sie Interprozesskommunikation thingy
2. Nenne Sie 3 Methoden davon und beschreiben Sie diese
3. Beschreiben Sie die Funktionen von verdrängende und kooperative Scheduling
4. Warum Priorisierung Scheduling und Wie
**Aufgabe4:**
1. verschiedene Partionierungsverfahren beschreiben
2. Speicherabstraktion und Funktion von Adressenräumen
3. Paging erklären
4. Virtueller Speicherraum vs Container

View File

@ -0,0 +1,86 @@
# Agile Design
> [UML](UML.md) ist nicht Software Design
- Diagramme repräsentieren einen Teil des SW-Designs
- Source Code
- Design ist ein abstraktes Konzept
- Struktur und Form des Projekts
- Detaillierte Beschreibung der Klassen, Module, Methoden
## What goes wrong with Software
- Im besten Fall
- Projekt startet mit klarem Bild, was das System tun soll
- Design ist ein Bild in den Köpfen der Devs
- Mit Glück: Klarheit des Designs schafft es bis zum ersten Release
- Häufig geht vorher was schief
- Programm wird schwieriger wartbar
- kleinste Änderungen werden kompliziert
- Neudesign geht meistens schief
- Das alte System wächst weiter, neues muss mithalten
- Probleme im neuen Design entstehen
- Software geht kaputt, wenn es anfängt mit Design Smells:
## Design Smells
### Rigidity (Steifigkeit)
- Das Design ist schwer zu ändern
- Code ist schwer zu ändern
- kleine Änderungen erzeugen Probleme in dependent Modulen
- je mehr Module geändert werden müssen, desto mehr steif ist das Design
- Ergebnis:
- Änderungen dauern deutlich länger als gedacht
### Fragility (Zerbrechlichkeit)
- Das Design ist einfach kaputtzumachen
- Neue Probleme sind in unvorhergesehenen Umgebungen
- Lösen dieser Probleme führt zu neuen Problemen
- Fragilität wird mit der Zeit höher
- Ist sehr normal
- Module sind bekannt dafür, dass sie repariert werden müssen
- Sind auf der Bug Liste
- Niemand will sich der Aufgabe widmen
### Immobility
- Das Design ist kaum neu zu benutzen
- Enthält Teile, die in anderen Systemen sinnvoll wären
- Risiko involviert in Aufteilung
- Ungünstig, aber sehr häufig
### Viscosity
- Es ist schwer das Richtige zu tun. Zwei Formen:
1. Viskosität der Software
- Devs entscheiden zwischen Designerhaltung und einfacher Lösung
- Design sollte design erhaltende Änderungen fördern
2. Viskosität der Umgebung
- Umgebungen, die einfache statt design erhaltende Änderungen
- Lange compile Zeiten verringern Lust auf recompilen
- Lange VCS-Check-ins verringern Check-ins
### Needless Complexity
- Ein Design enthält Elemente, die momentan nicht nützlich sind
- Passiert häufig, wenn Devs Änderungen erwarten
- Vorbereitung für zukünftigen Code
- Das Design muss das Gewicht dieser Elemente nun mittragen
- Manche Vorbereitungen sind nützlich, aber nicht alle
- Software wird komplex
### Needless Repetition
- Copy Paste sollte nicht benutzt werden
- Wenn Code mehrfach in minimal unterschiedlichen Formen vorkommt
- Devs haben Abstraktion vergessen
- Wiederholungen sollten gefunden und beseitigt werden
- Wiederholender Code macht Änderungen schwierig
- Bugs müssen in allen Wiederholungen geändert werden
- Änderungen nicht immer gleich in allen
### Opacity
- Code ist in einer unverständlichen Art geschrieben
- Häufig in Code der über Zeit weiterentwickelt wird
- Benötigt konstanten Einsatz den Code clean zu halten
- Wenn Code das erste Mal geschrieben wird, scheint er clean
- Verständnis auf intimer Ebene
- Devs müssen aus der Sicht eines Außenstehenden gucken
- Refactor bis Leser es verstehen können
- Code von anderen lesen lassen

View File

@ -0,0 +1,277 @@
# Design Patterns
- Typische Lösung für häufige Probleme im Software Design
- Kein Code, nur Lösungsansatz
- Gute OO-Designs sind wiederverwendbar, erweiterbar, wartbar
## Pattern - SOLID
| | Factory | Singleton | Composite | Adapter | Facade | Observer | Strategy | State |
|-----------------------------------------------------------------|---------------------------------------------------------------|-----------|---------------------------|--------------------------------|-----------------------------|----------|----------|-------|
| [Srp](SOLID-Principle.md#s-single-responsibility-principle-srp) | X <br/>viele unterschiedliche Creator, die eine Aufgabe haben | - | ? <br/>(sowohl als auch) | x | X<br/>mit Tendenz zu ? | X | | |
| [Ocp](SOLID-Principle.md#o-open-closed-principle-ocp) | X | - | X | x | - <br/>zumindest in Vorlage | X | | |
| [Lsp](SOLID-Principle.md#l-liskov-s-substitution-principle-lsp) | ? | - | ? <br/>(kann, muss nicht) | - | - | X | | |
| [Isp](SOLID-Principle.md#i-interface-segregation-principle-isp) | ?/X | - | - | X<br/>sollte, kann aber auch ? | - <br/>zumindest in Vorlage | X | | |
| [Dip](SOLID-Principle.md#d-dependency-inversion-principle-dip) | X | - | X | X | - <br/>zumindest in Vorlage | ? | | |
### Legend
- **X**: follows clearly
- **?**: not sure, might follow / changes with implementation
- **-**: has nothing to do with it
## Typen von Design Patterns
- **Creational Patterns**
- Objekterstellungsmechanismen → erhöhen Flexibilität
- **Strukturelle Pattern**
- Objekte anwenden und Klassen in größeren Strukturen gruppieren ohne Flexibilität einzubußen
- **Behavioral Patterns**
- Algorithmen und Zuordnung von Verantwortlichkeiten
## How to use a design pattern
- Bibliotheken
## Observer Pattern
- One-To-Many Abhängigkeit
- Wenn ein Objekt sich ändert
- Alle Abhängigkeiten werden benachrichtigt
### Nutzung Observer Pattern
- Wenn Zustandsänderung eines Objekts Änderung in anderen Objekten hervorruft
- Wenn Objekte etwas beobachten müssen für eine bestimmte Zeit/Fall
### Beispiel Observer Pattern
- Kunden über Verfügbarkeit von Produkten informieren
- 2 Typen von Objekten: Kunde, Markt
#### Pull
- Kunde fragt häufiger nach, ob es da ist
- Meistens: NEIN
#### Push
- Markt schreibt alle Kunden an, sobald ein Produkt verfügbar ist
- Auch die, die kein Interesse haben
#### Observer
- Jedes Produkt hat eine Liste von Subscribern
- Sobald sich Verfügbarkeit ändert alle benachrichtigen
### Struktur Observer Pattern
![image_375.png](image_375.png)
#### Subject (Interface)
- Kennt seine Beobachter
#### Observer (Interface)
- Definiert Interface für Objekte, welche benachrichtigt werden sollen
#### ConcreteSubject
- Speichert Daten (oder Zustand) der Interesse
- Sendet Benachrichtigung bei Änderung
#### Concrete Observer
- Behält Referenz zu ConcreteSubject
- Gespeicherter Zustand bleibt gleich mit Subject-Zustand
- Implementiert das update-Interface des Observers
### Fazit Observer Pattern
- Wird gefördert durch das [OPC](SOLID-Principle.md#o-open-closed-principle-ocp)
- [LSP](SOLID-Principle.md#l-liskov-s-substitution-principle-lsp) wird angewendet
- [DIP](SOLID-Principle.md#d-dependency-inversion-principle-dip) wird angewendet
- [ISP](SOLID-Principle.md#i-interface-segregation-principle-isp) wird manchmal angewendet
- Manchmal kann eine Klasse Observer und Subjekt sein
## Factory Method (Virtual Constructor)
- Interface für die Erstellung eines Objekts
- Lässt Subklassen entscheiden welche Klassen instanziiert wird
- Ersteller Klassen wissen nicht von den tatsächlichen Objekten
### Struktur Factory Method
![image_376.png](image_376.png)
#### Product (Abstract Class / Interface)
- Definiert üblichen Typ der Objekte
- Abstraktion, welche von der restlichen Codebase genutzt wird
#### Concrete Product(s)
- Implementierung des Produkt-Interface
#### Creator (Abstract Class)
- Deklariert Factory-Methode
- Gibt Objekt zurück
- Kann noch andere Methoden enthalten
#### ConcreteCreator
- Jedes semantische Produkt hat seinen eigenen ConcreteCreator
- Überschreiben der Factory-Methode
- Implementierung der Kreation der spezifischen Produkte
- Mehrere ConcreteCreator können ein ConcreteProduct erstellen (bspw. verschiedene Werte)
### Beispiel Factory Pattern
- **Logistik Management Anwendung**
- Erste Version kann nur mit LKWs transportieren
- Transportation mit Schiff kommt dazu
- Code aus LKW Klasse muss teilweise auch in Schiffklasse verwendet werden
- Vllt. kommen ja noch mehr Transportmittel dazu?
- **Lösung**
- ![image_377.png](image_377.png)
- Objektkreation macht nur die Factory-Methode, spezifisch für das Produkt
- In diesem Fall Transport
- Logistics ist der Ersteller
- Plan für die Lieferung
- Definierung der FactoryMethode
- ConcreteCreators
- ![image_378.png](image_378.png)
### Fazit Factory Method
- Implementierung von OO Prinzipien
- [OCP](SOLID-Principle.md#o-open-closed-principle-ocp)
- Motivierung ist, dass Applikation erweiterbar ist
- Client bleibt geschlossen
- [LSP](SOLID-Principle.md#l-liskov-s-substitution-principle-lsp)
- Kann gestört werden durch unterdrückung der Standardimplementierung durch eine Subklasse
- [DIP](SOLID-Principle.md#d-dependency-inversion-principle-dip)
- Client definiert/besitzt Interface für Ersteller und Produkte
- Bestärkt [Loose Coupling](ImplementingForMaintainability.md#loose-coupling)
## Abstract Factory
- Interface für die Erstellung von Familien oder Abhängigkeiten von Objekten
### Struktur Abstract Factory
![image_379.png](image_379.png)
#### AbstractFactory (Interface)
- Deklariert Interface fpr Operationen, die Objekte produzieren
#### ConcreteFactory
- Repräsentiert Factory für eine Variante/Familie von Produkten
- Implementiert die Operationen, um Objekte zu erstellen
#### AbstractProduct (Interface)
- Deklariert Interface für einen Typ
#### ConcreteProduct
- Definiert konkretes Produkt der Familie
#### Client
- Nutzt nur AbstractFactory und AbstractProduct
### Beispiel Abstract Factory
- ![image_380.png](image_380.png)
- AbstractProduct
- Chair, Sofa, CoffeeTable
- Produkt
- 3 jeder abstrakten Klasse
- Abstract Factory
- Interface für FurnitureFactory
- ConcreteFactory
- Implementierung des AbstractFactory Interface
### Fazit Abstract Factory
- **OO Prinzipien**
- [OCP](SOLID-Principle.md#o-open-closed-principle-ocp)
- [LSP](SOLID-Principle.md#l-liskov-s-substitution-principle-lsp)
- Abhängig von der Implementierung
- [DIP](SOLID-Principle.md#d-dependency-inversion-principle-dip)
- Client definiert/besitzt Interface für Ersteller und Produkte
## Singleton
- Sorgt dafür, dass eine Klasse nur ein Interface hat und dieses global erreichbar ist
- Wird genutzt, wenn eine Klasse nur eine einzelne Instanz haben soll
- bspw. DatenbankVerbindung
### Struktur Singleton
- Konstruktor hat private Sichtbarkeit
- Methode getInstance()
- ![image_381.png](image_381.png)
### Beispiel Singleton
- ![image_382.png](image_382.png)
### Fazit Singleton
- **Probleme**
- Pattern löst zwei Probleme gleichzeitig
- verletzt [SRP](SOLID-Principle.md#s-single-responsibility-principle-srp)
- Kann sychlechtes Design verstecken (bspw. kein Loose Coupling)
## Adapter Pattern
- Erlaubt das Nutzen eines Clients mit einem inkompatiblen Interface
### Structure Adapter Pattern
![image_401.png](image_401.png)
#### Target
- Definiert domänenspezifisches Interface, das der Client nutzt
#### Client (Adapter Pattern)
- Arbeitet mit Objekten, welche mit dem [Target](#target)-Interace übereinstimmen
#### Adaptee
- Definiert existierendes Interface, welches Adaption benötigt
#### Adapter
- Adaptiert das Interface des Adaptee zum Target-Interface
#### Collaborations
- Client ruft Operationen auf dem Adapter-Interface auf
### Beispiel Adapter Pattern
![image_402.png](image_402.png)
![image_403.png](image_403.png)
### Fazit Adapter Pattern
- **SRP**
- Primäre Business Logik eines Programms ist vom Interface getrennt
- **OCP**
- Neuer Adapter kann, ohne den existierenden Code zu bearbeiten, erstellt werden
- Adapter ändert Interface in eins, das der Client erwartet
- **Sollte vermieden werden, wenn es möglich ist**
## Facade Pattern
- Klasse, die ein simples Interface zu einem komplexen System bereitstellt
### Struture Facade Pattern
![image_404.png](image_404.png)
#### Facade
- Weiß, welche Subsystem-Klassen verantwortlich sind
- Delegiert Client-Anfragen an Klassen
#### Subsystem Classes
- Implementiert Subsystem Funktionalität
- Hat kein Wissen von der Fassade
#### Collaborations Facade Pattern
- Clients kommunizieren mit dem Subsystem durch requests zur Fassade
### Fazit Facade Pattern
- **SRP**
- Kann verletzt werden je nach Implementierung
## Composite Pattern
- Baumartige Objektstruktur
### Structure Composite Pattern
![image_405.png](image_405.png)
#### Component (Abstract Class)
- Deklariert Interface für Objekte in der Komposition
- Implementiert für teilweises default-Verhalten
#### Leaf
- Definiert Verhalten, welches individuell für die Klasse ist
#### Composite
- Definiert Verhalten für Branch-Komponenten
#### Client (Composite Pattern)
- Nutzt Objekte in der Komposition durch das Interface
### Beispiel Composite Pattern
![image_406.png](image_406.png)
![image_407.png](image_407.png)
## Strategy Pattern
![image_408.png](image_408.png)
## State Pattern
![image_409.png](image_409.png)

View File

@ -0,0 +1,29 @@
# Design Principles
## [SOLID Design Principles](SOLID-Principle.md)
- Fokus auf der Erstellung von Code
- Wartbar, Robust, Wiederverwendbar
### S - Single Responsibility Principle (SRP)
- Eine Klasse sollte nur eine einzige Aufgabe / Verantwortung haben
### O - Open/Closed Principle (OCP)
- Software Komponenten sollten nur fpr Erweiterung, nicht für Modifikation offen sein
### L - Liskov's Substitution Principle (LSP)
- Basisklassen müssen komplett passend für die erbenden Klassen sein
### I - Interface Segregation Principle (ISP)
- Clients sollten nicht dazu verpflichtet werden unnötige Methoden zu implementieren
### D - Dependency Inversion Principle (DIP)
- Abhängig von Abstraktion, nicht Konkretion
## Favor Composition over Inheritance
- Vererbung ist ein offensichtlicher Weg um Code von der Basisklasse wiederzuverwenden
- Unterklassen können die Codebasis der Basisklassen nicht verkleinern
- Methoden des Interfaces müssen alle implementiert werden
### Composition
- Inheritance: _is-a relationship_
- Composition
- _contains relationship_
- Prinzip kann auch auf Aggregation angewendet werden
- ![image_374.png](image_374.png)

View File

@ -0,0 +1,51 @@
# Designing for Maintainability
## [UML (Unified Modeling Language)](UML.md)
```mermaid
classDiagram
class AdventurePackage {
-title: String
-description: String
}
class Trip {
-startingDate: Date
}
class Accommodation {
-name: String
-address: String
}
class Person {
-name: String
-address: String
}
class Participant {
}
class TourGuide {
}
class Booking {
-bookingDate: Date
-isPaid: Boolean
}
Person <|-- Participant
Person <|-- TourGuide
AdventurePackage "1" --o "0..*" Trip : contains >
Trip "0..*" -- "1" Accommodation : has >
Trip "0..*" -- "1" TourGuide : leads >
Trip "0..*" -- "0..*" Participant : booked by >
Participant "1" --o "0..*" Booking : makes >
Booking "0..*" -- "1" Trip : for >
Booking "0..*" -- "1" Participant : by >
TourGuide "1" --o "0..*" AdventurePackage : certified for >
```

View File

@ -0,0 +1,214 @@
# Implementing for Maintainability
> **We are NOT DONE when the code works!**
>_Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live_
>
> ~_John F. Woods_
## Materials
- [Refactoring _by Martin Fowler_](https://learning.oreilly.com/library/view/refactoring-wie/9783958459434/)
- [refactoring catalog](https://refactoring.com/catalog/)
- [Clean Code _by Uncle Bob_](https://learning.oreilly.com/library/view/clean-code/9783826655487/)
## Introduction
- Code wird häufiger gelesen als geschrieben
- **Refactoring** ist ein
- Prozess, der die Struktur des Codes verbessert, ohne die Funktion zu verändern
- disziplinierter Weg den Code zu bereinigen und so die Chance auf Bugs zu minimieren
- **Code Smells**
- Charakteristik im Code, das etwas falsch sein könnte
- Nicht alle Zeichen von Code Smells sind zwingend ein Zeichen von schlechtem Code
## Refactoring
### Rename Variables
```c++
double a = height * width
double area = height * width
```
### Replace magic literals
```c++
2 * 3.14 * radius
2 * pi * radius
```
### Extract Variable
```c++
void renderBanner(){
if((platform.toUpperCase().indexOf("MAC") > -1) &&
(browser.toUpperCase().indexOf("IE") > -1) &&
wasInitialized() && resize > 0){
//do something
}
}
void renderBanner() {
final bool isMacOs = platform.toUpperCase().indexOf("MAC"") > -1;
final bool isIE = browser.toUpperCase().indexOf("IE") > -1;
final bool wasResized = resize > 0;
if (isMacOs && isIE && wasResized){
//do something
}
}
```
### Extract Function
```c++
void printOwing(){
printBanner();
//prinz details
std::cout << "name: " << name << std::endl;
std::cout << "amount: " << getOutstanding() << std::endl;
}
void printOwing(){
printBanner();
printDetails(getOutstanding());
}
void printDetails(double outstanding){
std::cout << "name: " << name << std::endl;
std::cout << "amount: " << outstanding << std::endl;
}
```
## Meaningful Names
- Namen im Code sollten immer die Intention der Variable/Funktion/Klasse zeigen
- Umbenennen, falls nicht
- Ein Wort pro Konzept
- immer getName() bspw.
| Solution Domain Names | Problem Domain Names |
|-----------------------|----------------------------------------------------------------------|
| Developer-Sprache | Code mit Kundenkontakt sollte verständlich für nicht-Entwickler sein |
## Functions
- Sollten klein sein
- Nur eine Zeile im body von:
- if/else
- for-loop
- while-loop
- Sollten nur eine Aufgabe haben
- Geschafft, wenn
- es nicht möglich ist eine Funktion daraus zu extrahieren
- sie keine Side-Effects haben
- sie entweder auf etwas antworten ODER etwas tun
- switch-Statements nur, wenn
- sie nur einmal vorkommen
- sie polymorphe Objekte erzeugen
- sie nicht für den Rest des Systems sichtbar sind
> **Don't Repeat Yourself! (DRY)**
### Arguments
- Weniger Argumente machen den Code lesbarer
- **Flag arguments are ugly**
- Boolean in Funktion mitgeben zeigt, dass die Funktion mehrere Sachen macht → :(
- Ideale Anzahl an Argumenten ist 0
- 1 Argument (**monadic**)
- Fragen an ein Argument
- _bspw. ```boolean file exists(String fileName)```_
- Operation an argument ausführen und Ergebnis zurückgeben
- Events
- Kein Rückgabewert
- 2 Argumente (**dyadic**)
- schwieriger zu verstehen
- Sind manchmal trotzdem sinnvoll
- _bspw. wenn man einen Punkt (x, y) mitgibt_
- 3 Argumente (**triadic**) (_sollten, wenn möglich, vermieden werden_)
- sollten vermieden werden
- Mehr Argumente (**polyadic**) (_sollten vermieden werden_)
### Argument Objects
- Wenn eine Funktion mehr als 2-3 Argumente braucht
- Objekt erstellen, welches mehrere Argumente zusammenfasst
- _bspw. ```double x, double y → Point center```
### Argument Lists
- Falls beliebig viele Argumente mitgegeben werden sollen, diese aber identisch behandelt werden
- Zählen als "ein" Argument
- _bspw. ```String.format("\%s worked \%.2 hours.", name, hours)```
- Ist dyadic
## Comments
> **Don't comment bad code - rewrite it!**
> ~_B.W. Kernighan and P.J. Plaugher_
### Good comments
- gibt es, aber die besten sind die, die du nicht mehr schreiben musst
#### Legal comments
- sind häufig nötig und verständlich
- sollten trotzdem vermieden werden, indem auf ein Lizenz-File verwiesen wird
- _bspw. Copyright etc._
#### Informative comments
- manchmal sollte man basic Informationen mitgeben, um die Sprache zu verstehen
- _bspw. ```//format matched kk:mm:ss``` ```"\\d*:\\d*:\\d*```_
#### Explanation of Intent
- _bspw._ ![image_49.png](image_49.png)
#### Clarification
- _bspw._ ![image_50.png](image_50.png)
#### Warning of Consequences
- _bspw._ ![image_51.png](image_51.png)
#### TODO Comments
- Sollten auch vermieden werden, einfach fertig machen :)
#### Amplification
- Manchmal zeigen Kommentare wie wichtig etwas ist
- _bspw._ ![image_52.png](image_52.png)
### Bad Comments
- Wenn der Code eh schon verständlich genug ist
- Zu viele Informationen
- Auskommentierter Code
- Nicht verständliche Verbindung zwischen Code und Kommentar
## Formatting / Style Guides
> Der beste Stil ist der, der durchgängig ist
## Classes
- Sollten klein sein
- Wird gemessen in Responsibilities
- **Single Responsibility Principle (SRP)**
- Klassen sollten nur EINE Aufgabe haben
- Führt zu high cohesion
| low cohesion | high cohesion |
|------------------------------------------------------------------------|-------------------------------------------------------------------------|
| bewirbt Schwierigkeit zu warten, testen, wiederverwenden, zu verstehen | bewirbt Robustheit, Verständlichkeit, Wiederverwendbarkeit, Reliability |
## Loose Coupling
> **Law of Demeter**
>
> _Talk to Friends, not to Strangers_
- Ein Freund eines Freundes ist ein Fremder
![image_82.png](image_82.png)
- Minimiere den Grad von Interdependencies
![image_53.png](image_53.png)

View File

@ -0,0 +1,75 @@
# Introduction
## What is Software Engineering
> **Definition according to Ian Sommerville**<br/>
> Software engineering is an _engineering discipline_ that is concerned with all aspects of
> _software production_ from the early stages of system specification through to maintaining
> the system after it has gone into use.
| ...Ingenieurdisziplin... | ...alle Aspekte der Softwareproduktion... |
|------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| Ingenieure lassen Dinge funktionieren! | nicht nur die Softwareentwicklung |
| Sie wenden Theorien, Methoden und Werkzeuge dort an, wo diese angemessen sind | beinhaltet auch Aktivitäten wie _Projektmanagement_, Entwicklung von Werkzeugen, Methoden und Theorien zur Unterstützung |
| Lösungen **müssen** innerhalb organisatorischer und finanzieller Einschränkungen funktionieren | |
## Iron Triangle: Organizational and Financial Constraints
![image_38.png](image_38.png)
- visualisiert Einschränkungen im Projektmanagement
- verkündet:
1. Qualität der Ergebnisse eines Projekts ist durch folgende Faktoren eingeschränkt:
- Kosten (_verfügbar: Budget, Ingenieure, ..._)
- Zeit (_verfügbar: Zeit, Fristen_)
- Umfang (_Funktionen, bereitgestellte Funktionalität_)
2. PM kann zwischen Einschränkungen handeln
3. Änderungen in einer Einschränkung erfordern Änderungen in anderen zur Kompensation, oder die Qualität wird leiden
- Die Realität ist komplexer
- Geld in ein vollständig ausgelastetes Projekt zu stecken, kann es verlangsamen
## Software Development Lifecycle (SDLC)
```mermaid
stateDiagram
1: Requirement Analysis
2: Design
3: Implementation
4: Testing
5: Maintaining/Operations
1-->2
2-->3
3-->4
4-->5
5-->1
```
### Requirement Analysis
- Understand what your client wants and/or needs
### Design
- Design a solution that meets [functional/non-functional](IntroductionOOAD.md#requirements-in-software-engineering) requirements
### Implementation
- Actually build the system meeting required quality goals
### Testing
- Ensure that the whole system meets all requirements
### Maintaining/Operations
- The system serves its purpose (earns money)
## Software Quality
### Requirements in Software Engineering
| **Functional Requirements (FR)** | **Non-Functional Requirements (NFR)** |
|------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| Systemfunktionen, Anwendungsfälle, ... | Eigenschaften des Systems als Ganzes, nicht im Zusammenhang mit der Funktionalität (_bspw. Sicherheit, Performance, Wartbarkeit_) |
| Können unterschiedlich detailliert erfasst sein (je nach Komplexität des Projekts) | Beeinflussen die gesamte Architektur eines Systems, nicht nur einzelne Komponenten |
| FRs sind meist höchste Prio des Clients, aber auch am einfachsten zu verhandeln | Wenn ein NFR scheitert, kann das ganze System nicht funktionieren |
### Eight Quality Characteristics
![image_39.png](image_39.png)
### Maintainability
- Modularität
- Wiederverwendbarkeit
- Analysierbarkeit
- Modifizierbarkeit
- Testbarkeit
>_Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live_
>
> ~_John F. Woods_

View File

@ -0,0 +1,107 @@
```mermaid
classDiagram
class Person
<<abstract>> Person
Person : - name
Person : - adress
class Tourguide
Tourguide : - certifiedAdventurePackages <AdventurePackage*> vector
class Participant
class AdventurePackage
AdventurePackage : - title
AdventurePackage : - description
class Accommodation
Accommodation : - name
Accommodation : - adress
class Trip
Trip : - startingDate
class Booking
Booking : - payed
Booking : - dateOfBooking
Tourguide --|> Person
Participant --|> Person
Trip "1..*" o-- "1..*" AdventurePackage
Trip "*" o-- "1" Accommodation
Participant "1..*" -- "1..*" Trip: Booking
Participant "1..*" .. Booking
Booking "1..*" .. "1..*" Trip
Tourguide "1" --o "*" Trip
Tourguide "1..*" -- "1..*" AdventurePackage
```
```mermaid
sequenceDiagram
actor Tom as Tom : Human
participant LibGui as libGUI
participant Lib as Lib
participant CTom as Tom : Customer
activate LibGui
Tom -) LibGui: name = "HP1"
LibGui ->>+ Lib: getEbook("HP1")
create participant EBook as HP1 : EBook
Lib -->>+ EBook: <<create>> EBook("HP1", 3.99)
note right of EBook: Im Konstruktor von EBook fehlt<br/>die Zuweisung des Preise.<br/>Hier ergänzt
EBook --)- Lib: return
Lib --)- LibGui: return
LibGui --)+ Tom: return
Tom -)- LibGui: clickBorrowButton
LibGui ->>+ Lib: getEbook("HP1")
Lib ->>+ CTom: borrow("HP1")
CTom ->>+ EBook: getPrice()
EBook --)- CTom: return 3.99
CTom ->> CTom: charge(3.99)
CTom --)- Lib: return
Lib --)- LibGui: return
LibGui ->>+ EBook: generateLink()
EBook --)- LibGui: return link
activate LibGui
LibGui ->> LibGui: showLink()
LibGui --)- LibGui: return
LibGui --) Tom: return
destroy EBook
LibGui -x EBook: <<destroy>>
destroy CTom
LibGui -x CTom: <<destroy>>
destroy Lib
LibGui -x- Lib: <<destroy>>
destroy LibGui
Tom --x LibGui: <<destroy>>
```
```mermaid
classDiagram
class Kreis{
<<abstract>>
- radius : ft
+ setRadius()
}
class Ellipse{
- breite : ft
- hoehe : ft
+ setBreite()
+ setHoehe()
}
Ellipse --|> Kreis
```

View File

@ -0,0 +1,124 @@
```plantuml
@startuml
class Subject <<abstract>>{
+ ~Subject()
+ attach(obersever: Observer*): void
+ detach(observer: Observer*): void
+ notify(): void
}
class Observer <<interface>>{
+ {abstract} update(): void
+ ~Observer()
}
class SystemBattery{
+ setBatteryLevel(data: int): void
+ getData(): int
- BatteryLevel: int
}
class BatteryApp{
+ BatteryApp(subject: SystemBattery&, name: string)
+ update(): void
- name: string
}
class BatteryLogger{
+ BatteryLogger(subject: SystemBattery&, name: string)
+ update(): void
- name: string
}
Subject <|-- SystemBattery
Observer <|-- BatteryApp
Observer <|-- BatteryLogger
SystemBattery "1" *- "*" BatteryApp: - subject: SystemBattery&
SystemBattery "1" *- "*" BatteryLogger: - subject: SystemBattery&
Subject "*" -o "*" Observer: - observers: list<Observer*>
@enduml
```
```mermaid
sequenceDiagram
actor human
activate human
create participant Main
human -)+ Main: <<create>>
Note over Main: create Observers and Subject
create participant SystemBattery as systemBattery: Subject
Main ->>+ SystemBattery: <<create>>
SystemBattery --)- Main: return
create participant Observer as batteryApp: Observer
Main ->>+ Observer: <<create>>(SystemBattery* = *systemBattery, name = "BatteryApp")
Observer->>+ SystemBattery: attach(this)
SystemBattery ->> SystemBattery: observers.push_back(batteryApp)
SystemBattery --)- Observer: return
Observer --)- Main: return
create participant Logger as batteryLogger: Observer
Main ->>+ Logger: <<create>>(SystemBattery* = *systemBattery, name = "BatteryLogger")
Logger->>+ SystemBattery: attach(this)
SystemBattery ->> SystemBattery: observers.push_back(batteryLogger)
SystemBattery --)- Logger: return
Logger --)- Main: return
Note over Main: Set BatteryLevel to 87
Main ->>+ SystemBattery: setBatteryLevel(data = 87)
activate SystemBattery
SystemBattery -->> SystemBattery: BatteryLevel = data
SystemBattery --) human: "New value 87
%% Loop for each observer
note over SystemBattery: update each Observer
SystemBattery ->>+ SystemBattery: notify()
SystemBattery ->>+ Observer: update()
Observer ->>+ SystemBattery: getData()
SystemBattery --)- Observer: return BatteryLevel
Observer -->> Observer: newValue = BatteryLevel
Observer --) human: "This is batteryApp! Received value 87"
Observer --)- SystemBattery: return
SystemBattery ->>+ Logger: update()
Logger ->>+ SystemBattery: getData()
SystemBattery --)- Logger: return BatteryLevel
Logger -->> Logger: newValue = BatteryLevel
Logger --) human: "TThis is batteryLogger! Received value 87! Will proceed to log value into file..."
Logger -->> Logger: log data into file
Logger --)- SystemBattery: return
%% end loop
deactivate SystemBattery
SystemBattery --)- Main: return
Note over Main: delete created Objects
Main --x Observer: <<delete>>
activate Observer
Observer ->>+ SystemBattery: detach(this)
SystemBattery ->> SystemBattery: overservers.remove(batteryApp)
deactivate Observer
destroy Observer
SystemBattery --)- Observer: return
Main --x Logger: <<delete>>
activate Logger
Logger ->>+ SystemBattery: detach(this)
SystemBattery ->> SystemBattery: overservers.remove(batteryLogger)
deactivate Logger
destroy Logger
SystemBattery --)- Logger: return
destroy SystemBattery
Main --x SystemBattery: <<delete>>
Main --)- human: return
destroy Main
human --x Main: <<destroy>>
deactivate human
```

View File

@ -0,0 +1,113 @@
# Requirements Analysis
## Domain Diagram
- Konzeptuelles Modell um ein gemeinsames Vokabular im Projekt-Team zu etablieren
### Problem Domain
- Devs haben ein gemeinsames Verständnis von Lösungen
### Solution Domain
- Es muss ein gemeinsames Verständnis von dem Arbeitsumfeld des Klienten geschaffen werden
### Beispiel Domain Diagram
![image_410.png](image_410.png)
- Zeigt die wichtigsten Problem-Domains und ihre Verbindungen
## UML Use Case Diagram
- System Anforderungen erfassen
- NUR [Functional Requirements](IntroductionOOAD.md#requirements-in-software-engineering)
### Notation
#### Actor
- ![image_411.png](image_411.png)
- Identifizierung:
- ![image_412.png](image_412.png)
#### Use Case
![image_413.png](image_413.png)
#### Communication Lines
![image_414.png](image_414.png)
#### System Boundaries
![image_415.png](image_415.png)
## User Stories
### Definition
- Beschreiben funktionalen Wert für einen Nutzer des Systems / der Software
- Aspekte
1. **Card**
- Beschreibung der Story
- Genutzt für Planung, Erinnerung
- Traditionell Handschriftlich
- Repräsentiert Kunden-Anforderungen
- nicht Dokumentation
2. **Conversation**
- Gibt Details über Story
- Wichtigster Teil der User Story
- Werden mit dem Kunden vor der Entwicklung diskutiert
3. **Confirmation**
- Akzeptierungskriterien (Tests)
- Dokumentation der Konversation
- Können entscheidend sein, wann eine Story abgeschlossen ist
##### Beispiel UserStory: Job Posting und Search-Website
- Ein Nutzer kann nach Jobs suchen
- Eine Firma kann eine offene Stelle posten
- Ein Nutzer kann einstellen, wer seinen Lebenslauf sehen kann
![image_416.png](image_416.png)
### Good User Stories: INVEST Criteria
![image_417.png](image_417.png)
#### I - Independent
- Unabhängig von allen anderen Stories
- Stories sollten in allen möglichen Reihenfolgen bearbeitet werden können
- Falls eine enge Kupplung besteht
- MERGE
- **Beispiel:**
- ![image_418.png](image_418.png)
#### N - Negotiable
- Stories sind keine festen Verträge
- Kurze Beschreibung von Funktionalität
- Details müssen in Konversation zwischen Kunde und Team verhandelt werden
- Falls wichtige Details vorher bekannt sind
- als Annotation inkludieren
- **Beispiel:**
- ![image_419.png](image_419.png)
#### V - Valuable
- **Beispiel:**
- ![image_420.png](image_420.png)
#### E - Estimable
- Devs müssen workload abschätzen können
- **Gegenbeispiel:**
- ![image_421.png](image_421.png)
#### S - Small
![image_422.png](image_422.png)
#### T - Testable
## Gathering Stories
- **Nutzer-Interviews**
- Standard
- Wichtig:
- Echte Nutzer befragen
- Fragen sollten offen und kontextfrei sein
- **Umfragen**
- Für weitere Details in bekannten Stories
- Beispielfragen:
- Wie oft nutzt du [Feature]
- Warum nutzt du [Feature] nicht mehr
- **Beobachtungen**
- Nutzer beobachten, während Nutzung befragen
- Seltene Möglichkeit zur Durchführung
- Wenn dann da: NUTZEN!
- **Story-Writing-Workshops**
- Meeting mit Devs, Nutzer, Produkt-Kunde, andere Beteiligte
- Schnellste Möglichkeit für neue Stories
- Führen des Workshops benötigt Erfahrung

View File

@ -0,0 +1,90 @@
# SOLID
## S - Single Responsibility Principle (SRP)
- Änderungen entstehen, wo Verantwortung ist
- Verantwortung ist ein Grund zur Änderung
- Falls eine Klasse mehr als eine Verantwortung hat
- Verantwortungen werden gruppiert :(
- Führt zu [fragilem Design](AgileDesign.md#fragility-zerbrechlichkeit)
### Beispiel SRP Verletzung
- ![image_364.png](image_364.png)
- Erzeugte Probleme
- GUI muss in computionalGeometryApplication inkludiert werden
- Änderungen in Graphical führen zu Änderungen in computional
- Besser:
- ![image_365.png](image_365.png)
### Was ist eine Responsibility
- Ein Grund zur Änderung
- Wenn jemandem mehr als eine Idee einfällt, warum man die Klasse ändern könnte
- Mehrere Responsibilitys
## O - Open/Closed Principle (OCP)
- Änderungen an einzelnen Dateien sollen sich nicht auf andere Klassen auswirken
- Lieber neuen Code statt Code zu ändern, der funktioniert
- Wird durch Abstraktion erreicht
- Abstraktion ist nach außen fest
- Geerbte Klassen können Methoden neu zu ihren Bedürfnissen anpassen
### Beispiel OCP Verletzung
- ![image_366.png](image_366.png)
- Client nutzt Server Klasse
- Falls Server sich clientseitig ändert gehts teilweise nicht mehr
- Besser:
- ![image_367.png](image_367.png)
### Wann OCP anwenden?
- Gegen welche Änderungen möchte man sich schützen?
- Nicht gegen die falschen Änderungen
- häufig falsch, aber passiert
- Häufig unnötig → [Needless Complexity](AgileDesign.md#needless-complexity)
## L - Liskov's Substitution Principle (LSP)
- Subtypen müssen passend zu ihren Basisklassen sein
- Macht OCP besser
### Beispiel LSP Verletzung
- ![image_368.png](image_368.png)
- Pinguin kann nicht fliegen → :(
- Besser:
- ![image_369.png](image_369.png)
## I - Interface Segregation Principle (ISP)
- Niemanden dazu zwingen Interfaces zu nutzen
- ![image_371.png](image_371.png)
### Beispiel ISP Verletzung
- ![image_372.png](image_372.png)
- Besser
- ![image_373.png](image_373.png)
### Conclusion ISP
- Fette Klassen erzeugen schädigende Kupplung zwischen ihren Klienten
## D - Dependency Inversion Principle (DIP)
- Abstraktionen sollten nicht von Details abhängig sein
- DIP behandelt Besitztum und Abhängigkeiten
- Detaillierte Implementierungen definieren die Abstraktion, von der sie abhängig sind
### Naive Layering System
- High Level Policy Layer
- Lower Level Mechanism Layer
- Detailed Level Utility Layer
### Inversion of Ownership
- ![image_370.png](image_370.png)
### When to use the DIP?
- Nichts sollte von einer konkreten Klasse abhängig sein
- Keine Variable sollte einen Pointer auf eine andere Klasse enthalten
- Keine Methode sollte eine bereits implementierte Methode seiner Basisklasse überschreiben
### Conclusion DIP
- Sowohl Policies als auch Detail basieren auf Abstraktion
- Fundamentaler low-level Mechanismus hinter OOAD

View File

@ -0,0 +1,92 @@
# Software Processes
In den 1950ern wurde Software an Seite der Hardware entwickelt
- Ziel dieser Prozesse war das komplette Produkt in einem einzigen Projekt zu entwerfen
## Classic Organizational Structure
- **Business or Client**
- braucht neue Software/System
- Definiert Kriterien, welche für die Vollständigkeit des Systems essenziell sind
- Definiert _[requirements specification](IntroductionOOAD.md#requirements-in-software-engineering)_, welche das benötigte System beschreibt
- **Entwicklungsteam oder Software-Firma**
- Bekommt _requirements specification_
- Designt und entwickelt das System anhand der gegebenen Spezifikationen
- Erstellt ein Handbuch
- **Operations Team**
- Bekommt Handbuch
- Nimmt Rechenschaft für das Laufen der Software auf sich
- Gibt auftretende Fehler an das Entwicklungsteam weiter
## Handling of Change: Implications
Ursprüngliches Projekt ist fertig - Kunde ist aber nicht glücklich
- Ein neues Projekt startet den SDLC neu
- ![image_42.png](image_42.png)
## Waterfall Model
- Sequenzielle Ausführung der Phasen des [SDLC](IntroductionOOAD.md#software-development-lifecycle-sdlc)
- Jede Phase wird mit einer Dokumentation des Schritts beendet
- Iterationen sind nur zwischen zwei aufeinanderfolgenden Phasen möglich
- ![image_40.png](image_40.png)
- [![image_41.png](image_41.png)](SoftwareProcesses.md#classic-organizational-structure)
## Neue Modelle
### V-Modell
![image_43.png](image_43.png)
### Spiral-Modell
![image_44.png](image_44.png)
## Agile
### The Agile Manifesto
#### 4 Werte
- **Individuen und Interaktionen** über _Prozesse und Werkzeuge_
- **Funktionierende Software** über _verständliche Dokumentation_
- **Arbeit mit Kunden** über _Vertragsverhandlungen_
- **Anpassung an Veränderung** über _folgen des Plans_
#### 12 Prinzipien
- Funktionierende Software ist die primäre Ressource um den Fortschritt zu messen
- Die höchste Priorität ist den Kunden durch frühe und durchgehende Lieferung von wertvoller Software glücklich zu machen
- Liefere funktionierende Software regelmäßig, ~mehrere Wochen bis mehrere Monate → kürzer = besser
- Durchgehende Aufmerksamkeit auf technische Exzellenz und gutes Design verbessert die Agilität
### Strongly Iterative Development
Verstärkt durchgehende Kreation von Nutzen für Kunden
- Scope: wichtigsten Features der Iteration
- ![image_45.png](image_45.png)
Durchgehende Anpassung der Anforderungen an aktuelle Nachfrage
- ![image_46.png](image_46.png)
### Small and Cross-functional Teams
- Selbst organisiert, divers, T-shaped skills
- klein
- ![image_48.png](image_48.png)
- Beispiel Scrum Team:
- **3-9 Developers**
- verantwortlich für alle Aspekte der Entwicklung
- **1 Product Owner**
- spielt Kunde für die Devs, kreiert und priorisiert Features
- **1 Scrum Master**
- Coach, Prozess-Authorität
Business/Client wird Teil des Teams
- Product Owner
- ![image_47.png](image_47.png)
## DevOps
Erweiterung der agilen [Software-Entwicklung](SoftwareProcesses.md#agile)
- nicht nur Dev (_Entwicklung_), sondern auch Ops(_Operations_)
- Gefördert durch dynamische Cloud-Infrastuktur
- Führt zu höherer Qualität
- Devs machen stabileren Code
- fördert Automatisierung in allen Aspekten
DevOps fördert schnellere Iterationen
- Features können individuell ausgeliefert werden
- mehrere Releases am Tag sind normal
- schnellere Feedback-Cycles
- Bessere Adaption zu neuen Anforderungen
- Nutzer-Verhalten kann aufgezeichnet und für spätere Arbeit genutzt werden

View File

@ -0,0 +1,28 @@
# UML (Unified Modeling Language)
## Categories
### Structure Diagrams
- dynamisches Verhalten der Elemente (bspw. Veränderung über Zeit) wird nicht beachtet
- **[Class Diagram](UMLKlassenDiagramme.md)**
- Package Diagram
- **[Object Diagram](UMLKlassenDiagramme.md#objekt-diagramme)**
- Component Diagram
- Profile Diagram
- Composition Structure Diagram
- Deployment Diagram
### Behavior Diagram
- Kann Verhalten detailliert definieren
- Bestimmt, wie sich der Zustand eines Elements über Zeit verändert
- **[State Machine Diagram](UMLStateDiagramme.md)**
- **Use Case Diagram**
- Activity Diagram
- Interaction Diagram
- **[Sequence Diagram](UMLSequenzDiagramme.md)**
- Interaction Overview Diagram
- Communication Diagram
- Timing Diagram

View File

@ -0,0 +1,161 @@
# Klassen Diagramme
https://www.hanser-elibrary.com/doi/epdf/10.3139/9783446431973
- Klassen werden als Boxen dargestellt mit
- Name
- Attribute
- Methoden
### Aufbau Klassen-Diagramm
#### 1. Bereich: Name der Klasse
- beginnt mit Großbuchstaben
- ist ein Nomen
- sollte die Klasse beschreiben
#### 2. Bereich: Attribute der Klasse
Es gibt zwei Arten die Attribute darzustellen
- Inline, dabei muss angegeben werden:
- [Sichtbarkeit](UMLKlassenDiagramme.md#sichtbarkeit-von-attributen-methoden)
- Name
- Typ (primitiv / komplex)
- Durch [Assoziation](UMLKlassenDiagramme.md#association)
- bspw.: entries ![image_96.png](image_96.png)
#### 3. Bereich: Methoden der Klasse
- Haben 4 Elemente:
- [Sichtbarkeit](UMLKlassenDiagramme.md#sichtbarkeit-von-attributen-methoden)
- Name
- ggf Parameter
- Rückgabewert
- Bspw.: ```+ addEntry(int number, string description): void```
### Sichtbarkeit von Attributen / Methoden
- **Public (+)**
- Jedes Objekt anderer Klassen kann zugreifen
- **Protected (#)**
- Jedes Objekt der Klasse und der Unterklassen kann darauf zugreifen
- **Package (~)**
- Jedes Objekt, deren Klasse im selben Package ist, kann darauf zugreifen
- **Private (-)**
- Nur das Objekt selbst kann darauf zugreifen
### Beispiel Klassen Diagramme:
- 3 Klassen (Student, Course, LectureHall)
- Student kann keine bis n Lectures beitreten
- Courses können in keine bis einer LectureHall stattfinden
- Student hat einen first name, last name, date of birth...
- etc.
![image_87.png](image_87.png)
### Erstellung eines Klassen-Diagramms
1. Identifizierung der Klassen
- ![image_107.png](image_107.png)
2. Identifizierung der Attribute
- ![image_108.png](image_108.png)
3. Identifizierung von Generalisierungen
- ![image_109.png](image_109.png)
4. Identifizierung von Assoziationen und Aggregationen
- ![image_110.png](image_110.png)
_Entstandenes UML-Diagramm ist nicht einzig korrektes!_
## Objekt Diagramme
### Beispiel Objekt Diagramme:
- 4 Instanzen / Objekte vom Typ Student (Helen, Mike, Paul)
- Helen ist im Kurs oom und iprog
- Der Kurs db ist in der LectureHall lh2
- ![image_88.png](image_88.png)
## Relationship Overview
Klassen arbeiten zusammen über verschiedene Arten von Relationships
- Relationships werden als Linie zwischen den Boxen dargestellt mit
- Name
- Leserichtung
- Multiplizität
- Sind als Intervall dargestellt _[Min..Max]_
- Falls es kein Limit gibt: *
- Falls Min = Max: nur eins hinschreiben
- Bsp.:
- ```[0..1]```: Attribut hat 0 - 1 Wert
- ```[5]```: Attribut hat genau 5 Werte
- ```[*]```: Attribut hat 0 bis unendlich Werte
- ```[3..*]```: Attribut hat 3 bis unendlich Werte
### Association
Wenn ein Objekt einer Klasse mit Objekten einer anderen Klasse arbeitet
![image_89.png](image_89.png)
- schwächstes Relationship
- Kommunikationspartner können auf Attribute und Methoden des Anderen zugreifen
- Bsp.:
- ![image_98.png](image_98.png)
#### Navigatability
- **x**: Darauf ist nicht zugreifbar
- **>**: Darauf kann zugegriffen werden
- nix: undefined
### Aggregation
Wenn eine Klasse eine Referenz zu Objekten einer anderen Klasse besitzt und teilt
![image_90.png](image_90.png)
- Objekte existieren auch unabhängig
- Es können auch [mehrere Objekte](UMLKlassenDiagramme.md#relationship-overview) in einer Aggregation verbunden werden
### Composition
Wenn eine Klasse Objekte einer anderen Klasse enthält
![image_91.png](image_91.png)
- Nur maximal eine Instanz
- Objekt kann nicht allein existieren
### Generalization (Inheritance)
Wenn eine Klasse ein Typ einer anderen Klasse ist
![image_92.png](image_92.png)
## Erstellung von Klassen
### Appropriate Level of detail
Detail der Zeichnung sollte abhängig vom [SDLC](IntroductionOOAD.md#software-development-lifecycle-sdlc) sein.
1. keine Details (erste Analyse für die ersten Diskussionen des Domänen-Konzepts)
- ![image_93.png](image_93.png)
2. mehr Details (während späterer Analysen)
- ![image_94.png](image_94.png)
3. sehr detaillierte Beschreibung (detaillierte Analyse oder während Implementierung)
- ![image_95.png](image_95.png)
## N-Ary Association
- Relationship zwischen mehr als zwei Klassen
- Wird durch hohle Raute in der Mitte der Klassen dargestellt
- bspw.: ![image_99.png](image_99.png)
### Implementierung in Code von N-Ary Association
- nicht existent in Standard-Programmiersprachen
#### Using Two Binary Associations
![image_100.png](image_100.png)
#### Using additional Class
![image_101.png](image_101.png)
## Association Class
### Introduction Association Class
Erlaubt [N-Ary Associations](UMLKlassenDiagramme.md#n-ary-association)
### Possible Implementations of Association Classes
![image_102.png](image_102.png) ![image_103.png](image_103.png)
## Abstract Class
![image_104.png](image_104.png)
- nur im Kontext von Generalisierungsbeziehungen sinnvoll
## Interface
![image_106.png](image_106.png)

View File

@ -0,0 +1,78 @@
# Sequenz Diagramme
gehören in die Kategorie der Verhaltensdiagramme in UML
Beispiel:
![image_111.png](image_111.png)
## Time
- Zeit läuft von oben nach unten
- Abstand zwischen den einzelnen Elementen hat nichts mit der Dauer derer zu tun
## Participants
- Repräsentieren den Teil des Systems, welcher miteinander interagiert
- Jeder Teilnehmer hat eine lifeline
### Participant Names
- Format: _role [selector] : class_name_
- bspw.:
- admin - wird admin genannt, muss aber nicht einer Klasse zugeschrieben werden
- : ContentManagementSystem - Klasse ist bekannt, muss aber keinen Namen haben
- admin : Administrator - Klasse und Name sind bekannt
- eventHandlers[2] : EventHandler - Teil innerhalb Array und bekannte Klasse
## Messages
- Mit einem Pfeil spezifiziert
- ![image_112.png](image_112.png)
### Message Signatures
- Format für eine Signatur:
- _attribute = sinal_or_message_name (arguments) : return_type_
- abhängig von den Informationen die bekannt sind, ggf auch kürzer
## Activation Bars
Indizieren, dass ein [Teilnehmer](UMLSequenzDiagramme.md#participants) aktiv ist
![image_113.png](image_113.png)
## Nested Messages
- [Nachricht](#messages) von einem [Teilnehmer](#participants) resultiert in weitere Nachrichten, welcher der Empfänger schickt
- Diese neuen Nachrichten werden als "nested" innerhalb der triggernden Nachricht bezeichnet
- ![image_114.png](image_114.png)
- Bspw.:
- participant1 sends initialMessage() to p2
- When p2 receives initialMessage(), p2 becomes active, sends two nested messages to p3
## Message Types
### Message Arrows
![image_115.png](image_115.png)
#### Creation and Destruction
- Nicht alle Teilnehmer leben während der gesamten Sequenz
![image_116.png](image_116.png)
### Creation of Participants
- create() Nachricht zu der Lebenslinie
- **Nutzung der "dropped participant box"**
- macht es klar, dass der Teilnehmer vorher nicht existiert
### Destruction of Participants
- Beendung der Lebenslinie mit dem Löschen-Kreuz
### Synchronous Messages
- Default
- Nachrichtensender wartet auf Antwort von Empfänger
### Return Message
- Zeigt, dass die Kontroller der Aktivierung wieder zum Empfänger zurückgeht
### Asynchronous Message
- _wird von uns nicht innerhalb des Systems genutzt_
- _nur von Mensch zu System_
- Sender wartet nicht bis der Empfänger fertig ist
- Implementierung bspw. durch Threads
## Möglicher Spicker
![image_253.png](image_253.png)

View File

@ -0,0 +1,99 @@
# State Machine Diagrams
## Introduction
- Beschreiben den Zustand von Objekten oder des Systems
### Introduction Example
- Light can be on / off
- ![image_117.png](image_117.png)
## States
- Diskretes, durchgehendes Segment von Zeit, während der das Verhalten des Objekts stabil ist
- Kann eine passive Qualität haben
- _Licht an / aus_
- Kann auch eine aktive Qualität haben / Was das Objekt tut
- _Kaffeemaschine mahlt Kaffee_
- Objekt bleibt in dem Zustand bis es von einem Event stimuliert wird
- States sind **nicht**:
- Objekte oder Komponenten des Systems
- Aktivitäten des Systems
### Internal Activities of States
![image_118.png](image_118.png)
- 3 Aktivitäten die an einem definierten Moment ausgeführt werden
- **entry behavior**
- **do-activity behavior**
- kann unterbrochen werden
- **exit behavior**
- entry- und exit behavior können nicht unterbrochen werden
#### Activities Example
![image_119.png](image_119.png)
### Internal Pseudostate
![image_121.png](image_121.png)
- **nur einmalig**
- Markieren den Start eines Maschinen-Diagramms
- Keine eingehenden Pfeile
- Ein ausgehender Pfeil zum ersten _richtigen_ Zustand
- ohne Events
### Final State
![image_120.png](image_120.png)
- **können mehrere existieren**
- Objekte können permanent in einem End-Status sein
## State Transitions
### External Transitions
![image_122.png](image_122.png)
- Repräsentiert eine Änderung des Zustands von einem Ursprungs-Zustand zu einem Ziel-Zustand
- Eine Transition braucht keine Zeit
- Das System ist immer in einem Zustand, nie in einer Transition
![image_123.png](image_123.png)
#### Syntax of Description: trigger[guard] / behavior
- Alles **optional**:
- **Trigger** (Event), dass eine [Transition](#state-transitions) hervorruft
- **Guard** (Condition), welche die Ausführung der Transition aktiviert
- Sobald das Event stattfindet, muss der Guard erfüllt werden
- Falls dasselbe Event mehrere Transitions eines einzigen States hervorruft
- Die Guards müssen sich gegenseitig ausschließen
- Falls nicht: EIne Transition wird zufällig ausgesucht
- **Behavior** (Effects) wird während der Transition ausgeführt
### Internal Transition
- Handhaben Events innerhalb eines States
- ![image_124.png](image_124.png)
## Types of Events
### Call Events
- Operation calls inklusive der Parameter
- _occupy(user, LectureHall)_
### Time Events
- Zeitbasierter Zustandsübergang (relativ / absolut)
- _relative: after(5 sec)_
- _absolute: when(time == 16:00)_
### Change Events
- Permanente Überwachung, ob eine Bedingung wahr wird
- _when (registration == numberOfSeats)_
### Any Receive Events
- Zur Spezifikation einen Typ eines _else_ Übergangs
- Falls ein Event auftritt, welches keine Übergänge für den aktiven Zustand auslöst
- _the object transitions to S4 without any event that is not e1 or e2_
### Completion Events
- Falls alle Verhaltensweisen eines States vollständig sind
- _once A1 is completed completion event triggers transition to S2_
## State Transition Examples
- ![image_125.png](image_125.png)
- ![image_126.png](image_126.png)
- ![image_127.png](image_127.png)
## Möglicher Spicker
![image_270.png](image_270.png)

View File

@ -0,0 +1,89 @@
# Historie
```mermaid
stateDiagram
[*]--> ersteAutomaten
ersteAutomaten: 60 n Chr.
note right of ersteAutomaten
Alexandriner Heron entwickelte
viele Automaten z.B.
automatische Türen mit Hebeln
_
end note
ersteAutomaten --> zeitDerUhrmacher
zeitDerUhrmacher: 1348-1364
note left of zeitDerUhrmacher
Giovanni de Dondi baute 1348-1364 die
erste Astronomische Uhr
_
end note
note left of zeitDerUhrmacher
Eingabe: Takt
Ausgabe: Zeiger
Zahnräder: innerer Zustand
_
end note
zeitDerUhrmacher --> astronomischeUhr
astronomischeUhr: 1354
note left of astronomischeUhr
Astronomische Uhr
_
end note
astronomischeUhr --> lochkartenWebstuhl
lochkartenWebstuhl: 1725-1728
note right of lochkartenWebstuhl
Basile Bouchon 1725 und Jean
Babtiste Falcon 1728 erfanden
eine Apparatur die über
Lochkarten gesteuert wurde
_
end note
lochkartenWebstuhl --> jaquesDesVaucanson
jaquesDesVaucanson: 1745
note left of jaquesDesVaucanson
Der mechanische Webstuhl wurde
durch Jacques de Vaucanson, einem
Erfinder um 1745 weiterentwickelt,
konnte sich aber immer noch nicht
durchsetzen
_
end note
note left of jaquesDesVaucanson
Vaucanson entwickelte auch andere
Automaten, so die berühmte Ente
_
end note
jaquesDesVaucanson --> jaquard
jaquard: Der Jaquard Webstuhl
note right of jaquard
erste frei programmierbare
Maschine, die in großer Menge
gefertigt wurde
_
end note
note right of jaquard
Der Lochkartenstreifen ist der
erste Datenträger, der
austauschbare Programme trägt
_
end note
jaquard --> lochkartenSteuerungMusik
lochkartenSteuerungMusik: Ende 17. Jhd
note left of lochkartenSteuerungMusik
Drehorgeln, Orchestrion
(stellt ganzen Orchester dar)
Konnte noch nicht speichern
_
end note
lochkartenSteuerungMusik --> ersteRechenmaschine
```

View File

@ -0,0 +1,129 @@
# Klassifikation
> Eigenschaften von Prozessoren
## Klassifizierung gemäß Operandenstruktur
### Stackarchitektur
- Stacks werden unabhängig von der jeweiligen Architektur verwendet
- bei Unterprogrammaufrufen und Prarameterübergaben
- Call-Befehl
- pusht Rücksprungadresse und ggf. Registerstati
- Return
- popt Werte wieder
- ![image_257.png](image_257.png)
![image_254.png](image_254.png)
### Akkumulator Architektur
- Ausgezeichnetes Register: Akku(mulator) (_ehem. ACC_)
- LOAD und STORE wirken nur auf Akku
- expliziter Operand, an jeder Operation beteiligt
- jede Operation braucht nur eine Adresse
- Sehr kompaktes Befehlsformat
- ![image_255.png](image_255.png)
- ![image_256.png](image_256.png)
### Register-Register-Architektur
- RISC (LOAD-STORE-Architektur)
- alle Operationen greifen nur auf Register zu
- 32-512 Register verfügbar
- **nur** LOAD und STORE greifen auf Speicher zu
- Einfaches Befehlsformat fester Länge
- ![image_258.png](image_258.png)
- alle Instruktionen brauchen in etwa gleich lange
- ![image_259.png](image_259.png)
### Register-Speicher-Architektur
- CISC (Mischung von Akkumulator- und Load-Store-Architektur)
- Operationen greifen auf Register und/oder Speicher zu
- Befehlsformat variabler Länge
- mächtige Befehle
- ![image_260.png](image_260.png)
- stark unterschiedliche Zeiten für Instruktionsausführung
- ![image_261.png](image_261.png)
## Klassifizierung gemäß Busaufbau
### [Vergleich Harvard- / von Neumann Architektur](MU6Rechner.md#vergleich-harvard-von-neumann-architektur)
### Bussysteme
- Systembus = Datenbus, Adressbus, Kontrollbus, Bus zur elektrischen Versorgung der Komponenten
- teilweise zstzl. I/O-Bus
- ![image_262.png](image_262.png)
## Klassifizierung gemäß Befehlssätzen
### Orthogonale Befehlssätze
> Wenn Opcode, Adressierungsart und Datentyp beliebig kombiniert werden können
| **Vorteile** | **Nachteile** |
|---------------------------------------------------|--------------------------------|
| Vereinfacht Nutzung der verfügbaren Instruktionen | Sehr umfangreiche Befehlssätze |
### CISC Kriterien
- Befehle unterschiedlicher Länge von 1-17 Byte
- Speichereffizienz
- komplexe Befehlskodierung
- Komplexer Befehlssatz
- Anpassung an Compiler
- Hochsprachenkonstrukte im Assembler
- Erleichterung der Assemblerprogrammierung
- Mächtige Befehle
- kurze Programme
### RISC Prinzipien
- Grundlegendes Design-Prinzip
- Einfachheit
- Befehle gleicher Länge (meist 32 Bit)
- Abarbeiten mit gleicher Taktzahl
- erlaubt Befehlspipelines
- Eingeschränkter Befehlssatz (32-128 Befehle)
- Explizite Lade/Speicher-Befehle (Load-Store-Architektur)
- [3-Adress-Befehle](#3-adress-befehle)
- Delayed Branches
- Pipeline enthält Befehl, dass Pipeline gelöscht wird
- währenddessen kann noch eine Instruktion ausgeführt werden (_kein Jump_)
## Klassifizierung gemäß Speicherorganisation
### Little/Big Endian
![image_269.png](image_269.png)
### 4-Adress-Befehle
![image_263.png](image_263.png)
- Allgemeinste Form für Befehlsformat
- next_i = Adresse des nächsten Befehls
- schwierig zu programmieren
- wird für Microcode verwendet (CISC Mikroprogramme)
### 3-Adress-Befehle
![image_264.png](image_264.png)
- Standard bei RISC Prozessoren (_bspw. ARM 32 Bit_)
- 3 Adressen benötigen Platz
- Format ist erst ab 32-Bit-Befehlssatz sinnvoll
- nächste Befehlsadresse implizit
- Sprungbefehle können implizites Verhalten ändern
### 2-Adress-Befehle
![image_265.png](image_265.png)
- Standardformat für 8 und 16-Bit-Mikroprozessoren
- Format für Intel Prozessoren
- RISC-Prozessoren mit komprimierten Befehlssatz nutzen ebenfalls das Format
- _bspw. ARM Thumb, MIPS_
### 1-Adress-Befehle
![image_266.png](image_266.png)
- Zielregister ist implizit und wird ACC genannt
- wird im [MU0-Design](MU0Rechner.md) benutzt
- Hohe Befehlsdichte
- geringe Flexibilität
### 0-Adress-Befehle
![image_267.png](image_267.png)
- Beide Operanden und das Ziel sind implizit
- Befehlssatz nur für Stackarchitektur möglich
- weitere Befehle mit Operanden zum Speichern / Laden nötig
- _verwendet in [Java Virtual Machine](12_Virtualisierung.md#anwendungsvirtualisierung)_
## Einordnung Prozessoren
![image_268.png](image_268.png)

View File

@ -0,0 +1,178 @@
# MU0-Rechner
## Historie
- **SSEM** _Small Scale Experimental Machine_ erste erfolgreiche Implementierung des Von-Neumann-Rechners
- 1948 erstmals Programm aus dem Speicher ausgeführt
## Elemente
![image_22.png](image_22.png)
- **[Steuerwerk](MU0Rechner.md#steuerwerk)**
- _Control_ - Takt, Steuerlogik
- _IR - Instruction Register_ - speichert den aktuellen Befehlscode
- _PC - Programm Counter_ - speichert die aktuelle Programmadresse
- **Rechenwerk**
- _[ALU](MU0Rechner.md#alu) - Arithmetic Logic Unit_ - kann rechnen
- _ACC - Akkumulator_ - Ergebnis Register für Rechnungen
- **[Speicherwerk](MU0Rechner.md#speicher)**
- _Memory_ - speichert Programme und Daten
- **Bus** - verbindet alle Elemente
### Steuerwerk
- Steuert Elemente mithilfe von Steuersignalen
- Besteht aus
- Ablaufsteuerung / Steuerlogik
- Dekodierer
- Befehlsregister IR
- Befehls-Zähler PC
- **Endlicher Automat, der gemäß der Steuerlogik Steuersignale schaltet**
- führt für jeden Befehl ein Mikroprogramm aus Mikroschritten aus
### Register
![image_23.png](image_23.png)
- Zwischenspeicher
- Register-Größe: 1 Wort (16 Bit)
- Arbeitsmodus Lesen / Schreiben
- _output enable_ liegt an → Daten ausgeben (schreiben)
- _input enable_ liegt an → Daten einlesen
- Ausgeben und Lesen erfolgt jeweils beim Flankenwechsel
- Ausgeben erfolgt einen halben Takt früher als das Lesen, sodass ein Register in einem Zyklus schreiben und lesen kann
- ![image_24.png](image_24.png)
### Speicher
- Stelle im Speicher wird über eine Adresse angesprochen
- Adresse wird vom Adressbus gelesen
- Daten werden vom Datenbus gelesen bzw. geschrieben
- ![image_25.png](image_25.png)
### Datenpfade
- je nach Steuerungscode lesen / schreiben
- geschriebene Daten liegen an Datenpfad an
- immer nur 1 Element schreiben
- ![image_26.png](image_26.png)
### ALU
- über Steuercode wird Funktion ausgewählt
- Eingang A, B führt aus
- mögliche Funktionen:
- A+Β
- A-B
- A*Β
- Konjunktion (logisches UND, bitweise)
- Disjunktion (logisches ODER, bitweise)
- Vergleich von A und B (bitweise)
- ...
## Beispiel für einen Befehlsablauf
![image_27.png](image_27.png)
## Der Rechenzyklus
### Fetch
![image_28.png](image_28.png)
1. Wert des Programmcounters auf den Adressbus legen
2. Programmcode aus dem Speicher in das Instructionregister lesen
3. ALU erhöht gleichzeitig Wert des PC und speichert diesen wieder zurück
### Decode/Execute/Write für Rechenoperationen
![image_29.png](image_29.png)
1. Adresse des Operanden aus dem Befehl dekodieren (1)
2. Wert des angesprochenen Speicherworts an einen Eingang des ALU schalten (2)
3. zweiter Eingang der ALU erhält seine Information vom Akkumulator (2)
4. Rechenoperation wird aus dem Befehl dekodiert und and der ALU über Steuercode gewählt (1)
5. Ergebnis der Rechnung wird wieder im Akkumulator gespeichert (3)
## Taktsynchronität
- Register sind Zwischenspeicher und arbeiten getaktet
- Daten liegen taktsynchron am Bus an
- ALU und Speicher sind nicht taktsynchron
- folgen Steuercodes und dem Inhalt auf dem Bus
## Umsetzung MU0-Struktur in Hardware
- Architektur muss in Gattern und getaktet umsetzbar sein
- Prinzip des minimalen Hardwareaufwands
- Festlegung der Wortbreite: 16 Bit
- [Datenpfad-Modell](MU0Rechner.md#datenpfad-modell)
- Steuerung der Elemente durch Steuercodes
- Befehle (Instruction Set)
- Kodierung der Befehle
- Steuerlogik
### Datenpfad-Modell
![image_30.png](image_30.png)
- bisheriges Bild lässt sich nicht 1:1 umsetzen
- ALU hat nur zwei Eingänge
- Getrennte Datenpfade für jeden ALU-Eingang
- Kontrolle der PFade für Daten und Adressen durch [Multiplexer](MU0Rechner.md#multiplexer)
#### Multiplexer
![image_31.png](image_31.png)
- Schalter, der durch Anlegen eines Steuersignals das ausgewählte Eingangssignal auf den Ausgang legt
#### Befehlsgruppen
- Multiplexer B steht auf 1 bei allen _Datenverarbeitungs-Befehlen_ und auf 0 bei allen _Sprung-Befehlen_
- Multiplexer A wird nur für _Fetchzyklus_ auf 0 gestellt
- ansonsten wird S (unterer Teil von IR) immer als Adresse interpretiert
- Bei _Sprung-Befehlen erfolgt kein Datenzugriff, S (IR) wird direkt nach PC verschoben
## Kennwerte
- Wortbreite des Prozessors: 16 Bit
- Registergröße
- Busbreite
- Eingänge/Ausgänge ALU
- Instruktionen immer 2 Takte lang
- Fetch + Instruction (= Execute): 2 Takte
- Schreiben + Lesen + Schreiben + Lesen: 4 Taktflanken
## Elemente und Steuercodes
![image_32.png](image_32.png)
## Speicher des MU0
- Steuersignale des Datenbus:
- MemRQ (Memory Request)
- Speicherbaustein wird angesprochen
- RnW(Read / not Write)
- gibt an, ob (von oder in) den Speicher geschrieben wird
- _Lesen bei High, Schreiben bei Low_
## Instruction Set des MU0-Rechners (Befehlssatz)
![image_33.png](image_33.png)
- Prozessor kennt keine Befehle
- zum **Laden und Speichern** von Werten
- zur **Berechnung**
- zur **Ablaufkontrolle**
- Die Instruktionen setzen sich zusammen aus
- einem 4 Bit Operation Code
- einer 12 Bit Adresse
→ 16 Befehle möglich
## MU0-Steuerlogik (_Kontroll-Logik_)
Opcode: 4Bits, Adresse: 12Bits
![image_34.png](image_34.png)
### Fetchen
![image_35.png](image_35.png)
### ADD S
![image_36.png](image_36.png)
## Ein erstes MU0-Programm
![image_37.png](image_37.png)
## Fazit
- Elemente der von-Neumann-Architektur
- Steuerwerk, Rechenwerk, Speicherwerk, I/O
- Speicherprogrammiert
- Programme (& Daten) liegen im Speicher
- Architektur muss in Gattern umsetzbar sein
- Datenpfad & Steuertabelle
- Von-Neumann-Zyklus: Fetch-Decode-Execute-Write
- Steuerlogik wird über Opcodes (Befehle) abgefragt und generiert Steuercodes
- MU0 ist ein Modellrechner zum Lernen
- 16-Bit Wortbreite, binär
- Register: PC, IR, ACC
- Befehlssatz (Instruction Set)
- 4-Bit OpCode erlaubt 16 Befehle, 8 sind implementiert
- Takt
- Immer 2 Zyklen pro Mikroprogramm

View File

@ -0,0 +1,311 @@
# MU1-Rechner
## Was kann er mehr:
- Indirekte Adressierung
- Schleifen
- Unterprogramme (Strukturen)
- Optimieren der Datenzugriffe (schneller)
## ALU
### Verbesserungen
- Funktionen der ALU
- **A+B** ist der Ausgang des Addierers
- **A-B** wird gebildet als **A+nichtB+1**
- **B** wird implementiert, indem A fest auf 0 gesetzt wird
- **A+1** wird implementiert, indem Eingang B fest auf 0 und Carry-Eingang auf 1 gesetzt wird
![image_54.png](image_54.png)
### Grundfunktionen MU1-ALU
_Im Praktikum wird nur erwartet, dass Funktion bekannt ist, nicht bspw FA, FIA, etc._
- FA: Funktion (0, A) (also eig. F0A)
- FB: Funktion (0, B)
- FIA: Funktion (Inverter, A)
- FIB: Funktion (Inverter, B)
- FC: Funktion (F1, Carry-Flag)
- F1: Funktion (0/1)
- FS: Funktionsergebnis Statusregister
- C: Funktionsergebnis C
![image_56.png](image_56.png)
![image_55.png](image_55.png)
## Der MU1-Datenpfad
- Das erweiterte Modell besitzt
- Stackpointer SP
- Register Din und Dout
- Laufzeiten sind kürzer pro Takt
- Takt kann erhöht werden
- Durch Din und Dout braucht es mehr Taktzyklen, diese sind aber schneller durchlaufen
![image_57.png](image_57.png)
## Der Reset
- Jeder Prozessor hat einen Reset-Eingang
- ist negiert angelegt → 0 macht [reset](MU1Rechner.md#reset)
- [Program Counter](MU0Rechner.md#steuerwerk) wird auf 0 gestellt, [Microprogram-Counter step](MU1Rechner.md#micro-program-counter-step) ebenfalls
- ALU wird auf Funktion NULL gesetzt
- Beim Einschalten wird Reset-Signal verzögert gesetzt
- Prozessor braucht Zeit um Startzustand herzustellen
## Micro-Program-Counter Step
- Step ist ein Speicher in der Steuereinheit (_Timing/Control Unit_)
- meiste Befehle benötigen mehrere Takte
- Micro-Program-Counter Step gibt Steuerlogik Informationen
- welche Aktionen sind auszuführen
- Step = Eingangsinformation für jeden Schritt
- Steuerungstabelle weiß welcher step welcher Schritt ist
## Befehlsablauf MU1
![image_58.png](image_58.png)
- Step == Null
- **Fetch** (lesen des Befehls in das Instruction Register)
- letzter Schritt: Step = Null
- Step wird meistens um 1 erhöht
- falls nicht → Schleife
### Fetch-Zyklus
- findet in einem Takt statt
- 1. Taktflanke
- Program Counter wird auf Adressbus und auf ALU[A] geschaltet
- An der ALU ist Befehl=A+1, S=0
- 2. Taktflanke
- Speicher liest nächste Instruktion und speichert in IR
- PC wird über ALU um 1 erhöht
![image_59.png](image_59.png)
![image_80.png](image_80.png)
### Befehl LDA (Laden des AKK aus Speicher)
- Zwei Takte
- ![image_60.png](image_60.png)
- ![image_81.png](image_81.png)
### Zustandsbeschreibung des Ladebefehls
![image_61.png](image_61.png)
- Nach Fetch entscheidet Opcode im IR und Schrittnummer, welchen Zustand der Automat als nächstes annimmt
- Step ist PC im Microcode und beschreibt Abfolge der Befehle im Microcode
- Zu jedem Schritt gehört eindeutige Funktion
- Lässt sich in Timing-Control-Logik umsetzen
## Adressierung
### Direkte Adressierung (STO/LDA)
![image_62.png](image_62.png)
- Befehl erhält direkt die Speicheradresse
- Adresse kann zur Laufzeit nicht mehr verändert werden
### Indirekte Adressierung (STR/LDR)
![image_63.png](image_63.png)
- Adresse steht an Speicherstelle
- effektive Adresse kann noch berechnet werden
- Schleifen können programmiert werden
### Adressierungsarten
#### Unmittelbare Adressierung (_immediate_)
- Befehl erhält Konstante
- bspw.: _ADD #1_
#### Direkte Adressierung (_direct, absolute_)
- Befehlt enthält Adresse im Speicher, an der sich Operand befindet
- bspw.: _LDA S_ (_S gibt Adresse im Speicher an_)
#### Indirekte Adressierung (_indirect_)
- Befehl enthält Adresse, an der dich effektive Adresse mit Inhalt befindet
- bspw.: _LDR S_ (_S gibt indirekte Adresse an_)
## Der Stack
- stellt dynamischen Zwischenspeicher dar
- Grundoperationen: [Push](MU1Rechner.md#stack-push), [Pop](MU1Rechner.md#stack-pop)
- Meiste Speicherlayouts (_Konventionen_) sehen vor:
- wächst von oben nach unten
- wächst von großen zu kleinen Adressen
### Stack - PUSH
![image_65.png](image_65.png)
- erniedrigt Stackpointer
- schiebt einen Wert in Speicherwort, auf das der Stackpointer zeigt
### Stack - POP
![image_66.png](image_66.png)
- liest ein Speicherwort von Adresse auf den der Stackpointer zeigt
- erhöht den Stackpointer
### Der Stack im Speicher
![image_64.png](image_64.png)
- Stackpointer wird auf Adresse am Ende des Speicherbereichs gesetzt
- Programme werden im unteren Speicherbereich platziert
- Programm-Counter auf Adresse 0
- Programmbereich schließt sich nach oben an Datenbereich an
- Zwischen Daten und Stack findet man Heap
### Zugriffe auf den Speicher
![image_67.png](image_67.png)
## Unterprogramme
![image_68.png](image_68.png)
- wichtiges Strukturierungsmittel für Programmierung
- werden mit Sprungbefehl (_call, bl_) angesprungen
- Nach Verlassen des UP wird ursprüngliches Programm wieder fortgesetzt
- Rücksprung erfolgt indem gespeicherte Adresse wieder in PC übertragen wird
### Unterprogramm Aufrufe
#### Call
![image_69.png](image_69.png)
- nächster nach der Rückkehr auszuführende Befehl wird auf den Stack gespeichert
- Sprungadresse wird aus IR in PC geladen
#### Return
![image_70.png](image_70.png)
- Rücksprungadresse von Stack in PC geschrieben
- fetch-Zyklus lädt neue Instruktion
## MU1-Befehlssatz
![image_71.png](image_71.png)
## Micro-Codes
**X = Y**
- Inhalt des Registers Y wird nach X verschoben
**X = [Y]**
- Inhalt von Adresse in Y wird nach X verschoben
**X = Y op Z**
- Inhalt von Y (A-Bus der ALU) wird mit Z (B-Bus der ALU) verrechnet und nach X transportiert
**[X] = Y**
- In Adresse in X wird Inhalt von Y geschrieben
**ACC = Din**
- ACC & Din sind Registernamen
- Inhalt von Din wird nach ACC transportiert
- in Din muss oe gesetzt sein, in ACC muss ie gesetzt sein
- Transport über ALU
- [ALU Funktion](MU1Rechner.md#grundfunktionen-mu1-alu) muss B sein
- Da Speicher nicht angesprochen wird (keine [ ])
- [MEMeq=0](MU0Rechner.md#speicher-des-mu0) und [RnW beliebig (laut Rapp lieber 1)](MU0Rechner.md#speicher-des-mu0)
**Din = [SP]**
- Inhalt von SP ist Adressinformation
- Adressmultiplexer muss auf 0 stehen
- Da Speicher angesprochen wird
- MEMrq = 1, RnW = 1
- Da ALU nicht benutzt wird
- ALU-Funktion kann beliebig gesetzt werden
**PC = PC + 1**
- ALU-Funktion muss [A+1](MU1Rechner.md#grundfunktionen-mu1-alu) sein
- PC wird auf A-Bus gelegt
- in der zweiten Hälfte des Takts wird Ergebnis in PC geschrieben
- oe und ie von PC müssen 1 sein
**Din = [SP], SP = SP+1**
- Beide Operationen können in einem Takt durchgeführt werden
- Adressierung in der ersten Takthälfte
- Zurückschreiben in der zweiten Takthälfte
## Regeln für MU1
**[X] = Dout**
- wird in den Speicher geschrieben, muss rechte Seite [Dout](MU1Rechner.md#der-mu1-datenpfad) sein
- [MEMrq = 1, RnW = 0](MU0Rechner.md#speicher-des-mu0)
- zu schreibender Wert muss VORHER nach Dout gebracht werden
**X = [Y]**
- wird vom Speicher gelesen
- linke Seite muss IR oder Din sein
- [MEMrq = 1, RnW = 1](MU0Rechner.md#speicher-des-mu0)
**keine Adresse**
- wird keine Adresse verwendet
- [MEMrq = 0, RnW = 1](MU0Rechner.md#speicher-des-mu0)
- **Nur ein Register darf jeweils auf einen Bus schreiben (A- oder B-Bus), aber alle dürfen lesen**
## Die Addition ADD S
- IR wird zur Adressierung verwendet und der Wert nach Din gebracht
- **Din = [IR]**
- Inhalt des AKK wird auf A-Bus gelegt, Inhalt von Din auf B-Bus
- [ALU-Funktion](MU1Rechner.md#grundfunktionen-mu1-alu) ist **A+B, S: ACC = ACC + DIN**
![image_72.png](image_72.png)
## Die Operation PUSH
**Akkumulator wird auf den Stack geschoben**
- Besteht aus 3 Schritten
1. **SP = SP-1**
- ![image_73.png](image_73.png)
2. **Dout = ACC**
- ![image_74.png](image_74.png)
3. **[SP] = Dout**
- ![image_75.png](image_75.png)
- [Micro-Program-Counter Step](MU1Rechner.md#micro-program-counter-step) wird auf 0 gesetzt
- Fetch-Zyklus schließt sich an
## MU1-Zustandsautomat für LDA, ADD, PUSH
![image_76.png](image_76.png)
- Nach dem Holen des Opcodes im Fetch-Zyklus
- Zustand des OpCode wird angesprungen
- Step-Variable (PC im Micro-Code) wird in Schleife durchlaufen
- endet bei 0 im Fetch-Zyklus
## Bedingte Sprünge
- Bedingter Sprung **JGE** (_Jump on greater or equal_)
- in Abhängigkeit des Negative-Flags im Statusregisters (~15 Bit des ACC, ACC >=0 oder ACC <0) wird ein unterschiedlicher Zustand angesprungen
- ? N = 0 (ACC >= 0)
- PC = IR
- ? N = 1 (ACC < 0)
- keine Operation wird ausgeführt (NOP)
- Bedingter Sprung **JNE** (_Jump on not equal)
- strukturell gleich, Zusatzbedingung:
- Accumulator = Null (Zero-Flag = 1)
### MU1-Steuerlogik für bedingte Sprünge
- Beide Befehle weisen 2 Zustände auf
- unterscheiden sich durch Statusbits des Akkumulators
- Beide Zustände haben Schrittnummer 1 und Folgeschritt 0
- Funktion **NOP** (**N**o **Op**eration) ist gekennzeichnet
- kein Registerinhalt wird verändert
- Alle Register haben oe und ie auf 0
- Speicher wird nicht angesprochen
- MEMrq = 0
- ![image_77.png](image_77.png)
## Der Stop-Befehl
- hat als Folgezustand _stop_
- kein Fetch-Zyklus mehr
- Zustandsmaschine wird in der Stellung angehalten
- ![image_78.png](image_78.png)
## Reset
- Zustandsmaschine geht in Zustand _reset_
- PC = 0
- Step = 0
- Beendigung des Reset-Signals mit dem fetch fortgefahren und Befehl von Adresse 0 wiederholt
- ![image_79.png](image_79.png)
## Zusammenfassung
- Funktionen ALU
- Neue Register Stackpointer, Din, Dout
- Micro-Programm-Counter Step
- Fetch-Zyklus
- Micro Programm + Micro Codes + Zustandsautomaten für LDA, ADD, Push, JGE, Stop, Reset
- Direkt und indirekte Adressierung
- Stack, Unterprogramme
- Beschreibung der Microcode-Funktion durch einfache Sprache
- Zentrales Register: ACC Akkumulator-Architektur
## Probleme des MU1-Designs
- **Speichergröße**
- begrenzt auf 4096 Worte (12Bit) bzw. 65k Worte (16Bit)
- **Anzahl Befehle**
- Begrenzung auf 4 Bit breiten Opcode
- **Absolute Adressierung**
- **Adressberechnungen**
- Müssen in einem Register zwischengespeichert werden
- **Nur ein Datenregister**
- **Berechnung Programmcounter**
- Muss jedes Mal durch ALU erhöht werden verlangsamt Prozessor
## [Weiterentwicklung MU2](MU2-3Rechner.md)

View File

@ -0,0 +1,67 @@
# MU2/3-Rechner
## MU2 Rechner
## Adressraum vergrößern
### Wortbreite vergrößern
- 16 Bit → 32 Bit
- Register, Bus, ALU
### Adressberechnung mit Offset
- Adresse = Register(bereits vorhandene Adresse) + Offset
- Offset kann mit weniger Bits angegeben werden
- Adresse hat volle Breite
**Wird benötigt für:**
- **Relative Adressierung** für Unterprogramme / Sprünge
- **Indizierte Adressierung** für Speicherzugriffe
- Wie indirektes Laden und Speichern mit Offset
- Laden von **PC-relativen Konstanten**
- Prozessoren mit fester Befehlsbreite
- Nur kleine Konstanten können im Code dekodiert werden
- Falls Konstanten in der Nähe des augenblicklichen Programms (_bspw. hinter Returnanweisung eines Unterprogramms_)
- können geladen werden
### Relative Adressierung
- ![image_128.png](image_128.png)
- Code wird im Speicher verschiebbar
#### Labels
- Umsetzung von PC-relativen Sprüngen mit Labels
- ![image_129.png](image_129.png)
### Indizierte Adressierung
#### Beispiel Stack
![image_130.png](image_130.png)
- In Unterprogrammen wird dyn. Speicher reserviert, indem der Stackpointer dekrementiert wird
- Zugriff auf Speicher über Stack + Offset(in Befehl)
- PUSH & POP nicht ausreichend
- bei mehreren Variablen auf dem Stack jeweils beim Lesen der Stack geräumt werden müsste
### Adressberechnung in der ALU
- Adresse als Ergebnis der ALU ohne Speicherung in ACC
- Keine absolute Adressierung (aus IR)
- Nur ALU schreibt auf Adressbus (ohne Multiplexer)
- 32 bit
#### Maximale Laufzeit:
![image_131.png](image_131.png)
- **Gesamtlaufzeit ist zu lang!**
- in einem Takt möglich
- falls Taktfrequenz niedrig genug
## MU3: Einführung des Adressregisters
![image_132.png](image_132.png)
- Ein Takt mehr um Daten aus dem Speicher zu holen
- Taktfrequenz kann höher sein
- Laufzeit pro Teilstück kürzer
- **Nachteil:**
- Nutzen des PC und Inkrementieren geht nicht mehr parallel
- in Aout muss vor Fetch eine Kopie des aktuellen PC stehen
- _(Fetch beginnt bei Aout!)_
### Beispiel relative Sprünge
![image_133.png](image_133.png)
## Problem im Fetch-Zyklus
**Datentransferbefehle ändern Aout**
![image_134.png](image_134.png)

View File

@ -0,0 +1,130 @@
# MU4/5-Rechner
## Registeranzahl erhöhen
### Registerarchitektur
- Gesamtzahl der Register ist normalerweise eine Zweierpotenz
- 8 (ARM-Thumb), 16 (ARM), 32 (Power PC, MIPS) und mehr Register
→ Ergebnisse von Registern können in einem von n Registern gespeichert werden
- Manchmal werden Spezialregister (_PC, SP, LR_) wie andere Register adressiert
- Vorteil: Werte können in arithmetischen Operationen und zur Adressierung benutzt werden
- _ARM: PC in R15, LR in R14, SP in R13_
**Adressierung der Quell- / Zielregister muss im Befehl enthalten sein**
- Bei 16 Registern ist 4Bit (=n) Adressinformation für QR und ZR nötig
- 2-Adress-Befehle (_bspw. add R0, R1 ; R0 += R1_)
- brauchen 2n Bits zur Dekodierung
- 3 Adress-Befehle (_bspw. add R0, R1, R2 ; R0 = R1+R2_)
- brauchen 3n Bits zur Dekodierung
- Prozessoren mit 16 Bit
- 2-Adress-Befehle, wenig Register
- Prozessoren mit 32 Bit
- 3-Adress-Befehle, viele Register
## Konsequenzen aus der Registerarchitektur
- Gut
- Register erlauben schnellere Speicherung von Werten
- arithmetische Befehle lassen sich in einem Takt ausführen
- Register erlauben indirekten Zugriff auf Variablen
- Inhalt eines Registers wird als Adresse genutzt
- Registerbreite sollte groß genug für jede Adresse sein
- Schlecht
- Direkter Zugriff funktioniert bei einem Befehlssatz mit gleicher Breite aller Befehle nicht mehr
- Laden von Konstanten (Immediate Werte) in ein Register ist schwierig
- nur kleine Immediate Werte haben Platz im Befehlscode
## Link-Register für Unterprogrammaufrufe
- Speichert Rücksprungadresse bei Ausführung eines Unterprogramms
- (vorher: Push auf den Stack)
- Am Ende des UP wird die Adresse wieder in den PC geschoben
- (vorher: Pop vom Stack)
- Erlaubt Unterprogrammaufrufe ohne Speicherung auf Stack
## MU4 mit Registersatz (Übergang von Akkumulator- zur Registerarchitektur)
![image_135.png](image_135.png)
- Einfachste Operation (_add r1, r2, r3_) kann nicht erzeugt werden
- Registerbank hat nur Zugriff auf A-Bus
**Prozessor funktioniert so noch nicht!**
_Registerbank braucht Zugriff auf A- und B-Bus_
## MU5: Verbesserung des internen Bussystems und Shifter
![image_136.png](image_136.png)
- meiste Befehle lassen sich realisieren
- Jedes Register hat Ausgang auf A- und B-Bus
- Operanden, die über B-Bus in ALU kommen, können vorher noch geschoben werden
- Auf B-Bus können kleine Immediate-Werte aus IR in Berechnungen verwendet werden
- Es werden noch zu viele Takte pro Operation benötigt
- bisher konnten Registerinhalte auf A-Bus gelegt werden, Immediate auf B-Bus
- nicht optimal, da arithmetische Operationen zwei Registeroperanden haben
- Verbesserung, wenn Registerinhalte auf A-Bus und B-Bus gelegt werden können
### Shifter
- erlaubt es Operanden des B-Bus vor der Verarbeitung nochmal zu schieben
- Wichtig für Adressberechnungen
- häufig ein Wortoffset in eine Adresse auf Byte-Basis umgewandelt
## MU5: Verbesserte ALU
![image_137.png](image_137.png)
- Einsatz von Modifikatoren
- Kann Eingang durchschalten
- Kann alle Bits auf 0 / 1 setzen
- Einsatz eines Shifters
- Kann Wert um Shiftweite nach links / rechts schieben
- Kann Rotation durchführen
- Weitere Funktionen der ALU
- Neben **A+B, A-B, A+B+1**
- **A AND B**
- **A OR B**
- **NOT A**
- **NOT B**
- **A XOR B**
## MU5 Fetch-Zyklus
![image_138.png](image_138.png)
- in Aout muss Kopie von PC stehen
- vorheriger Befehl muss sicherstellen, dass das gegeben ist
- Insbesondere Datentransfer-Befehle
## Arithmetische Operationen
![image_139.png](image_139.png)
- brauchen ein Taktzyklus + Fetch
## Datentransfer
![image_140.png](image_140.png)
## Steuermatrix des MU5
![image_141.png](image_141.png)
![image_142.png](image_142.png)
## Vergleich MU5 - ARM-Design
- Datenverarbeitungsbefehle können wie bei ARM in einem Takt durchgeführt werden
- Datentransferbefehle
- MU5: 3 Takte
- ARM: 2 Takte
- Dout-Register gibt Informationen direkt an Speicher
- Din braucht auch keinen Takt Verzögerung
- ARM-Prozessor
- Kann Daten über Din direkt in Registerbank zu schreiben
- sonst wären einige Adressierungsarten nicht möglich
## MU5a
### Verbesserte Adressberechnung und Umstellung der Speicheradressierung
![image_143.png](image_143.png)
#### Optimierung der Speicheradressierung
- 32 Bit → Register, Bus, ALU
- Speicher bisher wortweise
- verbraucht für kleine Datenwerte viel Speicher
- Umstellung auf byteweise Adressierung erlaubt Einführung neuer Befehle für Adressierung von Halbwörtern
- zusätzlicher Incrementer für Register mit Speicheradressen
- effiziente Inkrementierung um 2 oder 4
![image_144.png](image_144.png)
#### Speicheradressierung
![image_145.png](image_145.png)
![image_146.png](image_146.png)
> AB 01 CD 23 steht im Speicher als 23 CD 01 AB

View File

@ -0,0 +1,30 @@
# MU6-Rechner
## Harvard-Architektur
- Trennung von Daten und Befehlsbus
- In einem Takt können Daten geholt/geschrieben und ein Befehl geholt werden
- Durchsatz wird deutlich erhöht
- Adressregister erhält einen Addierer, um Blocktransfers von Daten zu ermöglichen
- Zurückschreiben der letzten Adresse in ein Register erfordert Zugriff auf C-Bus
## Vergleich Harvard- / [Von-Neumann-Architektur](Prozessorkonzepte.md#von-neumann-rechner-speicherprogrammierter-rechner)
| Harvard | Von Neumann |
|-----------------------------------------------------------|----------------------------------------|
| je ein Befehls- und Datenbus | Nur ein Bus für Befehle und Daten |
| schnellerer gleichzeitiger Zugriff auf Programm und Daten | Kein Programm Fetch bei Datenzugriffen |
| ![image_149.png](image_149.png) | ![image_150.png](image_150.png) |
## Datenpfad mit Harvard-Architektur
![image_151.png](image_151.png)
- Barrelshift-Einheit der ARM-Prozessoren im B-Bus hier nicht eingezeichnet
- I-MEM = Speicher für Programme / Cache
- D-MEM = Speicher für Daten / Cache
## MU6-Architektur
- Wichtigste Änderung: Trennung von Instruktions- und Datenspeicher
- Da PC immer Instruktionsadresse vorgibt
- PC und Instruktions-Adressregister (IADR) sind identisch
- PC taucht im Registerfile noch auf
- sein Wert kann auf A- / B-Bus gelegt werden
- Werte im Instruktionregister können für [ALU-Operationen](MU4-5Rechner.md#mu5-verbesserte-alu) verwendet werden
- Man könnte Takte sparen
- WENN Dout und Din nicht Register, sondern ein direkter Zugriff möglich

View File

@ -0,0 +1,50 @@
# MU7-Rechner
## Pipeline
- erlaubt den nächsten Befehl zu holen während der letzte noch bearbeitet wird
- für Implementierung notwendig:
- Ergebnisse jeder Pipelinestufe in Zwischenregistern speichern
- Stufen werden unabhängig voneinander
- Stufen können gleichzeitig arbeiten
- Für jede Stufe eigenes Instruktionsregister
- steuert Abarbeitung des jeweiligen Befehls
- Sprungbefehle führen zu äußerem Eingriff in den Ablauf der Pipelinestufen
- kann Ausführung der jeweiligen Operation verhindern
- **Moderne Pipelines:**
- Pipelines mit 5-17 Stufen
- längere Bearbeitung von Floatingpoint-Befehlen → lange Pipelines
## Datenpfad mit 5-Stufen Pipeline
![image_152.png](image_152.png)
## Pipeline 6-stufig
![image_153.png](image_153.png)
- **fetch**: nächsten Befehl aus Speicher holen
- **dec**: Befehl dekodieren (Befehlsart ermitteln)
- **reg**: Operanden aus Registerbank holen
- **ALU**: ALU Berechnung / Speicheradresse berechnen
- **mem**: Zugriff auf Speicher
- **res**: Ergebnis in Registerbank zurückschreiben
## Pipeline-Hazard durch Registerzugriff
read after write Hazard
![image_154.png](image_154.png)
## Nachteil der Pipeline: Sprungbefehle
- Sprungbefehle brauchen 5 Takte zusätzlich um nächste gültige Instruktion auszuführen
- alle Befehle in der Pipeline müssen verworfen werden
- Ausweg: **Forwarding**
- Nach Berechnung der neuen Sprungadresse
- Direkt in IADR Register/PC schreiben
- nur noch 3 Leertakte
- ist in allen modernen Prozessoren vorhanden
## Pipeline-Hazard durch Sprungbefehl
Sprungverhalten einer Pipeline mit Forwarding
![image_155.png](image_155.png)
## Datenpfad mit 5-Stufen Pipeline und Forwarding des PC
![image_156.png](image_156.png)

View File

@ -0,0 +1,33 @@
# Prozessorkonzepte
## Was sollte ein Rechner können
- Rechnen
- **`+` `-` `*` `/`**
- **Datenbewegung** (kopieren)
- **Strukturierte Lösung eines Problems**
- Abfolge von Rechenoperationen
- Verwendung von Daten, indirekte Adressierung, Pointer
- Schleifen, Sprünge
- Unterprogramme (Strukturen)
- **Spezielle Befehle** (z.B. Interrupts zur Anbindung von Peripherie)
- **Performance**
- Optimierung der Datenzugriffe (schneller)
- mehr Daten
- spezielle Algorithmen z.B. Graphik, Audio-Codecs, ...
- **Energieeffizienz**
## Von-Neumann-Rechner (Speicherprogrammierter Rechner)
Veröffentlicht 1945
![image_20.png](image_20.png)
- _Arithmetic Logic Unit_ - Rechenwerk
- _Control Unit_ - Steuerwerk
- _Memory_ - Speicherwerk
- _Input/Output_ - Ein-/Ausgabewerk
## MU0 - MU7
### [MU0 - Rechner: Basiskonzept](MU0Rechner.md)
### [MU1 - Rechner: kompletter Rechner](MU1Rechner.md)
### [MU2/3 - Rechner](MU2-3Rechner.md)
### [MU4/5 - Rechner: Adressberechnung, Register-Architektur, Load-Store](MU4-5Rechner.md)
### [MU6 - Rechner: Harvard-Design](MU6Rechner.md)
### [MU7 - Rechner: Pipelining](MU7Rechner.md)

View File

@ -0,0 +1,104 @@
# ARM
## ARM Prozessoren
### Architektur Revisionen
- Unterschiedliche Features
- bspw. unterschiedliche Multiplikationsbefehle, Adressierungsarten, ...
- jeweils gleiches Befehssatzdesign für jede Revision
- aktuell: v7 / v8
### Profile: Konkrete Prozessor-Implementierungen
- Application Profil ['A']:
- High Performance
- bspw. Mobile, Enterprise
- Real Time Profil ['M']:
- Embedded Anwendungen
- bspw. Automotive, Industriesteuerungen
- Microcontroller Profil ['M']:
- Mikrocontroller für große Bandbreite an Anforderungen
- Anzahl Gatter, Kosten, Realtime, Performance
- Aktuell in 2017:
- v7 (32Bit):
- Cortex A7, Cortex M4, Cortex M0+
- v8 (64Bit):
- Cortex A53, Cortex A57
## Bedeutung des Befehlssatzes (ISA)
- Befehlssatz = Instruction Set Architektur
- ISA Level
- ist das Interface zwischen Soft- und Hardware
- definiert die Sprache, die von Soft- & Hardware verstanden werden muss
- ![image_291.png](image_291.png)
### ARM Instruction Sets
![image_292.png](image_292.png)
- ARM unterstützt derzeit 3 IS
- A64 instruction set
- eingeführt mit ARMv8-A, um 64 Bit zu unterstützen
- A32 instruction set ("ARM")
- 32 Bit Befehlsatz in pre-ARMv8-Architekturen
- T32 instruction set ("Thumb"/"Thumb2")
- komprimierter 16/32 Bit Befehlssatz (gemischt)
- in pre-ARMv8-Architekturen
## Coding Standards UAL und APCS
### Unified Assembler Language (UAL)
- Coding Standard, der von Compilern für ARM (32bit) und Thumb verstanden wird
- Macht Programme möglich, die mit verschiedenen Prozessoren kompatibel sind
### ARM Program Calling Standard (APCS)
- Regelt Aufruf von
- Unterprogrammen
- Verwendung von Registern
- ...
- Ermöglicht Verwendung von Objektbibliotheken, welche von anderen Compilern übersetzt wurden
## Architektonisches Erbe der ARM-Prozessoren
**Verwendete Merkmale**
- RISC
- Grundlegendes Design-Prinzip: Einfachheit
- Load/Store Architektur (Register-Register), von Neumann
- 32Bit oder 64Bit (1 Wort)
- 1Byte = 8Bit
- Byteweise Adressierung des Speichers
- Little-Endian und Big-Endian kompatibel
- Vorteil für Einsatzzweck als Standard CPU in Kommunikationsgeräten
- Standard: Little-Endian
- [3-Adressbefehle](Klassifikation.md#3-adress-befehle) (32Bit) oder Thumb
**Verworfene Merkmale**
- Registerfenster
- wird nur bei SPARC Prozessoren genutzt
- Delayed Branches
- der dem Branch folgende Befehl wird ausgeführt bevor der Sprung durchgeführt wurde
- Behandlung von Interrupts und Exceptions schwieriger
- Ausführung aller Befehle in einem Taktzyklus
- setzt [Harvard](MU6Rechner.md#harvard-architektur) voraus
- Kompensation durch verbesserte Adressierungsmodi
## Ein erstes ARM-Programm (GNU)
![image_293.png](image_293.png)
### Wie wird aus einem Programm Maschinencode?
![image_294.png](image_294.png)
- Codierungsvorgang immer gleich
- kann von Programm (_Assembler_) übernommen werden
- Kann weitere Erleichterungen ermöglichen
- Bezeichner Konstanten, Daten, Adressen
- Reservieren von Speicherbereichen für (Zwischen-)Ergebnisse
- Anlegen und Initialisieren von Daten und Datenstrukturen beim Programmstart hinzufügen
-
## [ARM Toolchain](arm_toolchain.md)
## [ARM Befehle](arm_befehle.md)

View File

@ -0,0 +1,130 @@
# ARM Adressierung
## Datentransfer-Befehle
- Einzelregister-Transfer-Befehle (MOV, MVN, MRS, MSR)
- Einzeltransfer-Load/Store-Befehle
- Blocktransfer-Load/Store-Befehle
## Datentransfer
### Datentransfer zwischen Speicher und Register
ldr r0, [r1]
str r0, [r1]
- R0: Zielregister
- R1: enthält Speicheradresse, von der geladen/gespeichert wird
- Langsamer Transfer zwischen Speicher- und Rechenwerk
### Zwischen Registern
mov r0, r1
- R0: Zielregister
- R1: Quellregister
- Schneller Transfer innerhalb des Rechenwerks
## Speicherorganisation
- Byte-orientierter Speicher
- Speicherstelle: **1 Byte**
- Transfer-Befehle liefern meist 32 Bit
- ![image_423.png](image_423.png)
### Little Endian
![image_424.png](image_424.png)
### Alignment im Speicher
- Ausrichtung der Adressen für Zugriffe an Worten (32Bit = 4 Byte)
- ![image_425.png](image_425.png)
- erlaubt einfachere Speicheranbindung, wenn Wortweise gelesen wird
- Cache Speicherung mindestens nach Worten ausgerichtet
- Wenn man Bytes frei anordnen würde, könnte eine Hälfte im Cache stehen, die andere nicht verfügbar
- **Intel:**
- Jedes Wort kann auf jeder Adresse stehen
- nicht ausgerichtete Wörter brauchen 2 Speicherzugriffe
- wäre langsamer
## Speicheraufteilung / Assembleranweisungen
- **.text**
- Legt Textbereich an
- **.align #Bits**
- nachfolgende Anweisung steht auf Speicherstelle, deren unteren #Bits 0 sind
- **.data**
- Legt Datenbereich an
- **.comm symbol, size**
- Legt Symbol in globale bss-Section für uninitialisierte Daten
- **.word Ausdruck**
- Legt initialisierten Speicherbereich mit Größe 4 Byte an
- **.byte Ausdruck**
- Legt initialisierten Speicherbereich mit Größe 1 Byte an
![image_426.png](image_426.png)
## Befehle LDR und STR
- Zugriff erfolgt indirekt
- Speicherung kann indiziert / mit Offset vorgenommen werden
- zum Zugriff genutzter Zeiger kann vor / nach Zugriff in-/dekrementiert werden
![image_427.png](image_427.png)
## Immediate Adressierung
- ![image_428.png](image_428.png)
- Operand wird direkt im Befehl gespeichert
- Kein weiterer Speicherzugriff erforderlich
## Direkte Adressierung
- ![image_429.png](image_429.png)
- Adresse befindet sich im Opcode
- Kann während der Laufzeit nicht mehr geändert werden
- **Achtung:**
- RISC kann nicht 32Bit im Opcode → nicht möglich
## PC-relative Adressierung
- Zugriff auf Daten mit _ldr register, label_
- Laden der ADresse erfolgt über Konstante
- wird PC-relativ adressiert
- Befehl ldr r0, Label
- Pseudobefehl, wird vom Assembler in passenden Befehl umgesetzt
- Beispielsweise:
- ```
add r0, pc, #8
sub r0, pc, #0xb7
ldr r0, [r0]
ldr r0, [pc, #8]
```
- Speicherinhalt an Stelle Label wird geladen
## Pipelining
- ![image_430.png](image_430.png)
- im PC immer aktuelle Befehlsadresse + 8
## Register-Adressierung
- `mov r0, r1`
- ![image_431.png](image_431.png)
- Wie [direkte Adressierung](#direkte-adressierung). nur mit Speicher- statt Registeradresse
### Register-indirekte Adressierung
- Beispiel: `ldr r0, [r1]`
- ![image_432.png](image_432.png)
- Benutzt Registerwert (**Basisregister**) als Speicheradresse
- zum Laden/Speichern des Wertes an der Adresse
- einer der Operanden aus dem Speicher, andere im Register
- Registeradressierung über Pointer
- Gesamter Speicherbereich kann adressiert werden, ohne dass Adresse in der Instruktion sein muss
### Beispiel Kopieren
![image_433.png](image_433.png)
## Indizierte Adressierung
- Register + Offset Adressierung
- Beispiel: `ldr r0, [r1, #8]`
- ![image_434.png](image_434.png)
- Kommt häufig vor, dass Speicher zugegriffen wird, der einen Offset relativ zur Basisadresse besitzt
- Adressierung über Register plus konst. Offset = **indexed Adressing**
- Arm:
- ![image_435.png](image_435.png)
- ![image_436.png](image_436.png)
## Beispiel Kopieren indiziert
- ![image_437.png](image_437.png)
- ![image_438.png](image_438.png)
-

View File

@ -0,0 +1,404 @@
# ARM Befehle
## ARM 7
- Architektur: ARM v4T, Prozessor ARM7 TDMI
- 1994 rausgekommen
- 12-70 MHz, 0,889 DMIPS/MHz
- [RISC](Klassifikation.md#risc-prinzipien), Load-Store-Architektur
- 3-stufige [Pipeline](MU7Rechner.md#pipeline)
- Instruction Set
- ARM 32 bit oder Thumb
- [3-Adress-Befehle](Klassifikation.md#3-adress-befehle)
- Little Endian als Standard
### ARM-Datenpfad
![image_302.png](image_302.png)
### ARM7-ALU
![image_303.png](image_303.png)
### ARM7-Pipeline für ALU-Befehle
![image_304.png](image_304.png)
- Latenz
- 3 Zyklen
- Durchsatz
- 1 Befehl je Zyklus
#### Multi-cycle Execution
- Execute benötigt einen Takt für simple Instruktionen
- Bei Speicherzugriff mind. 2 Takte
- Adress Berechnung
- Speicherzugriff
- ![image_305.png](image_305.png)
## Load/Store Befehle Hazard in Von-Neumann
![image_306.png](image_306.png)
![image_307.png](image_307.png)
## ARM Registerstruktur
![image_309.png](image_309.png)
## Statusflags
- **N** (Negative)
- Das Ergebnis der ALU ist negativ (Bit 31=1)
- **Z** (Zero)
- Das Ergebnis der ALU ist Null (Bit 0..31 = 0)
- **C** (Carry)
- Bei arithmetischer Operation wird C auf Carry-Out der ALU gesetzt
- Sonst auf Carry-Out des Shifters bzw. ohne Shift Operation bleibt C erhalten
- **V** (Overflow)
- Wenn Zahlensystem geändert wird
- Wenn mit unsigned gerechnet wird ist V ohne Interesse
## Current Program Status Register (CPSR)
- ![image_310.png](image_310.png)
- **T-Bit**
- T = 0
- Prozessor in Arm State
- T = 1
- Prozessor in Thumb State
- **Interrupt Disable Bit**
- I = 1, disables IRQ
- F = 1, disables FIQ
- **Mode Bits**
- Spezifizieren Prozessor Mode
## Übersetzungstabelle Assembler - Binärcode
![image_311.png](image_311.png)
## Thumb Befehlsatz
- zusätzlicher Befehlssatz
- 16 Bit
- Intern werden sie auf 32 Bit erweitert
- Programme verbrauchen nur halben Speicher
- weniger Register stehen zur Verfügung
- Während Programmausführung kann zwischen ARM-32 und Thumb gewechselt werden
- Thumb-2 ist ein gemischter 16/32 Bit Befehlssatz
- Prozessor ARM7TDMI unterstützt sowohl ARM als auch Thumb
## ARM Befehlssatz
- Drei Befehlstypen
- zur Datenverarbeitung (bspw. Addition)
- Ablaufsteuerung (bspw. Verzweigungen)
- Befehle zur Adressierung
- Groß-Kleinschreibung wird ignoriert
### ARM-Befehle: MOV
- MOV ist ein Datentransferbefehl
- Kopiert Daten in ein Register
- Beispiele
- mov r0, r1 @Inhalt von R1 wird nach R0 kopiert
- mov r1, #0 @Zahl 0 wird nach R1 kopiert
- mov pc, lr @PC wird auf LR gesetzt
- Variante:
- mvn r1, r2
- Wendet zusätzlich zu mov ein EOR auf Inhalt von r2 an
### ARM-Befehle: ADD
- Die arithmetischen Befehle der ARM Prozessoren sind 3-Register-Befehle
- Alle Operanden sind 32Bit
- Das Ergebnis ist 32 Bit
- 3 Operanden: 2 als Input, 1 als Ergebnis
- Beispiel
- ADD r0, r0, r3 @R0 = R0 + R3
### ARM-Befehle: SUB
- ARM-Prozessoren implementieren keine Subtraktion
- Addition mit 2er Komplement
- Beispiel
- SUB r0, r0, r3 @R0 = R0 - R3 = R0 + (-R3)
### ARM-Befehle: CMP
- Befehl vergleicht zwei Werte auf Gleichheit und setzt Statusflags entsprechend
- CMP r0, #5 @r0 == r5?
- Dazu wird folgende Berechnung (r0=3) ausgeführt
- CMP r0, #5 @r0-5 = 3-5 ausgeführt
- MOV r1, #5
- SUBS r1, r0, r1
- Folgende Statusflags werden gesetzt
- ![image_312.png](image_312.png)
### ARM-Befehle: -S
- Setzen des Statusregisters bei arithmetischen und logischen Befehlen
- Bedingungsbits des Statusregisters werden nur bei Test-/Compare-Befehlen automatisch gesetzt
- Alle anderen Befehle müssen explizit setzen
- Beispiel
- add r0, r0, r3 @lässt Statusregister unverändert
- subs r0, r0, #1 @schreibt alle Flags NZCV
### ARM-Befehle: - {cond}
- Jeder Befehl kann bedingt ausgeführt werden
- Bedingung (bezogen auf vorher gesetzte Werte des Statusregisters) als Ergänzung an den Befehl angehängt
- Beispiel
- CMP r0, #5
- ADDNE r1, r1, r0
- SUBNE r1, r1, r2
- if (r0 != 5) {r1 = r1+r0-r2}
- NE = not equal
- Bezogen auf die vorherigen Werte des Statusregisters
#### Bedingte Ausführung von Befehlen
![image_313.png](image_313.png)
##### Signed/unsigned
![image_314.png](image_314.png)
##### carry set / higher same
- Beispiel:
- CMP r0, r1 @berechnet R0-R1, also R0 + (-R1) und setzt NZCV
- JCS sprungziel @springt zur Marke "sprungziel", wenn CS erfüllt ist
- Bedeutung: Wenn **unsigned >=** dann C gesetzt
- R0 = 3,R1 = 2 (nur 4-Bit Darstellung)
- R0 = 0011 2k = 1110
- Berechnet: 0011 + 1110 = 3 + (-2) = 0001
- C = 1
- R0 = 2, R1 = 3 (nur 4-Bit Darstellung)
- R0 = 0010 R1 = 0011
- Berechnet: 0010 + 1101 = 2 + (-3) = 1111
- C = 0
##### Bedingte Ausführung LT (Less than)
- Beispiel
- CMP R0, R1 @berechnet R0-R1 und setzt NZCV
- JLT sprungziel @springt zur Marke "sprungziel", wenn CS erfüllt ist
- Bedeutung: wenn **signed <** dann N ungleich V
- Beispiel 1
- R0 = 3, R1 = 4 (nur 8 Bit)
- R0 = 00000011 R1 = 00000100
- Berechnet: 00000011 + 11111100 = 3 + (-4) = 11111111
- N = 1, V = 0
- Beispiel 2
- R0 = -127, R1 = 2
- R 0 = 10000001 R1 = 00000010
- Berechnet: 10000001 + 11111110 = -127 + (-2) = 127 (?)
- N = 0, V = 1
### ARM-Befehle: Der Barrel Shifter
![image_315.png](image_315.png)
#### LSL: Logical Shift Left = Arithmetic Shift Left (ASL)
- ![image_316.png](image_316.png)
- Multiplikation mit einer Zweier-Potenz
- ![image_317.png](image_317.png)
- LSL R0, R1, #5 -> R0 = R1*2^5
#### LSR: Logical Shift Right
- ![image_318.png](image_318.png)
- Division durch eine Zweier-Potenz
- ![image_319.png](image_319.png)
- LSR R0, R1, #5 -> R0 = R1/2^5
#### ASR: Arithmetic Shift Right
- ![image_320.png](image_320.png)
- Division durch eine Zweier-Potenz unter Erhaltung des Vorzeichens
- ![image_321.png](image_321.png)
- ASR #5, positiver Operand
#### ROR: Rotate Right
- ![image_322.png](image_322.png)
- ![image_323.png](image_323.png)
#### RRX: Rotate Right Extended
![image_324.png](image_324.png)
#### Multiplikation mit einer Konstanten
- mit 2^x oder als 2^x +-1 darstellen lassen
- können in einem Zyklus durchgeführt werden
- Beispiel: Mul mit 5
- ADD r0, r1, r1, LSL #2
- Durch Zusammensetzen mehrerer Instruktionen können auch komplexere Multiplikationen durchgeführt werden
- Beispiel: Mul 10
- ADD r0, r1, r1, LSL #2
- LSL r0, r0, #1 @mov r0, r0, LSL#1
- Beispiel Mul mit 119 = 17·7 = (16+1)·(8-1)
- ADD r2, r3, r3, LSL #4 @r2 = r3·17
- RSB r2, r3, r2, LSL #3 @r2 = r2·7
## UAL (Unified Assembler Language)
- gemeinsamer Syntax für ARM32 und Thumb
- gleicher Code für beide Modi
- Falls Befehl nicht umgesetzt werden kann
- Assembler gibt Fehlermeldung aus
- Beispiel 1
- vorher
- Thumb: AND R0, R1
- ARM: AND, R0, R0, R1
- Jetzt: AND **R0, R0, R1**
- Beispiel 2
- vorher
- Thumb: LSL R0, R1, #2
- ARM: MOV R0, R1, LSL #2
- Jetzt: **LSL R0, R1, #2**
## Arithmetische und logische Befehle
![image_325.png](image_325.png)
### Binärcodierung arithmetischer und logischer Befehle
![image_326.png](image_326.png)
![image_327.png](image_327.png)
### Assembler Format
- Arithmetische und logische Befehle haben eins der beiden logischen Formate
- \<op\>{\<cond\>}{S} -> Rd, Rn, #\<32-Bit-Immidiate\>
- \<op>{\<cond\>}{S} -> Rd, Rn, Rm, {\<shift>}
- Rd: Destination
- Rn: Operand 1
- Rm: Operand 2
- Beispiel:
- ADD r0, r1, r2
- ADD r0, r2, #4
- MOV r0, r1
- ADDGTS r0, r1, r2, LSR r3
#### Operand 2 als Konstante (Immidiate)
- Befehlsformat für Datenverarbeitungsbefehle reserviert 12 Bits für Operand 2
- ergäbe einen Wertebereich von max 2^12 = 4096
- oder aufgeteilt in Wertebereiche mit 8 Bits (0-255)
- Diese 8 Bits können (links) rotiert werden
- gerade Anzahl von Positionen (0, 2, 4, ..., 30)
- Ergibt weitaus größere Abdeckung des Zahlenbereichs
- 8 zusammenhängende Bits innerhalb des 32-Bit-Wertebereichs
- ![image_328.png](image_328.png)
- Einige Konstanten müssen dennoch vom Speicher geladen werden
- oder in einem Register konstruieren
- ![image_329.png](image_329.png)
#### Operand 2 als Konstante
- Wertebereich
- | 0-255 | [0-0xff] |
|-----------------------------|--------------------------------------------|
| 256, 260, 264, ..., 1020 | [0x100-0x3fc, step 4, 0x40-0xff ror 30] |
| 1024, 1040, 1056, ..., 4080 | [0x400-0xff0, step 16, 0x40-0xff ror 28] |
| 4096,4160, 4224,..,16320 | [0x1000-0x3fc0, step 64, 0x40-0xff ror 26] |
- Beispiel MOV-Befehl
- MOV r0, #0xFF000000 @MOV r0, #0xFF, 8
- Beispiel MVN: erzeuge das bitweise 1er-Komplement
- MOV r0, #0xFFFFFFFF @umgesetzt zu MVN r0,#0
- Falls benötigte Konstante nicht erzeugt werden kann
- Assembler erzeugt Fehlermeldung
## Multiplikation
![image_330.png](image_330.png)
## Befehle zur Ablaufsteuerung
### Sprungbefehle (Branch)
- dienen dazu den Kontrollfluss von Programmen zu kontrollieren
- in Kombination mit Vergleichsbefehlen
- können alle wichtigen Anweisungen (if, else, while, for, switch) darstellen
- Ziel ist immer eine Marke (Label)
- Assembler erzeugt Sprungadresse
- Beispiel
- ```
CMP R0, #0
BNE Marke 1
...
...
Marke 1: MOV R5, #5
```
- ![image_331.png](image_331.png)
### Sprungbefehle
![image_332.png](image_332.png)
#### Unterprogramme (Branch-with-Link)
- Der Befehl BL führt einen Sprung aus
- speichert die Rücksprungadresse im Link-Register r14(LR)
- Weitere Subroutinen müssen r14(LR) im Speicher sichern
- bspw. auf Stack und bei Rückkehr in r15(PC) wieder herstellen
- Arbeitsregister können ebenfalls gesichert werden
- wenn Unterprogramm diese benötigt
- Übergabe von Parametern nach APCS-Standard
- Beispiel
- ![image_333.png](image_333.png)
#### Sprungbefehle mit Mode-Wechsel (32Bit Thumb)
- **BX Rn Branch and Exchange**
- Als Argument erhält der Befehl eine Registeradresse
- Inhalt wird in PC kopiert
- Falls ungerade → Wechsel in Thumbmode
- Falls gerade → Wechsel in ARM-Mode
- Befehl **BX LR** ist Standardbefehl um Unterprogramme zu verlassen
- Rücksprungadresse steht noch im Linkregister
- **BXL Label - Branch and Link with Exchange**
- Standardbefehl zum Aufruf von Unterprogrammen
- wird in Programmen mit gemischtem 32-Bit/Thumb Code genutzt
- **BLX Rn**
- Führt Modewechsel durch
- Speichert nächste Adresse im Linkregister
#### Unterprogrammaufruf mit Modewechsel
![image_334.png](image_334.png)
### Befehle zur Ablaufsteuerung - Beispiele
- ![image_335.png](image_335.png)
- Befehle MOV PC, Rd, ist nach Einführung des Thumb Befehlssatzes nicht mehr empfohlen
- Lässt direkten Zugriff auf PC nicht zu
- Stattdessen BX, BLX
- Alle Sprungbefehle können bedingt ausgeführt werden
- Offset der Sprungbefehle bis zu 32 MByte
- FÜr größere Sprünge muss Zieladresse erst in ein Register geladen werden
### Assembler-Format der Sprungbefehle
![image_336.png](image_336.png)
## APCS (ARM Procedure Calling Standard)
- Standard definiert wie Funktionen geschrieben werden sollen
- können unabhängig geschrieben, compiliert, assembliert uns später gelinkt werden
- Umfasst auch andere Programmiersprachen wie C
- Definiert sind
- Anforderungen an aufrufende/aufgerufene Funktionen
- Einschränkungen bei der Nutzung von Registern durch Funktionen
- Daten- und Stacklayout und Konventionen
- C/C++ Language Bindings, shared libs, reentrant code, etc.
### Parameterübergabe an Funktionen
- Funktionsaufruf:
- Result = fct(ARG1, ARG2, ARG3, ARG4)
- Parameter 1-4 in Register r0-r3 übergeben
- Rückgabewert von Funktionen steht im Register r0 oder r0/r1
- Verwendung von Registern in der Funktion
- r0-r3 und IP = Scratch Register
- dürfen im Unterprogramm zerstört werden
- Informationen in r4-r10, fp, sp dürfen nicht zerstört werden
- Inhalt von lr wird zur Rückkehr ins aufrufende Programm benötigt
- ![image_337.png](image_337.png)
## [ARM Adressierung](arm_adressierung.md)

View File

@ -0,0 +1,48 @@
# ARM Toolchain
![image_296.png](image_296.png)
## Targets
### Entwicklung auf dem Device
- Native Toolchain
- Benötigt ein OS
### Cross Entwicklung
- Compiler auf dem PC übersetzt für Hardware für die Zielplattform
### Entwicklung im Emulator auf dem PC
- Compiler auf dem PC übersetzt für Hardware, ausgeführt im Simulator
- Wenn Hardware nicht verfügbar oder Entwicklung zeitaufwändig
- Insight, QEmu
### Bare Metal
- Für Mikroprozessor ohe BS
### Betriebssysteme
- Linux
- Embedded Windows
- Realtime OS
## Toolchain für das Praktikum
![image_297.png](image_297.png)
## GNU ARM Assembler
- ![image_298.png](image_298.png)
- rn = Registername
### Assembler-Direktiven
- können Übersetzungsvorgang steuern
- können Speicherbereiche für das Programm reservieren
- ![image_300.png](image_300.png)
- können Datenstrukturen für das Programm anlegen und initialisieren
- ![image_299.png](image_299.png)
### Pseudobefehle
- Befehle, die es in der Maschinensprache nicht gibt, aber häufig gebraucht werden
- Assembler übersetzt diese in eine geeignete Sequenz von "echten" Assemblerbefehlen
- Beispiel:
- ![image_301.png](image_301.png)
-