operating system
WiSe 2023/2024

Table of Contents

git clone git@gitlab.informatik.uni-bremen.de:fdrees/operating-systems.git

1. GitLab Page

2. GitLab Repo

3. UPPAAL

3.1. Erklären Sie das Konzept von „Clocks“ in UPPAL.

  • kann zur Prüfung von Zeitinvarianten verwendet werden
  • es gibt schreibend nur ein Reset auf 0
  • sonst monoton linear steigend

Clocks are global variables that are incremented in each transition. They can be reset to 0 in each transition. They can be compared to constants and other clocks. They can be used to model time.

3.2. Erklären Sie das Konzept von „Channels“ in UPPAAL.

Channels are used to model communication between processes.

3.3. TODO Wie lässt sich eine typische Safety Property in UPPAAL prüfen?

pass

3.4. TODO Unter welchen Voraussetzungen gilt eine Eigenschaft der folgenden Form:

pass

3.5. TODO A[]phi

3.6. TODO A<>phi

3.7. TODO E<>phi

3.8. TODO E[]phi

3.9. TODO phi–>psi

3.10. TODO Wie lässt sich die Negation der Formel (not E <> (P(1).cs and P(2).cs)) ?

3.11. TODO Modellieren sie den Algorithmus von Peterson in UPPAAL.

3.12. TODO Durch welche UppAal Query lässt sich der gegenseitige Ausschluss von Petersons Algorithmus prüfen?

3.13. TODO Wie lässt sich die Deadlock-Freiheit von Petersons Algorithmus prüfen?

3.14. TODO Wie lässt sich die Fairness für beide Prozesse von Petersons Algorithmus prüfen?

Es gibt keinen Pfad auf dem ein Prozess verhungert, obwohl er in die Critical-Section möchte. A[] (P(1).WAIT --> P(1).CS) bei dem --> Operator is es äquivalent das A[] wegzulassen P(1).WAIT --> P(1).CS

4. IDEA Active-Wait-Verfahren

4.1. What are the advantages of an active-wait protocol compared to semaphores?

  • keinen Kontextwechsel zwischen User- und Kernel-Mode

Active-wait protocols are more efficient than semaphores, because they do not require a context switch. They are also easier to implement.

4.2. What are the disadvantages of an active-wait protocol?

Active-wait protocols are not preemptive, so they can lead to starvation. Also, they are not deadlock free, because they do not provide mutual exclusion.

4.3. What is priority inversion (de: "Prioritäten-Inversion")?

  • bei active-wait auf einem singe-core-sytem kann es dazu kommen

Ein hochpriorisierter Prozess will auf eine Critical-Section zugreifen, die aber noch von einem niederpriorisierten Prozess blockiert wird. Nun würde der hochp. Prozess gescheduled und bremst sich damit selber aus, um in die Critical-Section zu kommen.

Priority inversion is a problem that can occur when using semaphores. A high priority process is waiting for a low priority process to release a semaphore.

4.4. How does Peterson's algorithm work?

Peterson's algorithm is an active-wait protocol that provides mutual exclusion. It uses two flags to indicate that a process is interested in entering the critical section. It also uses a turn variable to indicate which process is allowed to enter the critical section.

(mutual exclusion):

  • only one process can be in the critical section at a time
  • if process 0 is in the critical section, then process 1 is not in the critical section
int turn = 0;
int interested[2] = {0, 0};

// Oo enter a ciritical section, call the following function.
// (pid is in range 0..1)
void enterCritical(int pid) {
    // int other = 1 - pid;

    interested[pid] = 1;
    turn = pid;

    while (turn == pid && interested[1 - pid] == 1) {
	// busy wait
    }
}

// To leave a critical section, call the following function.
void leaveCritical(int pid) {
    interested[pid] = 0;
}

4.5. "What happens if you swap the assignments in Peterson's algorithm?

If the assignments are swapped, then the algorithm does not provide mutual exclusion anymore. This is because the turn variable is set before the interested flag is set.

// WRONG: this does not provide mutual exclusion

void enterCritical(int pid) {
    int other = 1 - pid;

    // WRONG: turn is set before interested[pid] is set
    turn = pid;
    interested[pid] = 1;

    while (turn == pid && interested[other] == 1) {
	// busy wait
    }
}

4.6. How does Fischer's protocol work?

Fischer's protocol is an active-wait protocol that provides mutual exclusion. It uses a flag to indicate that a process is interested in entering the critical section. It also uses a turn variable to indicate which process is allowed to enter the critical section.

Can be implemented and used in practice for applications with arbitrary many processes.

Most famous protocol using timers for synchronization.

It works as follows:

  • A process that wants to enter the critical section sets its flag to true.
  • It then waits until the flag of all other processes is false.
  • It then sets its flag to false and enters the critical section.
  • When it leaves the critical section, it sets its flag to false.

4.7. What assumption must be fulfilled for Fischer's protocol?

The processes must be synchronized. This means that they must start at the same time. Also, they must have synchronized clocks.

4.8. How does strict alternation work?

Strict alternation is an active-wait protocol that provides mutual exclusion. It uses a flag to indicate that a process is interested in entering the critical section. It also uses a turn variable to indicate which process is allowed to enter the critical section.

It works as follows:

  • A process that wants to enter the critical section sets its flag to true.
  • It then waits until the flag of the other process is false.
  • It then sets its flag to false and enters the critical section.
  • When it leaves the critical section, it sets its flag to false.

5. Kommunikationsmechanismen

5.1. TODO Wie funktioniert ein Ringpuffer?

5.2. TODO Wie kann festgestellt werden, dass der Ringpuffer leer ist?

5.3. TODO Wie kann festgestellt werden, dass der Ringpuffer voll ist?

5.4. TODO Wie kann der Ringpuffer ohne Modulo-Operation umgesetzt werden?

5.5. TODO Wie implementiert man einen Ringpuffer mit sehr großen Datenelementen x , so dass man nicht ein ganzes Array-Feld der Größe x verschwenden muss?

5.6. TODO Wie funktioniert das Non-Blocking Write Protokoll?

6. Semaphoren

6.1. TODO Welche Systemcalls bietet das System V Paket für Semaphoroperationen?

6.2. TODO Wie kann mit diesen Systemcalls eine up-Operation auf einer Semaphore durchgeführt werden?

6.3. TODO Wie können mit diesen Systemcalls down-Operation auf mehreren Semaphoren mit einem Systemcall Aufruf durchgeführt werden?

6.4. TODO Was passiert in diesem Fall, wenn eine einzelne down-Operation nicht ohne Blockieren ausgeführt werden kann, der Systemcall aber für MEHRERE Semaphoren ein Down anfordert?

6.5. TODO Was passiert wenn das Feld sem\op für eine Semaphor-Operation den Wert 0 enthält?

7. Shared-Memory

7.1. TODO Welche Systemcalls bietet das System V Paket, um Shared-Memory zu nutzen?

8. Netzwerkkommunikation

8.1. TODO Was versteht man unter verbindungsloser/verbindungsorientierter Kommunikation?

8.2. TODO Was versteht man unter Datagramm-orientierter/Stream-orientierter Kommunikation?

8.3. TODO Welche Eigenschaften hat das TCP Protokoll?

8.4. TODO Welche Eigenschaften hat das UDP Protokoll?

8.5. TODO Welche Systemcalls sind nötig, um einen TCP-Client zu realisieren? (inkl. Parameter, und Reihenfolge der Systemcalls)

8.6. TODO Welche Systemcalls sind nötig, um einen TCP-Server zu realisieren? (inkl. Parameter, und Reihenfolge der Systemcalls)

8.7. TODO Was ist der Unterschied zwischen einem iterativen und parallelen Server? Wie werden diese umgesetzt? (Pseudo-Code)

8.8. TODO Welche Systemcalls sind nötig, um ein UDP-Paket zu versenden?

9. Prozesse und Threads

9.1. TODO Worin unterscheiden sich Prozesse und Threads?

9.2. TODO Welche Systemcalls werden zum Erzeugen eines Threads benötigt?

9.3. TODO Wie kann auf die Terminierung eines Threads gewartet werden?

9.4. TODO Wie lässt sich ein Prozess auf einer festen CPU ausführen?

9.5. TODO Erkläre die Aufrufe zur Prozesserzeugung und zum Prozessabbruch, die in der Sledgehammer/DPLL-Aufgabe verwendet wurden

10. Userspace Scheduling

10.1. Welche Vorteile bietet ein Userspace-Scheduler?

Userspace-Scheduling erlaubt es Anwendungsspezifische Scheduling-Entscheidungen zu treffen. Außerdem muss nicht in den Kernel-Mode, für erstellen oder wechseln von User-Threads, gewechselt werden. Dadurch weniger Overhead. Weil das Scheduling im Userspace gemacht wird, ist es unabhängig vom Betriebssystem-Scheduler und somit leichter zu portieren.

10.2. Welche Nachteile hat ein Userspace-Scheduler?

Die einzelnen User-Threads laufen alle im selben Prozess. Der Scheduler vom Kernel betrachtet den Prozess nur als ganzes. Dadurch können die User-Threads nicht echt-parallel laufen (auch auf Multithreaded CPUs) und sie laufen alle auf der selben CPU. Das Scheduling muss im Userspace gemacht werden. Weil das Scheduling im gleichen Prozess gemacht wird kann keine Preemption für aktuell laufende User-Threads gemacht werden. Die User-Threads müssen also kooperativ schedulen und sollten nicht blockieren.

10.3. Skizzieren Sie ein Beispiel, in welchem User-Space Scheduling die Code-Komplexität gegenüber C-Funktionen ohne Multi Threading reduziert.

Eine Anwendung mit mehreren Reitern. Bei dem Wechsel zwischen den Reitern werden die entsprechenden User-Threads gewechselt. Dadurch kann der Zustand (State) der vorher besuchten Reiter leicht behalten und später wieder aufgerufen werden. (TODO: besseres Beispiel?)

10.4. Welche C-Befehle sind nötig, um den Kontextwechsel in einem Userspace-Scheduler zu realisieren?

`getcontext(*ucp)` und `setcontext(*ucp)` wobei hier `*ucp` jeweils ein `user context pointer` vom Typ `ucontextt` ist. Zunächst kann man mit [`getcontext`](https://man7.org/linux/man-pages/man3/getcontext.3.html) den aktuellen Kontext bekommen. Mit `setcontext` kann man einen Kontext wieder herstellen und somit in einen anderen Kontext (User-Thread) innerhalb des selben Prozesses wechseln. Alternativ kann man auch mit [`swapcontext`](https://man7.org/linux/man-pages/man3/swapcontext.3.html) wechseln.

11. Scheduling

11.1. Wie viele Scheduling-Klassen gibt es im Linux-Kernel?

Ein Implementierungsdetail. Zum Beispiel mehrere Policies in einer Klasse. Zum Beispiel Realtime-Klasse und Other-Klasse. Innerhalb dieser Klasse werden Prozesse gleichbehandelt, egal welcher Policy sie angehören und entsprechend geschedult.

11.2. Welche Scheduling-Policies werden vom Linux-Kernel unterstützt?

Der Linux-Kernel hat 6 Scheduling-Policies (in den Klassen OTHER und REALTIME). SCHED\_OTHER, SCHED\_IDLE, SCHED\_BATCH, SCHED\_FIFO, SCHED\_RR und SCHED\_DEADLINE

11.3. Wie werden in der Realtime Scheduling Klasse die Prozesse verwaltet (Datenstrukturen, wie wird O(1)-Scheduling erreicht)?

Prozesse, die nach einer Realtime Scheduling Policy (SCHED\_FIFO, SCHED\_RR) geschedult werden, haben auch eine sched\_priority mit Werten typischerweise in [1..99]. (POSIX.1 verlangt mindestens nur 32 Prioriäten, also [1..32]) Der Scheduler hat eine Liste von Listen. Für jede sched\_priority gibt es eine Liste von lauffähigen Prozessen. Nun muss in der Liste von (sched\_priority) Listen die höchst-priorisierteste nicht-leere Liste gefunden werden. Der Kopf dieser Liste ist der Prozess der nun geschedult wird.

11.4. In einem 1-CPU System mit einem permanent rechenbereiten Prozess der Scheduling-Policy SCHED\FIFO: wie oft bekommen Prozesse der Policy SCHED\OTHER die CPU?

Überhaupt nicht, da SCHED\_FIFO eine Realtime-Policy ist und somit eine höhere (statische) Priorität als SCHED\_OTHER hat. Solange es lauffähige Realtime-Prozesse gibt (hier permanent der Fall), werden diese ausgeführt/geschedult. Prozesse mit der SCHED\_OTHER können nur eine statische Priorität von 0 haben, welche mit der SCHED\_FIFO jedoch in [1..99] (immer > 0).

11.5. In einem System mit einem permanent rechenbereiten Prozess der Scheduling-Policy SCHED\FIFO mit Prio 5: wie oft werden Prozesse der Policy SCHED\RR mit prio 12 geschedult?

Beides sind Realtime-Scheduling-Policies, daher ist hier vorallem die Priorität wichtig und für SCHED\_RR auch sogenanntes "time quantum" (Zeit Menge). Die Prozesse der SCHED\_RR Policy haben eine Priorität von 12 und werden damit vor denen der SCHED\_FIFO mit Priorität 5 geschedult. Bei dem Round-Robin-Scheduling können Prozesse nur eine maximale Zeit (bestimmt durch das "time quantum") aktiv sein, bevor sie preempted werden und wieder ans Ende der Scheduling-Liste gestellt werden. Solange es nun lauffähige Prozesse der SCHED\_RR mit Priorität 12 gibt (höher als 5) werden diese geschedult und entsprechend ihres Zeit-Budgets "rotiert". Die SCHED\_FIFO Prozesse mit Priorität 5 würden währenddessen jedoch nicht geschedult werden.

11.6. Was bedeutet präemptives Scheduling?

Präemptives Scheduling bedeutet, dass die Ausführung eines Prozesses unterbrochen wird, obwohl er noch lauffähig währe. Dies erlaubt es zwischendurch andere Prozesse zu schedulen. Insgesamt sollte dadurch die Interaktivität (responsiveness) des Systems verbessert werden.

11.7. Was bedeutet schwache Fairness?

(Aus den Folien) "A schedule is weakly fair, if and only if every process that is always runnable is scheduled infinitely often. A violation of weak fairness occurs if there exists a permanently runnable process which gets the CPU only a finite number of times (or not at all)." > Ein Prozess der immer lauffähig ist, wird "unendlich" oft wieder geschedult und bekommt entsprechend auch "unendlich" oft die CPU. Also z.B. ein permanent lauffähiger Prozess.

  • while True
  • mit nicht-blockierenden Instruktionen

11.8. Was bedeutet starke Fairness?

(Aus den Folien) "A schedule is strongly fair, if and only if every process that is runnable infinitely often is scheduled infinitely often. A violation of strong fairness occurs if there exists a process which is runnable infinitely often, but gets the CPU only a finite number of times (or not at all)." > Ein Prozess der "unendlich" mal lauffähig ist, wird "unendlich" oft geschedult und bekommt auch entsprechend "unendlich" oft die CPU. Also z.B. ein immer wieder lauffähiger Prozess

  • wird Berechnungen immer wieder beenden
  • und dann erneut lauffähig werden

11.9. TODO Welche Eigenschaft hat ein universell fairer Scheduler?

Ein universell fairer Scheduler muss "strongly fair" sein. Ein Scheduling von einem fairen Scheduler muss auch von einem universell fairen Scheduler erzeugt werden können.

11.10. TODO Wie lässt sich ein Universell Fairer Scheduler mit Hilfe von Zufallszahlen realisieren? Skizze in Pseudo-Code

11.11. TODO Skizzieren sie den Beweis der universellen Fairness dieses Schedulers.

11.12. TODO Nach maximal wie vielen Schedulingzyklen wird in diesem Fall ein Prozess mit Prozessgewicht M bei N Prozessen geschedult?

11.13. TODO Warum ist der universell faire Scheduler nicht umsetzbar, wenn die Prozessgewichte vom Typ „int“ sind?

11.14. TODO Wie werden im Linux-Kernel Prozesse der Policy SCHED\OTHER geschedult?

11.15. TODO Ist der Completely Fair Scheduler (CFS) ein universell fairer Scheduler?

11.16. TODO Ist der Completely Fair Scheduler (CFS) ein stark fairer Scheduler?

12. Cloud Computing

12.1. Wie erzeugt man einen Container mit Docker – erkläre den Inhalt eines Dockerfile und beschreibe die nötigen docker-Kommandos, um einen Container zu bauen

Ein `Dockerfile` könnte z.B. folgenden Inhalt haben: ``` FROM ubuntu:latest COPY project/binary/foo /usr/bin/foo RUN chmod +x /usr/bin/foo ENTRYPOINT ["/usr/bin/foo"] ``` Um mit einem `Dockerfile` ein neues Container-Image zu bauen `docker build -t CONTAINERNAME:TAG ./Dockerfile`. Es wird mit `FROM` ein Container-Image als Basis ausgewählt, dass angepasst werden soll. Mit dem `COPY` wird aus dem relativen Pfad `./project/binary/foo` eine Datei in den Container an den Pfad `/usr/bin/foo` kopiert. Mit `RUN` können Befehle im Container ausgeführt werden, die Änderungen dabei werden im entstehenden neuen Container-Image gespeichert (hier, dass `/usr/bin/foo` das executable-Bit gesetzt bekommt). Mit `ENTRYPOINT` wird der Befehl angegeben, der beim Start eines Containers (der das neue Container-Image verwendet) ausgeführt wird.

12.2. Erkläre den Inhalt eines yaml-Files zur POD Erzeugung - Beispiele "Hello World" sowie Start eines eigenen Containers vom Docker Hub

``` — apiVersion: batch/v1 kind: Job metadata: name: hello-world namespace: bs2024 spec: template: spec: containers:

  • name: hello-world image: ubuntu:latest imagePullPolicy: IfNotPresent command: ["echo", "Hello World - version 1!"]

restartPolicy: Never backoffLimit: 4 ``` Es wird eine Resource vom Typ `Job` definiert, mit dem Namen `hello-world` und in dem Namespace `bs2024`. Der Job wird entsprechend dem `spec` spezifiziert. Es soll ein Container mit dem Namen `hello-world` gestartet werden und dafür das Container-Image `ubuntu` mit dem `latest` Tag geholt werden. In diesem Container wird der Befehl `echo "Hello World - version 1!"` ausgeführt. Falls der Container "sterben" sollte, soll er nicht neugestartet werden (`restartPolicy: Never`). Das `backoffLimit` gibt eine Grenze an, wie oft versucht werden soll den Container neuzustarten, bevor aufgegeben wird. Um einen eigenen Container zu starten würde man `image`, `command` und die `name` entsprechend anpassen.

12.3. Was ist der Unterschied zwischen einem "normalen" POD und einem Deployment ?

Ein Deployment ist ein POD, welcher von Kubernetes neugestartet werden kann und von dem eine bestimmte Anzahl an Replicas vorhanden sein sollen.

12.4. Wie kann man in der POD-Spezifikation Umgebungsvariablen setzen?

Unterhalb der Container-Spezifikation können Environment-Variablen gesetzt werden: ``` spec: template: spec: containers:

  • name: example-container image: docker.io/example/container env:
    • name: VARIABLENAME value: examplevalue

```

12.5. Was ist ein Persistent Volume Claim?

Ein PVC ist ein Claim/Anspruch an einen persistenten Speicher der von einem Pod gestellt wird. Zu jedem PVC gehört ein PV. Wo die Daten letzendlich gesichert/persistiert wird vom Cluster System Management entschieden.

12.6. Welche Arten von Persistent Volume Claims gibt es ?

Es gibt drei verschiedene Typen von Claims: `ReadWriteOnce`, `ReadOnlyMany`, `ReadWriteMany`

12.7. Wie kann ein laufender POD auf dem Cluster die Cluster-IP eines dort laufenden Services abfragen?

Entweder über eine DNS-Query, oder über Environment-Variablen. Angenommen es gibt einen Service `mysql-example` im Namespace `bs2024`. Dann ist die Environment-Variable `MYSQLEXAMPLESERVICEHOST` entsprechend der IP gesetzt (Pod muss gestartet worden sein, nachdem der Service existierte!). Besser ist es über DNS-Queries, z.B. mit `dig +short mysql-example.bs2024`.

12.8. Erkläre das yaml-File zur Erzeugung eines öffentlich zugänglichen Service, der seinerseits replizierte Service Backends verwendet

Man benötigt 2 yaml-Files, eines für das replizierte Backend und eines für einen LoadBalancer welcher die Anfragen auf die Backends verteilt. ```backend.yml apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: replicas: 3 template: spec: containers:

  • name: example image: "docker.io/example/container:latest" ports:
    • name: http containerPort: 80

``` ```loadbalancer.yml apiVersion: v1 kind: Service metadata: name: frontend spec: selector: app: backend ports:

  • protocol: "TCP" port: 80 targetPort: 80

type: LoadBalancer ```

12.9. TODO Erkläre den Code von Client, Server Frontend und Server Backend im Projekt dpll-server-and-backend

12.10. Wie kann man auf dem Cluster mit mehreren PODS über eine Multicast-Adresse kommunizieren?

Mehrere Container die innerhalb eines PODS laufen, können über `localhost` miteinander kommunizieren. TODO Multicast-Adresse (ggf. auch über PODS hinweg?)

12.11. TODO Erkläre den Java Script Code, den der Client verwendet, um den Cloud Server über das REST API anzusprechen

12.12. TODO Erkläre den C++ REST API Code in backend Servern- Sledgehammer/DPLL-Anwendung

12.13. TODO Erkläre den C++ REST API Code im Server Frontend - Sledgehammer/DPLL Anwendung

Author: Felix Drees

Created: 2024-02-23 Fri 15:40

Validate