Skip to content
Snippets Groups Projects
Commit 2eaf5a60 authored by Philip Kaluđerčić's avatar Philip Kaluđerčić :u7121:
Browse files

Elaborate some of the answers to the recently added ss21 questions

parent 33f186e9
No related branches found
No related tags found
No related merge requests found
......@@ -2,22 +2,21 @@
- Bei kooperativem Scheduling sind Prozessumschaltungen unmöglich, wenn ein Prozess in einer Endlosschleife läuft. Selbst wenn er bei jedem Schleifendurchlauf einen Systemaufruf macht.
Nein, laufender Prozess gibt CPU mit Systemaufruf ab.
- Online-Schedulingverfahren sind für den Einsatz in Rechnern ohne Netzwerkschnittstelle ungeeignet.
Nein.
Nein, mit dem Begriff "online" ist nicht gemeint, dass die Schedulingverfahren mit einem Netzwerk interagieren, sondern eine Klasse von Algorithmen, welche ihre Daten zur Ausführungszeit erhalten, im Gegesatz zu "offline" Algorithmen, welche von Anfang an alle Daten zur Verfügung haben.
+ Verdrängende Schedulingverfahren können nur mit Hilfe von Unterbrechungen realisiert werden.
Ja.
Ja, spezifisch Timer-Interrupts werden dazu benutzt um selbst nicht-kooperative Programme _unterbrechen_ zu können. Wenn diese Ankommen, welchselt die Ausführung zum Betriebsystem, und das Betriebsystem kann den Scheduler anstoßen, damit dieser beliebige Prozesse ein- und auslagern kann.
- Deterministische Schedulingverfahren sind nur in der Theorie relevant, da die genaue Länge der CPU-Stöße nie vorhergesagt werden kann.
Nein.
.
0 Welche der folgenden Aussagen zum Thema Prozesse und Threads ist richtig? (2022-07)
+ Bei schwergewichtigen Prozessen ist die Schedulingstrategie durch das Betriebssystem vorgegeben.
Ja.
Ja, dieses ist der Fall für schwer- und leichtgewichtige Prozesse, aber nicht mehr für federgewichtige, wo die Schedulingstrategie durch einen Scheduler im User-Space umgesetzt wird.
- Jeder federgewichtige Prozess (User-Thread) und jeder leichtgewichtige Prozess (Kern-Thread) hat seinen eigenen, geschützten Adressraum.
Nein, teilen sich einen Adressraum.
Nein, teilen sich einen Adressraum. Dieses wäre bei schwergewichtigen Prozessen der Fall.
- Bei Blockade eines schwergewichtigen Prozesses werden alle anderen schwergewichtigen Prozesse, die das selbe Progamm ausführen, ebenfalls blockiert.
Nein, schwergewichtige Prozesse sind unabhängig voneinander, d.h. sie haben einen eigenen Ausführungsfaden.
Nein, schwergewichtige Prozesse sind unabhängig voneinander, d.h. sie haben einen eigenen Ausführungsfaden. Bei federgewichtigen Prozessen würde das Problem bestehen (beschränkt auf den Kontext von einem Prozess).
- Unabhängig von leichtgewichtigen Prozessen (Kernel-Threads) können federgewichtige Prozesse (User-Threads) Multiprozessoren ausnutzen.
Nein.
Nein, federgewichtige Prozesse (engl. oft "[user threads](https://de.wikipedia.org/wiki/User-Thread)") können höchstens so viele Kerne ausnutzen, wie es leichtgewichtige Prozesse gibt, insofern der Scheduler auch darauf ausgelegt ist die federgewichtigen Prozesse zwischen kernen bzw. leichtgewichtigen Prozessen hin und her zu schalten.
.
0 Welche der folgenden Aussagen zum Thema RAID ist richtig? (2022-07)
......@@ -26,39 +25,124 @@ Ja, da die Paritätsbits auf alle Platten aufgeteilt sind.
- Bei RAID 0 können nach Ausfall einer der beteiligten Platten die Daten durch die Information der anderen rekonstruiert werden.
Nein, wenn eine Platte ausfällt, fällt das System aus.
- Der Lesedurchsatz eines RAID-Systems mit mehreren Platten ist prinzipbedingt geringer als der Lesedurchsatz einer einzelnen Platte.
Nein.
Nein, weil mehr als eine Platte gleichzeitig angefragt werden kann um Daten zu liefern, und man auf all diese Anfragen gleichzeitig warten kann, was schneller ist als wenn diese Anfragen sequenziell abgearbeitet werden müssten.
- Bei RAID 4 werden alle im Verbund beteiligten Platten gleichmäßig beansprucht.
Nein, die Paritätsplatte bei RAID 4 wird mehr beansprucht als die anderen Platten.
.
0 Für lokale Variablen, Aufrufparameter usw. einer Funktion wird bei vielen Prozessoren ein Stack-Frame angelegt. Welche Aussage ist richtig? (2022-07)
- Ein Pufferüberlauf eines lokalen Arrays wird immer zu einem Segmentation Fault führen und kann somit keine sicherheitskritischen Auswirkungen haben.
Nein.
Nein, wie in der _Hacking Übung_ gezeigt wird, ist es möglich über den Speicher eines Arrays hinweg zu lesen und zu schreiben, was mit dem richtigem Wissen ausgenutzt werden kann. C als Sprache gibt nicht vor, welches verhalten richtig ist (_Undefined Behaviour_), und könnte prinzipiell zur Laufzeit oder insofern möglich statisch vorhersagen ob es zu einem solchem Fehler kommt, und das dann entsprechend Behandeln (wie im Fall von anderen Sprachem mit höhere Typsicherheit: Java, Ada, Rust, ...).
Ein Fehler wie ein Segmentation-Fault hängt mit der Speichervirtualisierung, und nicht mit dem Sprach-Konzept eines Arrays zusammen, und muss daher nicht auftreten, wenn der Speicher hinter dem Array verfügbar ist, auch wenn der Inhalt aus sprachlicher sicht nicht definier ist.
- Es ist nicht möglich auf lokale automatic-Variablen zuzugreifen, die sich im Stack-Frame einer anderen Funktion befinden.
Doch, innerhalb eines Threads kann man auf den gesamten Stack zugreifen.
Doch, aber diese sind nur nicht sichtbar (auser im Fall von Lokalen Funktionen), und müssten als Speicherreferenzen übergeben werden. Alternativ könnte man mit Wissen über die ABI die Addresse von Variablen aus einem anderem Stack Frame im gleichem Thread berechen. Aber inhärränt gibt es allgemein hierzu keine Einschränkung mittels Speicherschutzmechanismen.
- Bei rekursiven Funktionsaufrufen kann der Speicher des Stack-Frames in jedem Fall wiederverwendet werden, weil die gleiche Funktion aufgerufen wird.
Nein, Variablen müssen neu initialisiert werden, bei jedem Funktions-Aufruf -> Stackoverflow
Nein, das ist nur dann möglich wenn die Funktionen endrekursiv sind, und der Übersetzer in der Lage ist diese zu entrekursivieren (Tail Call Optimisation). Allgemein benötigen Rekursive Funktionen den Speicher der mit jedem Aufruf angelegt wird, um ihr Ergebnis zu bestimmen, bswp. eine naive Implementierung der Fakultätsfunktion
~~~
unsigned fact(unsigned n)
{
if (n <= 1) {
return 1;
}
return n * fact(n-1);
}
~~~
Speichert sich auf dem Stack alle Werte von `n` bis `1`, und multipliziert diese am Ende zusammen beim Abwickeln des Aufrufbaums. Würde der Stack-Frame wiederbenutzt werden, würde jeder Aufruf die Speicherstelle überschreiben wo der Wert von `n` aus jedem vorherigem Aufruf auch gespeichert wäre, und das Endergebnis wäre damit verfälscht (in dem Fall wäre es `n` quadriert).
+ Wenn in einem UNIX-Prozess mehrere Threads parallel laufen, benötigt jeder von ihnen einen eigenen Stack.
Ja.
Ja. Wenn die Anzahl der Threads nicht statisch bekannst ist (wie in C mit Pthreads im Allgemeinem der Fall ist), dann wird der Speicher für jeden Thread dynamisch auf der Halde angelegt.
.
1 Welche der folgenden Aussagen zu UNIX/Linux-Dateideskriptoren sind korrekt? (2022-07)
- Ein Dateideskriptor ist eine Verwaltungsstruktur, die auf der Festplatte gespeichert ist und Informationen über Größe, Zugriffsrechte, Änderungsdatum usw. einer Datei enthält.
Nein, ist prozesslokal gespeichert.
Nein, mit dieser Aussage ist die Inode Abstraktion gemeint. Außerdem geht es nicht um die Speicherung eines Deskriptors bei der Prozess-Lokalität, sondern dass die Interpretation des Wertes von einem Deskriptors vom Betriebsystem bei Systemaufrufen getätigt wird, indem dieser überprüft welcher Prozess den Systemaufruf abgesetzt hat.
+ Nach dem Aufruf von fork(2) teilen sich die Prozesse die den gemeinsamen Dateideskriptoren zu Grunde liegenden Kernel-Datenstrukturen.
Ja, definiert von fork(2).
Ja, ist auch sinnvoll, wenn man will, dass Prozesse die Standard Ein- und Ausgabe vererben, was die Grundlage von einer Shell bildet.
Dieses kann zu Nebenläufigkeitsfehlern führen! Nimmt man Beispielsweise dieses Programm, welches in zwei Prozessen ausgeführt wird:
~~~
#include <stdio.h>
#include <unistd.h>
int main()
{
/* disable output buffering: */
setvbuf(stdout, NULL, _IONBF, 0);
/* child writes "a\n", parent writes "b\n" */
char *line = 0 == fork() ? "a" : "b";
for (;;) puts(line);
return 0;
}
~~~
und lässt es eine Sekunde lang laufen,
~~~
$ timeout 0.1 ./a.out > out
$ uniq -c out | sort | uniq
1
1 a
1 ab
1 b
1 ba
2 a
2 b
3 b
4 a
4 b
63 b
7 a
~~~
sieht man, dass die Ausgabe irregulär ist, und davon abhängt wie der Scheduler die Prozesse ein und ausgelagert hat. Wenn man mit dem Systemaufruf `nice(2)` die Priorität eines Prozesses verändert, dann ändert sich entsprechend auch die Ausgabe. Hier bspw. hat man nach dem `fork(2)` die Priorität vom Eltern-Prozess (`"b\n"`) erhört:
~~~
$ timeout 0.1 ./a.out > out
$ uniq -c out | sort | uniq | sort -nr
189 b
50 a
44 a
34 b
31 b
27 b
20 b
16 b
13 b
11 b
10 b
5 b
5 a
4 b
4 a
3 b
3 a
2 b
2 a
1 ba
1 b
1 ab
1 a
1
~~~
+ Ist das Flag FD_CLOEXEC eines Dateideskriptors gesetzt, dann wird dieser Dateideskriptor geschlossen, sobald der Prozess eine Funktion der exec-Familie aufruft.
Ja, definiert von FD_CLOEXEC.
Ja, definiert von `FD_CLOEXEC`.
+ Ein Dateideskriptor ist eine prozesslokale Integerzahl, die der Prozess zum Zugriff auf eine Datei benutzen kann.
Ja.
Ja. Dabei ist wichtig, dass diese Zahl keine Bedeutung für den Prozess selbst hat, sondern nur als Identifikation einer Ressourcenzuteilung für den jeweiligen Prozess dienst. Daher kann der Wert nicht ohne weiteres zwischen Prozessen umher gereicht werden.
- Ein Dateideskriptor ist eine Integerzahl, die über gemeinsamen Speicher an einen anderen Prozess übergeben werden kann und von letzterem zum Zugriff auf eine geöffnete Datei verwendet werden kann.
Nein, ist eine prozesslokale Integerzahl.
+ Auch Netzwerkverbindungen werden über einen Dateideskriptor referenziert.
Ja.
- Wird ein Dateideskriptor mittels des dup(2)-Systemaufruf vervielfältigt, können die Zugriffsrechte auf dem resultierendem Deskriptor unabhängig vom ursprünglichen geändert werden.
Nein.
Nein, weil diese sich auf die gleiche Verwaltungsstruktur im Betriebssystemkern beziehen.
- Dateideskriptoren sind Zeiger auf Betriebssystem-interne Strukturen, die von den Systemaufrufen ausgewertet werden, um auf Dateien zuzugreifen.
Nein, ist eine Integerzahl.
Nein, obzwar ein Zeiger fürüblich auch ein Integerzahl ist, verweist ein Datei-Deskriptor nicht direkt auf eine Speicherstelle welche direkt derefernziert werden kann, wie bei einem gewöhnlichem Zeiger. Um auf die jeweiligen Strukturen im Betriebsystem zu verweisen, muss das Betriebsystem den Datei-Deskriptor interpretieren (oft bspw. als Index in einem Array von Zeigern auf eben die Betriebssystem-interne Strukturen).
.
1 Welche der folgenden Aussagen zum Thema persistenter Datenspeicherung sind richtig? (2022-07)
......@@ -71,9 +155,9 @@ Nein.
- Bei indizierter Speicherung kann es prinzipbedingt nicht zu Verschnitt kommen.
Doch, es kann zu Verschnitt kommen, da der Speicher in Blöcke unterteilt wird. (Verschnitt: manche Speicherblöcke bei Aufteilung von Daten können nur zum Teil gefüllt werden)
+ Bei kontinuierlicher Speicherung von Daten ist es unter Umständen mit enormem Aufwand verbunden, eine bestehende Datei zu vergrößern.
Ja, dynamisches Erweitern schwierig.
Ja, dynamisches Erweitern schwierig, weil es das umherbewegen ganzer Dateien benötigen könnte, welche jeweils alle wieder in freien, kontinuierlichen Speicherbereichen gelegt werden müssten. Das wird besonders dann erschwert, wenn mehre Prozesse versuchen lesend oder schreibend auf das Dateisystem zuzugreifen.
- Im Vergleich zu den anderen Verfahren ist bei indizierter Speicherung die Positionierzeit des Festplatten-Armes beim Zugriff auf alle Datenblöcke einer Datei minimal.
Nein.
Nein. Allgemein hat die Positionierzeit nichts direkt mit dem Dateisystem zu tun. Ein Dateisystem könnte so ausgelegt sein, um große Sprünge des Festplatten-Armes zu vermeiden.
+ Journaling-Dateisysteme garantieren, dass auch nach einem Systemausfall alle Metadaten wieder in einen konsistenten Zustand gebracht werden können.
Ja, mit Hilfe der Log-File.
+ Festplatten eignen sich besser für sequentielle als für wahlfreie Zugriffsmuster.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment