[{"id":"lpByZhVbrXfKmROD689EDw","source":"2019-06","question":"
Gegeben sei folgendes Szenario: zwei Fäden werden auf einem\nMonoprozessorsystem mit der Strategie First Come First Served
\nverwaltet. In jedem Faden wird die Anweisung\ni++;
auf der gemeinsamen, globalen volatile Variablen i\nausgeführt. Welche der folgenden Aussagen ist richtig?
In einem Monoprozessorsystem ohne Verdrängung ist keinerlei\nSynchronisation erforderlich.
\n","comment":"Ja, weil der Befehl immer ganz ausgeführt wird, und weil\nes keine unvorhergesehenen Unterbrechungen gibt,\nmuss man diese auch nicht verhindern oder\ndagegen vorbeugen.
\n"},{"option":"Während der Inkrementoperation müssen Interrupts vorübergehend\nunterbunden werden.
\n","correct":false,"comment":"Nein, weil ein Interrupt keinen Einfluss haben muss auf\ndiese Operation.
\n"},{"comment":"Nein, wenn notwendig, wäre es auch erlaubt es mit anderen mitteln zu\nsynchronisieren.
\n","correct":false,"option":"Die Inkrementoperation muss mit einer CAS-Anweisung\nsynchronisiert werden.
\n"},{"option":"Die Operation i++ ist auf einem Monoprozessorsystem\nimmer atomar.
\n","correct":false,"comment":"Nein, das hängt von der Recherarchitektur ab, und kann\naber muss nicht atomar übersetzt werden.
\n"}],"multiple":false},{"source":"2019-06","question":"Der Speicher eines UNIX-Prozesses ist in Text-, Daten- und\nStack-Segment untergliedert. Welche Aussagen bezogen auf C-Programme\nsind richtig?
\n","id":"fLqSDX1OQ7aHoT7vNTK0xw","multiple":true,"options":[{"comment":"Ja, damit verhindert man auch Namenskonflikte zwischen Modulen.
\n","correct":true,"option":"Die Sichtbarkeit globaler static
-Variablen ist auf das\njeweilige Modul beschränkt.
Funktionspointer werden nicht immer im\nText-Segment gespeichert.
\n","comment":"Ja, es kann auch direkt auf dem Stack gespeichert\nwerden.
\n"},{"comment":"Ja-ish; diese können nicht im Text-Segment liegen, weil\ndie dann nicht schreibbar währen; diese können\nnicht auf der Halde liegen, weil das zur laufzeit dynamisch\nverwaltet wird; diese können nicht auf dem Stack liegen,\nweil die Gültigkeit unabhängig vom Kontrollfluss und dem Aufrufbaum\nist.
\n","option":"Globale schreibbare Variablen liegen im Daten-Segment.
\n","correct":null},{"comment":"Nein, weil das Text Segment üblicherweise nicht zur\nlaufzeit verändert wird.
\n","correct":false,"option":"Dynamisch allozierte Zeichenketten liegen im Text-Segment.
\n"},{"comment":"Nein, dynamische Speicherverwaltung, würde wenn überhaupt die Halde\n(Heap) erweitern.
\n","correct":false,"option":"Bei einem Aufruf von malloc(3)
wird das Stack-Segment\ndynamisch erweitert.
Nein, der Code von Funktionen liegt im Text Segment.
\n","correct":false,"option":"Der Code von Funktionen wird zusammen mit den Variablen der Funktion\nim Stack-Segment abgelegt.
\n"},{"comment":"Eigentlich ja, aber man kann dann diskutieren ob eine\nnicht-initialsierte static
Variable, welche im BSS Segment\nliegt auch teil vom Daten-Segment ist oder nicht.
Variablen der Speicherklasse static
liegen im\nDaten-Segment.
Nein, diese behalten den gleichen Wert unabhängig vom\nFunktionsaufruf. Ihre Sichtbarkeit ist nur auf eine Funktion\nbeschränkt.
\n","option":"Lokale static
-Variablen werden bei jedem\nBetreten der zugehörigen Funktion neu initialisiert.
Was passiert, wenn Sie in einem C-Programm versuchen über einen\nZeiger auf ungültigen Speicher zuzugreifen?
\n","id":"9vO0Vv0H/3eXxrMdGQNFYw","options":[{"option":"Das Betriebssystem erkennt die ungültige Adresse bei der Weitergabe\ndes Befehls an die CPU (partielle Interpretation) und leitet eine\nAusnahmebehandlung ein.
\n","correct":false,"comment":"Das Betriebsystem interpretiert die Befehle des Programms\nnicht selbst. Diese werden direkt von der CPU\ninterpretiert, welches sich in einem unpriviligiertem Modus befindet.\nFür privilegierte Befehle, muss man mit einem Systemaufruf\nsich an das Betriebsystem wenden.
\n"},{"comment":"Zwar möglich, aber das ist nicht der Fall in C, wo\nFehlerbehandlung händisch gemacht wird.
\n","correct":false,"option":"Der Compiler erkennt die problematische Code-Stelle und generiert\nCode, der zur Laufzeit bei dem Zugriff einen entsprechenden Fehler\nauslöst.
\n"},{"comment":"Der Speicher
würde in diesem Fall keinen Interrupt schicken,\nweil der Zugriff auf den ungültigen Speicher bewusst und deterministisch\naufgetreten ist, und daher als ein Trap
angesehen werden\nsollte.
Der Speicher schickt an die CPU einen Interrupt. Hierdurch wird das\nBetriebssystem angesprungen, das dem gerade laufenden Prozess das Signal\nSIGSEGV
(Segmentation Violation) zustellt.
Ja; die CPU kann dann je nach Betriebsystem sich\nentscheiden diesen Trap weiter zu leiten an einen Prozess in Form eines\nSignals o.Ä.
\n","correct":true,"option":"Beim Zugriff muss die MMU, soweit vorhanden, die\nerforderliche Adressumsetzung vornehmen, erkennt die ungültige Adresse\nund löst einen Trap aus.
\n"}],"multiple":false,"source":"2019-06"},{"question":"Welche der folgenden Aussagen zum Thema Synchronisation ist\nrichtig?
\n","id":"+wOmNXjPgdMFEzsJLNo1oA","options":[{"correct":false,"option":"Der Einsatz von nicht-blockierenden Synchronisationsmechanismen\nkann zu Verklemmungen (deadlocks) führen.
\n","comment":"Nein, bei einer Verklemmung müssen mehre Fäden passiv aufeinander\nwarten, was bei nicht-blockierendeer Synchronisation nicht\npassieren kann.
\n"},{"correct":false,"option":"Ein Anwendungsprozess muss bei der Verwendung von\nSemaphoren Interrupts sperren, um Probleme durch Nebenläufigkeit zu\nverhindern.
\n","comment":"Nein, weil ein Anwendungsprozess keine Interrupts selbst\nsperren kann.
\n"},{"correct":true,"option":"Gibt ein Faden einen Mutex frei, den er selbst zuvor\nnicht angefordert hatte, stellt dies einen\nProgrammierfehler dar; eine Fehlerbehandlung sollte eingeleitet\nwerden.
\n","comment":"Ja, weil ein Mutex immer von dem gleichem Faden\nfreigegeben werden sollte, wer es auch beansprucht hat (im Gegensatz zur\nbinären Semaphore, wo diese Bedingung nicht gilt).
\n"},{"option":"Zur Synchronisation eines kritischen Abschnitts ist passives Warten\nimmer besser geeignet als aktives Warten.
\n","correct":false,"comment":"Je nach Situation ist es nicht möglich (bspw. im Kern\nselbst, wo die Mechanismen Fehlen um passiv
).
Welche Antwort trifft für die Eigenschaften eines\nUNIX/Linux-Dateideskriptor zu?
\n","options":[{"comment":"Nein, es ist zwar eine Ganzzahl, aber diese kann\nnicht beliebig hin und her gereicht werden, zumindest ohne\ndass das Betriebsystem entsprechend informiert wird (siehe\nsendmsg(2)
).
Ein Dateideskriptor ist eine Integerzahl, die über gemeinsamen\nSpeicher an einen anderen Prozess übergeben werden kann, und von\nletzterem zum Zugriff auf eine geöffnete Datei verwendet werden\nkann.
\n"},{"comment":"Nein, es handelt sich nicht um einen Zeiger im\ngewöhnlichen Sinne (eine Adresse auf eine Speicherstelle), auch wenn es\nüblicherweise dazu benutzt wird um eine Prozess-Lokale Datei Tabelle zu\nAdressieren. Es stimmt aber, dass es dazu benutzt wird, einem\nSystemaufruf eine Datei anzudeuten, auf dem dieses arbeiten soll.
\n","option":"Dateideskriptoren sind Zeiger auf Betriebssystemstrukturen, die von\nden Systemaufrufen ausgewertet werden, um auf Dateien zuzugreifen.
\n","correct":false},{"comment":"Ja, ein Dateideskriptor muss nicht nur auf\ngewöhnlichen
Dateien arbeiten, sondern kann\nverschieden Datei-Ähnlichen
Objekten (d.h. Datenströmen)\nabstrahieren. Wichtig ist auch der Punkt prozesslokal
, weil die\nZahl nur eine Bedeutung hat, wenn das Betriebsystem dem Prozess diese\nZahl zuvor explizit vergeben hat.
Ein Dateideskriptor ist eine prozesslokale Integerzahl, die der\nProzess zum Zugriff auf eine Datei, ein Gerät, einen Socket oder eine\nPipe benutzen kann.
\n"},{"correct":false,"option":"Beim Öffnen ein und derselben Datei erhält ein Prozess jeweils die\ngleiche Integerzahl als Dateideskriptor zum Zugriff zurück.
\n","comment":"Nein, es ist möglich eine Datei Mehrfach zu öffnen, und dabei mehrere\nDateideskriptoren zu bekommen. Versuche
\n\nint main()\n{\n int fd1 = open("/etc/passwd", O_RDONLY);\n int fd2 = open("/etc/passwd", O_RDONLY);\n\n printf("fd1: %d, fd2: %d\\n", fd1, fd2);\n}
\n"}],"multiple":false},{"options":[{"comment":"Ja, Beispielsweise bei einem ungültigem Speicherzugriff.
\n","correct":true,"option":"Ein Programm darf im Rahmen einer Trapbehandlung abgebrochen\nwerden.
\n"},{"comment":"Nein, weil ein Interrupt nichts mit dem Programm zu tun hat, und\ndaher dieses nicht (direkt) abbrechen sollte.
\n","correct":false,"option":"Ein durch einen Interrupt unterbrochenes Programm darf je nach der\nInterruptursache entweder abgebrochen oder fortgesetzt werden.
\n"},{"option":"Bei einem Trap wird der gerade in Bearbeitung befindliche\nMaschinenbefehl immer noch vollständig zu Ende bearbeitet,\nbevor mit der Trapbehandlung begonnen wird.
\n","correct":false,"comment":"Nein, bspw. wenn man versucht auf nicht lesbaren\nSpeicher versucht zuzugreifen, muss es abgebrochen werden,\nbevor auf den Speicher zuggegriffen wurde.
\n"},{"option":"Die CPU sichert bei einem Interrupt einen Teil des\nProzessorzustands.
\n","correct":true,"comment":"Ja, genau wie bei einer Signal-Behandlung unterbricht ein Interrupt\ndas Hauptprogramm
vom Betriebsystem. Der Prozessorzustand\nmuss dafür vermerkt worden sein, damit es danach wieder\nrestauriert werden kann.
Die Ausführung einer Ganzzahl-Rechenoperation (z. B. Addition,\nDivision) kann zu einem Trap führen.
\n","correct":true,"comment":"Ja, eine Rechnerarchitektur kann beim Teilen durch 0 ein\nTrap auslösen.
\n"},{"comment":"Nein, es ist dennoch möglich wenn beide auf die gleichen Ressourcen\nwarten, was im Betriebsystemkern möglich ist, vor allem wenn mehrere\nKerne mitspielen.
\n","option":"Da Traps immer synchron auftreten, kann es\nim Rahmen ihrer Behandlung nicht zu Wettlaufsituationen mit\ndem unterbrochenen Programm kommen.
\n","correct":false},{"comment":"Nein, ein Interrupt sollte nie direkt zur Beendigung\neines Programms füren.
\n","correct":false,"option":"Wenn ein Interrupt ein schwerwiegendes Ereignis signalisiert, wird\ndas unterbrochene Programm im Rahmen der Interruptbearbeitung\nimmer abgebrochen.
\n"},{"comment":"Nein, weil diese deterministisch immer dann auftreten,\nwenn ein Programm ein Systemaufruf absetzen will.
\n","correct":false,"option":"Ein Systemaufruf im Anwendungsprogramm ist der Kategorie Interrupt\nzuzuordnen.
\n"}],"multiple":true,"question":"Man unterschiedet zwei Kategorien von Ausnahmesituationen bei einer\nProgrammausführung: Traps und Interrupts. Welche der folgenden Aussagen\nsind zutreffend?
\n","id":"CqujDOAAJFgBTZE0ZOtCGw","source":"2022-02"},{"question":"In welcher der folgenden Situationen wird ein Prozess vom Zustand\nlaufend in den Zustand bereit übeführt?
\n","id":"83hLOh+dwcc/b1Fa8Hh2/g","source":"2022-02","multiple":false,"options":[{"comment":"Nein, weil danach der Prozess nicht mehr bereit
\nist (d.h. wieder eingelagert werden kann).
Der Prozess ruft die Bibliotheksfunktion exit(3)
\nauf.
Ja, weil die einzige Ressource welche dem Prozess fehlt ist die CPU,\nwelche der Scheduler später wieder vergeben
kann, und damit der\nProzess auch die ganze Zeit bereit ist wieder weiter zu laufen.
Der Scheduler bewirkt, dass der Prozess durch einen anderen Prozess\nverdrängt wird.
\n","correct":true},{"comment":"Nein, weil dann idr. der Prozess beendet wird mit einem Sigal wie\nSIGSEVG
, und nicht mehr laufen darf.
Der Prozess greift lesend auf eine Datei zu und der entsprechende\nDatenblock ist noch nicht im Hauptspeicher vorhanden.
\n","correct":false},{"comment":"Nein, weil dann der Prozess blokiert wird, und nicht\nmehr laufen kann, bis an einer anderen Stelle eine entsprechende\nV-Operation ausgeführt wird.
\n","correct":false,"option":"Der Prozess ruft eine P-Operation auf einen Semaphor auf, welcher den\nWert 0 hat.
\n"}]},{"options":[{"correct":true,"option":"Ein Speicherbereich, der mit Hilfe der Funktion free()
\nfreigegeben wurde, verbleibt im logischen Adressraum des zugehörigen\nProzesses.
Ja. Der logische Adressraum Al = [n, m]\nist der gesamte Adressbereich ohne Lücken, der einem Prozess zugeordnet\nwird. Dieser wird nicht verkleinert, wenn free
\naufgerufen wird. Im Gegensatz dazu ist der virtuelle Adressraum\nAv jener, der nur partiell auf den Hauptspeicher abgebildet\nwird, bei dem also Adressen ungültig sein können. (vgl. SP1 B Vl. 2 S.\n12 ff., 27) (Bin mir hier nicht zu 100 % sicher, dass meine\nInterpretation korrekt ist)
Nein, nach dem Ende des Programms wird der gesamte Adressbereich des\nProzesses freigegeben. Das ist möglich, weil das Betriebsystem den\nSpeicher für jeden Prozess virtualisiert und damit auch in der Lage ist,\nihm diese Ressource zu entziehen.
\n","correct":false,"option":"Mit malloc()
angeforderter Speicher, welcher vor\nProgrammende nicht freigegeben wurde, kann vom\nBetriebssystem nicht mehr an andere Prozesse herausgegeben\nwerden und ist damit bis zum Neustart des Systems verloren.
Nein, malloc(3)
ist kein Systemaufruf, sondern eine\nBibliotheksfunktion. Außerdem fordert die Laufzeitumgebung\n(libc) den Speicher üblicherweise grobgranular vom\nBetriebssystem an (mmap(2)
, brk(2)
) und\nverteilt diesen im Benutzerprozess.
Mit Hilfe des Systemaufrufes malloc()
kann\nein Programm zusätzliche Speicherblöcke von sehr feinkörniger Struktur\nvom Betriebssystem anfordern.
Nein, malloc
kann als Teil des\nLaufzeitsystems den grobgranular vom Betriebssystem angeforderten\nSpeicher feingranular aufteilen und zurückgeben.
Da das Laufzeitsystem auf die Betriebssystemschnittstelle zur\nSpeicherverwaltung zurückgreift, ist die Granularität der von\nmalloc()
zurückgegebenen Speicherblöcke vom Betriebssystem\nvorgegeben.
Welche Aussage zum Thema Adressraumverwaltung ist richtig?
\n"},{"options":[{"correct":false,"option":"Der TLB puffert die Ergebnisse der Abbildung von physikalische auf\nlogische Adressen, sodass eine erneute Anfrage sofort beantwortet werden\nkann.
\n","comment":"Nein, andersherum. Logische müssen in physikalische Adressen\nübersetzt werden.
\n"},{"comment":"Ja, da die Einträge im TLB beziehen sich auf einen bestimmten\nlogischen Adressraum.
\n","option":"Verändert sich die Speicherabbildung von logischen auf physikalische\nAddressen aufgrund einer Adressraumumschaltung, so werden auch die Daten\nim TLB ungültig.
\n","correct":true},{"comment":"Nein, ist kein Eintrag im TLB zu finden, wird die Addresse von der\nMMU aufgelöst.
\n","option":"Wird eine Speicherabbildung im TLB nicht gefunden, wird\nvom Prozessor immer eine Ausnahme (Trap) ausgelöst\ndie vom Betriebssystem behandelt wird.
\n","correct":false},{"comment":"Nein, ist kein Eintrag im TLB zu finden, wird die Addresse von der\nMMU aufgelöst. Der TLB agiert nur als cache für\nAdressübersetzungen.
\n","correct":false,"option":"Wird eine Speicherabbildung im TLB nicht gefunden, wird\nder auf den Speicher zugreifende Prozess mit einer Schutzraumverletzung\n(Segmentation Fault) abgebrochen.
\n"}],"multiple":false,"source":"2022-02","id":"xr8jLhVQPAxzuywYbe0Q0A","question":"Sie kennen den Translation-Lookaside-Buffer (TLB). Welche Aussage ist\nrichtig?
\n"},{"source":"2022-02","id":"xA1QqQfRhqL4/rFzy1YXWg","question":"Welche Aussage zu den verschiedenen Gewichtsklassen von Prozessen\ntrifft zu?
\n","multiple":false,"options":[{"comment":"Nein. Auch leichtgewichtigen Prozessen (kernel-level\nthreads) ist ein kernel thread zugeordnet.
\n","correct":false,"option":"Schwergewichtige Prozesse sind die einzige Klasse von Prozessen, die\nauf einem Multiprozessorsystem echt parallel ausgeführt werden kann, da\nnur hier jeder Benutzerfaden einem eigenen Kernfaden zugeordnet ist.
\n"},{"comment":"Ja, da bei federgewichtigen Prozessen mehrere Prozesse auf einen\nSystemkernfaden (kernel-level thread) gemultiplext werden, wird\ndie Ausführung der aller federgewichtigen Prozesse blockiert, die auf\neinem kernel-level thread ausgeführt werden, bis dieser wieder\nbereit ist.
\n","option":"Federgewichtige Prozesse (user-level threads) blockieren\nsich bei blockierenden Systemaufrufen gegenseitig.
\n","correct":true},{"comment":"Nein. Man kann mehrere Prozesse mit dem gleichen\nProgramm ausführen.
\n","option":"Beim Blockieren eines schwergewichtigen Prozesses werden\nalle anderen schwergewichtigen Prozesse, die das selbe\nProgamm ausführen, ebenfalls blockiert.
\n","correct":false},{"comment":"Falsch, das wären schwergewichtige Prozesse. Leichtgewichtige\nProzesse wie pthread
s teilen sich einen Adressraum.
Zu jedem leichtgewichtigen Prozess (kernel-level\nthread) gehört ein eigener, isolierter Adressraum.
\n","correct":false}]},{"multiple":false,"options":[{"comment":"Ja, die page descriptor table enthält für jeden\nSeitendeskriptor ein valid-Bit. Ist dieses nicht\ngesetzt, so wird ein Trap ausgelöst.
\n","option":"Im Seitendeskriptor wird ein spezielles Bit geführt, das der MMU\nzeigt, ob eine Seite eingelagert ist oder nicht. Falls die Seite\nnicht eingelagert ist, löst die MMU einen Trap aus.
\n","correct":true},{"comment":"Nein, die MMU interagiert nicht mit dem\nHintergrundspeicher, sondern ist nur für die Adressabbildung von\nlogischen zu realen Adressen zuständig.
\n","correct":false,"option":"Im Seitendeskriptor steht bei ausgelagerten Seiten eine Adresse des\nHintergrundspeichers und der Speichercontroller leitet den Zugriff auf\nden Hintergrundspeicher um.
\n"},{"comment":"Nein, das Betriebssystem überprüft nicht\njede Instruktion vor der Ausführung (vgl.\nTeilinterpretation).
\n","correct":false,"option":"Das Betriebssystem erkennt die ungültige Adresse vor Ausführung des\nMaschinenbefehls und lagert die Seite zuerst ein bevor ein Trap\npassiert.
\n"},{"option":"Bei Programmen, die in virtuellen Adressräumen ausgeführt werden\nsollen, erzeugt der Compiler speziellen Code, der vor Betreten einer\nSeite die Anwesenheit überprüft und ggf. die Einlagerung veranlasst.
\n","correct":false,"comment":"Nein, der Compiler fügt nicht in jedes\nProgramm eine Implementation der Speichervirtualisierung ein. Diese ist\neine Aufgabe des Betriebssystems und nicht der einzelnen\nBenutzerprogramme.
\n"}],"source":"2022-02","id":"NeE5MnVWhlExMvJOJrmPkQ","question":"Wie wird erkannt, dass eine Seite eines virtuellen Adressraums, auf\ndie ein Maschinenbefehl zugreift, gerade ausgelagert ist?
\n"},{"multiple":false,"options":[{"option":"Wenn der gleiche Seitenrahmen in zwei verschiedenen\nSeitendeskriptoren eingetragen wird, löst dies einen Seitenfehler aus\n(Gefahr von Zugriffskonflikten!).
\n","correct":false,"comment":"Nein, das würde z. B. zwischen Prozessen geteilten Speicher\nverhindern.
\n"},{"option":"Ein Seitenfehler wird ausgelöst, wenn der Offset in einer logischen\nAdresse größer als die Länge der Seite ist.
\n","correct":false,"comment":"Nein, dieser Fall kann per Definition nicht\neintreten. Seiten haben eine Größe von 2n Byte, (bei x86-64\nz. B. 4 KiB), n Byte der Adresse werden als Offset interpretiert. Somit\nist dieser Fall außerhalb des überhaupt darstellbaren Wertebereichs für\nden Offset. Im Gegensatz dazu wird bei Segmentierung überprüft, ob die\nlogische Adresse im Speichersegment liegt, das dem Prozess zugeordnet\nist. Dort könnte also ein derartiger Fehler auftreten.
\n"},{"correct":false,"option":"Ein Seitenfehler zieht eine Ausnahmebehandlung nach sich. Diese wird\ndadurch ausgelöst, dass die MMU das Signal SIGSEGV an den aktuell\nlaufenden Prozess schickt.
\n","comment":"Nein, ein Seitenfehler kann auch dadurch ausgelöst\nwerden, dass z. B. auf eine ausgelagerte Seite zugegriffen wird. Diese\nwird dann für den Prozess transparent eingelagert. Zudem löst die MMU\nein Trap aus, welches später zur Zustellung eines Signals führen kann.\nJedoch schickt sie nicht selbst Signale an Prozesse.
\n"},{"option":"Das Auftreten eines Seitenfehlers kann dazu führen, dass\nder aktuell laufende Prozess in den Zustand beendet überführt wird.
\n","correct":true,"comment":"Ja, wenn der Prozess auf eine ungültige Adresse zugreift, also\ninsbesondere auch keine Seite eingelagert werden\nkann und das entsprechende Signal nicht\nabgefangen wird, wird er terminiert.
\n"}],"source":"2022-02","id":"lTviFYeM7/qmUmE/knnqjw","question":"Welche der folgenden Aussagen zum Thema Seitenfehler (Page\nFault) ist richtig?
\n"},{"options":[{"correct":false,"option":"18
\n"},{"correct":false,"option":"10
\n"},{"option":"24
\n","correct":false},{"option":"16
\n","comment":"Ja. Makros, die mit #define
definiert sind, werden rein\ntextuell vor dem eigentlichen Kompiliervorgang vom Präprozessor\nexpandiert, indem an der Stelle, an der das Makro verwendet wird, die\nDefinition dessen, bis auf Ersetzung der Parameter mit dem angegebenen\nText, unverändert eingesetzt wird. Hier wird also nach dem\nPräprozessor-Schritt der folgende Ausdruck kompiliert:\n3 * 4 + 8 / 2
. Das ergibt 16. Dieses Problem könnte hier\ndurch das Einklammern der Definitionen gelöst werden.
Gegeben seien die folgenden Präprozessor-Makros:
\n#define ADD(a, b) a + b\n#define DIV(a, b) a / b
\nWas ist das Ergebnis des folgenden Ausdrucks?
\n3 * DIV(ADD(4, 8), 2)
\n","source":"2021-02"},{"source":"2021-02","question":"Welche Aussage über Einplanungsverfahren ist richtig?
\n","id":"qunySCF9iM7EQskvUqqeNg","multiple":false,"options":[{"correct":false,"option":"Im Round-Robin-Verfahren nutzen E/A-intensive Prozesse die ihnen\nzugeteilte Zeitscheibe immer voll aus
\n","comment":"Nein. Bei round-robin wird jedem Prozess reihum\neine gleich lange Zeitscheibe zugeteilt. Ein E/A-intensiver Prozess, der\noft früh in seiner Zeitscheibe durch eine E/A-Operation in den Zustand\nblockiert
übergeht, kann seine Zeitscheibe\nnicht bis zum Ende ausnutzen.
Nein. Insbesondere dort muss ein Prozess, der nur einen\nkurzen Rechenstoß macht, alle länger dauernden Rechenstöße\nin der Warteschlange abwarten.
\n","option":"Der Konvoieffekt kann bei kooperativen\nEinplanungsverfahren wie First-Come-First-Served nicht\nauftreten.
\n","correct":false},{"option":"Bei kooperativen Verfahren können Prozesse die CPU nicht\nmonopolisieren.
\n","comment":"Nein. Genau bei kooperativen Verfahren, bei denen Prozesse die CPU\nfreiwillig abgeben müssen, ist dies möglich. Präemptive Verfahren können\nim Gegensatz dazu derartige Prozesse unterbrechen.
\n","correct":false},{"option":"In einem asymmetrischen Multiprozessorsystem ist der Einsatz von\nasymmetrischen Verfahren zur Planung obligatorisch.
\n","comment":"Ja. Man betrachte z. B. den Fall CPU + GPU. Ein Prozess, der auf der\nCPU rechnen möchte, kann nicht unbedingt auch\nauf der GPU rechnen. Deswegen ist der Einsatz einer Bereitliste für\nalle Rechenkerne (symmetrisches Planungsverfahren) hier\nunmöglich. Stattdessen müssen zumindest für GPU und CPU separate\nBereitlisten existieren. Dies zeichnet asymmetrische Planungsverfahren\naus.
\n","correct":true}]},{"question":"Welche Aussage zu virtuellem Speicher ist richtig?
\n","source":"2021-02","options":[{"comment":"Nein. Mit virtuellem Speicher ist kein Bereich des physikalischen\nAdressraums gemeint. Stattdessen bezeichnet man damit die partielle\nAbbildung vom logischen zum physikalischen Adressraum.
\n","option":"Virtueller Speicher sind die nicht vorhandenen Bereiche\ndes physikalischen Adressraums.
\n","correct":false},{"correct":false,"comment":"Nein. Die Implementation von malloc
kann\ndas Betriebssystem dazu auffordern (mmap(2)
,\nbrk(2)
), den verfügbaren Speicherbereich des Prozesses zu\nvergrößern. Benutzerprogramme können jedoch nicht selbst\ndie Abbildung von virtuellen Adressen zu physikalischen Adressen\nändern.
Virtueller Speicher kann dynamisch zur Laufzeit von\neinem Programm mit der Funktion malloc(3p)
erzeugt\nwerden.
Nein. Die memory management unit übersetzt logische Adressen\nauf physikalische.
\n","option":"Unter einem Virtuellen Speicher versteht man einen physikalischen\nAdressraum, dessen Adressen durch eine MMU vor dem Zugriff auf logische\nAdressen umgesetzt werden.
\n"},{"correct":true,"comment":"Ja. Das bezeichnet man als swapping.
\n","option":"Virtueller Speicher kann größer sein als der\nphysikalisch vorhandene Arbeitsspeicher. Gerade nicht\nbenötigte Speicherbereiche können auf Hintergrundspeicher ausgelagert\nwerden.
\n"}],"multiple":false,"id":"SOzwqg8cUHa2ytfIyGMoUg"},{"options":[{"correct":false,"comment":"Nein. Systemaufrufe werden deterministisch ausgeführt, also werden\nsie der Kategorie Trap zugeordnet.
\n","option":"Weil das Betriebssystem nicht vorhersagen kann, wann ein\nProzess einen Systemaufruf tätigt, sind Systemaufrufe in die Kategorie\nInterrupt einzuordnen.
\n"},{"correct":false,"comment":"Nein. Das wäre die Definition von Traps. Interrupts, wie z. B. das\nEintreffen eines Netzwerkpakets treten ohne direkten Zusammenhang zum\nunterbrochenen Prozess auf.
\n","option":"Bei der mehrfachen Ausführung eines unveränderten Programms mit\ngleichen Eingabedaten treten Interrupts immer an den\ngleichen Stellen auf.
\n"},{"correct":false,"comment":"Nein. Das Unterdrücken von Interrupts ist eine privilegierte\nOperation, die dem Betriebssystem vorbehalten ist. (Das würde sonst z.\nB. einem Benutzerprozess das Umgehen einer präemptiven Einplanung\nermöglichen)
\n","option":"Ein gerade laufendes Maschinenprogramm kann bei Bedarf\ndie Behandlung aller Programmunterbrechungen unterdrücken.
\n"},{"correct":true,"comment":"Ja, wenn z. B. Division auf x86_64 mit\neinem Divisor von 0 ausgeführt wird.
\n","option":"Normale Rechenoperationen können zu einem Trap führen.
\n"}],"multiple":false,"id":"MqD4A1Li9FsmBATqJxj+rw","source":"2021-02","question":"Man unterscheidet Programmunterbrechungen in Traps und Interrupts.\nWelche Aussage ist richtig?
\n"},{"source":"2020-08","question":"Bei Programmunterbrechungen (Ausnahmen) unterscheidet man zwischen\nTraps und Interrupts. Welche Aussage zu Traps ist richtig?
\n","multiple":false,"id":"/LtHACvpnB/UQsA6qup/Ag","options":[{"correct":true,"comment":"Wahr, weil im physikalischem Addressraum nicht\nalle Addressen gültig sind. Teilweise bestehen Lücken, und\nje nach Addressbreite, wird es Addressen geben welche über den\nverfügbaren Speicher hinaus zeigen.
\n","option":"Der Zugriff auf eine physikalische Speicheradresse kann\nzu einem Trap führen.
\n"},{"comment":"Doch, können zu einem Trap führen. Vergleiche Division durch 0 auf\nx86 Prozessoren.
\n","option":"Normale Ganzzahl-Rechenoperationen (z. B. Addition, Division) können\nnicht zu einem Trap führen.
\n","correct":false},{"correct":false,"option":"Ein Trap steht nicht zwangsläufig in ursächlichem\nZusammenhang mit dem unterbrochenen Programm.
\n","comment":"Doch, ein Trap wird immer durch einen internen Fehler\nausgelöst. Im Gegensatz dazu ist dieses beim einem Interrupt\nnicht gegeben, weil die Ursache hier von außen kommt.
\n"},{"comment":"Nein, werden nach dem Beendigungsmodell und Wiederaufnahmemodell\nbehandelt.
\n","option":"Traps werden immer nach dem\nBeendigungsmodell/Terminierungsmodell behandelt.
\n","correct":false}]},{"options":[{"correct":false,"comment":"Nein, Symbolic Links sind nur Referenzen sind nicht\ndirekt mit einer Datei verbunden, im Sinne dass der einzige Weg zu\nbestimmen ob ein Symbolic Link auf eine Datei besteht, es wäre\nalle Symbolic Links im Dateisystem zu prüfen, weil diese\nInformation ansonsten nirgends zentral gespeichert wird.
\n","option":"Wenn der letzte symbolic link, der auf eine Datei verweist, gelöscht\nwird, wird auch der zugehörige Dateikopf (inode) gelöscht.
\n"},{"correct":false,"option":"Hard links können innerhalb des selben Datenträgers auf beliebige\nBlöcke zeigen.
\n","comment":"Nein, ein Hard Link bezieht sich auf Dateien im Dateisystem,\nnicht auf beliebige Blöcke. Die Dateien selbst werden sich\nauf Blöcke im Datenträgers beziehen.
\n"},{"option":"In einem Verzeichnis darf es keinen Eintrag geben, der auf das\nVerzeichnis selbst verweist.
\n","comment":"Doch, in jedem Verzeichnis verweist der .
\n(hier
) Eintrag auf das Verzeichnis selbst. Daher hat auch\njedes Verzeichnis mindestens einen nlink
(Anzahl\nVerweise auf diesen Inode) von 2, weil es von sich selbst und vom\nOberverzeichnis verwiesen wird (Ausnahme, das Root-Verzeichnis\n/
, wo .
und ..
beides Verweise\nauf sich selbst sind).
Ja, weil diese Informationen im Inode gespeichert werden unabhängig\nvom Pfad, und nicht im Verzeichnis. Würde es im Verzeichnis\ngespeichert sein, dann könnte man für jede Instanz einer\nDatei in einem Verzeichnis verschiedene Zugriffsrechte vergeben. Weil\naber ein Verzeichnis nur eine Abbildung von Datei-Namen im Verzeichnis\nzu Inodes sind, ist das nicht möglich.
\n","option":"Für Zugriff über verschiedene Hard links auf die selbe Datei gelten\nidentische Zugriffsrechte.
\n"}],"id":"LvMVnMSGtuKyBqwalmUFYQ","source":"2020-08","question":"Welche der folgenden Aussagen über UNIX-Dateisysteme ist richtig?
\n","multiple":false},{"options":[{"correct":false,"comment":"Nein, es ist das einem nachrangigen Prozess den Vorzug gegenüber\neinen vorrangigen Prozess gibt
(Woschglossar).
Das Phänomen der Prioritätsumkehr hungert niedrigpriore Prozesse\naus.
\n"},{"comment":"Ja, siehe Woschglossar:
\n\n\n","option":"Im Ergebnis behält ein Prozess niedriger Priorität den Prozessor,\nobwohl ein Prozess höherer Priorität darauf wartet, den Prozessor\nzugeteilt zu bekommen. Die Ursache dafür ist möglicherweise eine zuvor\ngeschehene Prioritätsverletzung bei der Zuteilung eines Betriebsmittels\nan einen darauf wartenden Prozess
\n
Ein hochpriorer Prozesse muss eventuell auf ein\nBetriebsmittel warten, das von einem niedrigprioren Prozess exklusiv\nbenutzt wird. Der niedrigpriore Prozess kann das\nBetriebsmittel jedoch wegen eines mittelhochprioren Prozesses\nnicht freigeben (Prioritätenumkehr).
\n","correct":true},{"option":"Eine prioritätenbasierte Auswahlstrategie arbeitet sehr ineffizient,\nwenn viele Prozesse im Zustand bereit sind.
\n","comment":"Nein, die Effizienz einer Auswahlstrategie sollte nicht\nvon der Anzahl an Prozessen welche Warten abhängen.
\n","correct":false},{"comment":"Nein, weil eine Priroritätsebene eine andere nicht\ndominiert, sondern nur bevorzugt behandelt wird.
\n","option":"Prioritätenbasierte Auswahlstrategien führen zwangsläufig zur\nAushungerung von Prozessen, wenn mindestens zwei verschiedene\nPrioritäten vergeben werden.
\n","correct":false}],"id":"sSElBhbeANl/4z0JPfVQsw","question":"Bei einer prioritätengesteuerten Prozessauswahl-Strategie\n(Scheduling-Strategie) kann es zu Problemen kommen. Welches\nder folgenden Probleme kann auftreten?
\n","multiple":false,"source":"2020-08"},{"id":"3f9liDXnpP7nhwFrcIx7dQ","options":[{"option":"Bei kontinuierlicher Speicherung von Daten ist es unter Umständen mit\nenormem Aufwand verbunden, eine bestehende Datei zu vergrößern.
\n","comment":"Ja, weil es unter Umständen das umherbewegen von anderen Dateien,\nbzw. der zu vergrößernden Datei benötigt, damit genug Speicher vorhanden\nist um die Datei kontinuierlich zu speichern.
\n","correct":true},{"correct":false,"comment":"Doch, der Blöcke sind zwar alle gleich groß, können aber\ntrotzdem teilweise nicht komplett gefüllt sein. Außerdem\nbesteht ein Konflikt zwischen den Index-Knoten-Segment und dem\nDatei-Segment, wo wenn die Index-Knoten-Tabelle zu viele kleine Dateien\nenthält, es nicht mehr möglich ist neue Dateien zu\nerstellen, obwohl der Speicher hierfür verfügbar ist.
\n","option":"Bei indizierter Speicherung kann es prinzipbedingt\nnicht zu Verschnitt kommen.
\n"},{"correct":false,"comment":"Nein, indizierter Speicherung hat per se keinen Einfluss darauf wie\nAufwendig die Positionierung für einen beliebigen Datenblock ist. Was\naufwendiger sein kann, ist es mehre Blöcke nacheinander auszulesen,\nwelche nicht konservativ abgespeichert werden müssen.
\n","option":"Im Vergleich zu den anderen Verfahren ist bei indizierter Speicherung\ndie Positionierzeit des Festplatten-Armes beim Zugriff auf\nalle Datenblöcke einer Datei minimal.
\n"},{"correct":false,"comment":"Doch, bspw. benutzen Ext4, Btrfs, NTFS diese.
\n","option":"Extents finden aus Performanzgründen keine Anwendung in\nmodernen Dateisystemen.
\n"}],"source":"2020-08","multiple":false,"question":"Welche der folgenden Aussagen zum Thema persistenter Datenspeicherung\nsind richtig?
\n"},{"multiple":false,"question":"Welche der folgenden Aussagen zum Thema Threads ist richtig?
\n","source":"2020-08","options":[{"option":"Auf Multiprozessorsystemen kann die Umschaltung von\nKern-Threads ohne Mitwirken des Systemkerns erfolgen.
\n","comment":"Nein, bei Kern-Threads ist System erforderlich.
\n","correct":false},{"correct":false,"comment":"Nein, nur weil der Addressraum geteilt wird, muss man\nnicht den gleichen Stack benutzen.
\n","option":"Kern-Threads teilen sich den kompletten Adressraum und verwenden\ndaher den selben Stack.
\n"},{"comment":"Ja, diese ist teil des Programms (üblicherweise der\nProgrammiersprache oder einer Bibliothek), und arbeitet unabhängig von\nder globalen Strategie des Betriebssystems.
\n","option":"Bei User-Threads ist die Schedulingstrategie keine\nFunktion des Betriebssystemkerns.
\n","correct":true},{"correct":false,"option":"Die Umschaltung von Threads muss immer im\nSystemkern erfolgen (privilegierter Maschinenbefehl).
\n","comment":"Nein, findet nur bei Kernel-Threads im Systemkern statt.
\n"}],"id":"D+SokrTTD7N/zAvGKZisrw"},{"options":[{"correct":false,"comment":"Nein, kann für einseitige und mehrseitige\nSynchronisation verwendet werden.
\n","option":"Ein Semaphor kann ausschließlich für mehrseitige\nSynchronisation verwendet werden.
\n"},{"correct":false,"comment":"Nein. Aktives Warten benötigt keine Unterstützung durchs\nBetriebssystem (welches nicht immer gegeben\nist) und vergeudet nicht immer CPU-Zeit\ngegenüber passivem Warten.
\n","option":"Zur Synchronisation eines kritischen Abschnitts ist passives Warten\nimmer besser geeignet als aktives Warten.
\n"},{"correct":false,"option":"Für nicht-blockierende Synchronisationsverfahren ist spezielle\nUnterstützung durch das Betriebssystem notwendig.
\n","comment":"Nein, zum Beispiel mittels CAS, welches durch einen Befehl der\nRecherarchitektur umgesetzt wird, bspw auf x86 CMPXCHG
.
Wahr, im Woschglossar wird es als ADT (Abstrakter Datentyp)\nbeschrieben, dass in einer Programmiersprache wie C oder C++ eingesetzt\nwird, aber in anderer Literatur wird es hauptsächlich als Eigenschaft\neiner Programmiersprache umgesetzt. Als ein Beispiel wo Nebenläufigkeit\nund Synchronisation nicht innerhalb einer Sprache umgesetzt\nwerden, sondern primitiven der Sprache selbst (in C wären Funktionen\nprimitiven, aber die Pthread Funktionalität wird mittels Funktionen\nbereitgestellt) sind ist Ada mit dem Konzept von Tasks.
\n","option":"Monitore sind Datentypen mit impliziten\nSynchronisationseigenschaften.
\n","correct":true}],"id":"ytjkMBgPpEfl2emv1x9jWA","source":"2020-08","multiple":false,"question":"Welche der folgenden Aussagen zum Thema Synchronisation sind\nrichtig?
\n"},{"id":"Fhto2k2IyVhoqw0Mv15+yg","options":[{"comment":"Nein, beispielsweise kann es schneller sein wenn\nnicht gewartet werden muss, weil es einen geringeren\nOverhead hat.
\n","option":"Aktives Warten vergeudet gegenüber passivem Warten immer\nCPU-Zeit.
\n","correct":false},{"option":"Bei verdrängenden Scheduling-Strategien verzögert aktives Warten nur\nden betroffenen Prozess, behindert aber nicht andere.
\n","comment":"Doch, es betrifft auch andere, weil beim Warten die CPU\nimmer noch benutzt wird, biss der Prozess verdrängt\n(preempted) wird. Bei passivem Warten würde der Prozess in den\nZustand blokiert
übergehen, und damit auch die CPU\nnicht mehr benutzen, bis es von anderer Seite wieder als\nbereit
markiert wird.
Aktives Warten darf bei nicht-verdrängenden Scheduling-Strategien auf\neinem Monoprozessorsystem nicht verwendet werden.
\n","comment":"Wahr, weil ansonsten die CPU hoffnungslos monopolisiert wird, und es\nnicht mehr möglich wäre, dass ein anderer Prozess die\nWarte-Bedingung aufhebt (eine Ausnahme hier könnte das Warten auf Daten\nin I/O-Registern sein, welche von externen (physikalischen)\nProzessen
manipuliert werden).
Falsch, die Nachteile bleiben bestehen, es wird nur\nnicht das gesamte System während der Zeitscheibe\nmonopolisiert.
\n","option":"Auf Mehrprozessorsystemen ist aktives Warten unproblematisch und\ndeshalb dem passiven Warten immer vorzuziehen.
\n"}],"multiple":false,"question":"Welche der folgenden Aussagen zum Thema Aktives Warten
ist\nrichtig?
Ein Seitenfehler zieht eine Ausnahmebehandlung nach sich. Diese wird\ndadurch ausgelöst, dass die MMU das Signal SIGSEGV an den aktuell\nlaufenden Prozess schickt.
\n","comment":"Nein, die MMU sendet ein Trap an das BS. Signale werden vom\nBetriebsystem an Prozesse geschickt.
\n","correct":false},{"option":"Seitenfehler können auch auftreten, obwohl die entsprechende Seite\ngerade im physikalischen Speicher vorhanden ist.
\n","comment":"Korrekt, beispielsweise wenn versucht wird auf eine Read-Only Seite\nzu schreiben.
\n","correct":true},{"comment":"Nein, das ist möglich und wird benutzt um die Kosten von\nfork(2)
zu minimieren, werden die gleichen Seiten im\nphysikalischem Speicher in verschiedenen Logischen Addressräumen\neingeblendet (siehe Copy on Write), oder wenn dynamische\nBibliothek, dessen Seiten ausführbare und nicht\nbeschreibbar sind, nur einmal geladen und dann von allen Programmen die\nes benutzen geteilt wird.
Wenn der gleiche Seitenrahmen in zwei verschiedenen\nSeitendeskriptoren eingetragen wird, löst dies einen Seitenfehler aus\n(Gefahr von Zugriffskonflikten!).
\n","correct":false},{"correct":false,"option":"Ein Seitenfehler wird ausgelöst, wenn der Offset in einer logischen\nAdresse größer als die Länge der Seite ist.
\n","comment":"Nein, was diese Frage vertauscht ist Paging und Segmentation, wo beim\nletzteren ein Segmentations-Fehler auftreten kann, wenn der Offset über\ndie Größe des Segments hinausreicht. Beim Paging sind i.d.R.\nalle Seiten gleich groß.
\n"}],"id":"D0zJ6RDd0yA1zKQ8in5Xxg","source":"2020-08","question":"Welche der folgenden Aussagen zum Thema Seitenfehler (page fault) ist\nrichtig?
\n","multiple":false},{"id":"uiYmsVX5fYVQ2jvvOKpbKQ","options":[{"option":"Man lagert regelmäßig länger nicht genutzte Seiten aus\nund trägt sie in einem Freiseitenpuffer ein.
\n","comment":"Nein, der Freiseitenpuffer soll es erleichtern ausgelagerte Seiten\nwieder einzulagern, ohne genau dann dafür eine andere Seite\nbestimmen zu müssen, welche ausgelagert werden soll dafür.\nRegelmäßig dafür Seiten auszulagern würde kontraproduktiv sein,\nweil man dann über einen Punkt der hilfreichen Flexibilität hinaus mehr\nSeiten auslagern würde als notwendig, welche dann nur wieder eingelagert\nwerden müssten.
\n(Siehe auch diesen FSI-Forums\nFaden)
\n","correct":false},{"comment":"Nein, weil meine Zeitmaschine gerade noch kaputt ist. Ich warte aber\nnoch auf eine Lieferung aus der Zunkunft, dann wird das schon wieder\nfunktionieren. Bis dahin ist es aber nicht möglich\nvorherzusehen was das Programm in der Zunkunft machen wird.
\n","option":"Man ermittelt, welche der Seiten eines Prozesses in Zukunft am\nlängsten nicht angesprochen wird und lagert genau diese aus\n(OPT Strategie).
\n","correct":false},{"comment":"Ja, das nennt man Paged\nSegmentation
und ist eine Kombination beider Ansätze.
Man setzt eine Segmentierung in Kombination mit Seitenadressierung\nein.
\n","correct":true},{"correct":false,"comment":"Nein, das würde das Problem nicht lösen weil\nSeitenfehler Traps sind, und daher deterministisch auftreten
\n","option":"Man übergibt Prozesse, die einen Seitenfehler verursachen der\nmittelfristigen Prozesseinplanung, damit sie in nächster Zeit\nnicht wieder aktiv werden.
\n"}],"multiple":false,"question":"Welches der folgenden Verfahren trägt in der Praxis am besten dazu\nbei, die Auswirkungen eines Seitenfehlers zu minimieren?
\n","source":"2020-08"},{"question":"Welche der folgenden Aussagen zum Thema Prozesszustände sind\nrichtig?
\n","multiple":true,"source":"2020-08","id":"O7l9n1Vah0VE2TKxTTYWQg","options":[{"correct":true,"comment":"Ja, da pro laufendem Prozess eine CPU benötigt wird. Es ist dabei gut\nsich daran zu erinnern, dass mache Zustände eher als Konzepte zu\nverstehen sein, und dass dieser Zustand nicht unbedingt\ndurch ein enum
am besten dargestellt wird, sondern durch\ndas Verhalten.
Es können sich maximal genauso viele Prozesse gleichzeitig im Zustand\nlaufend befinden, wie Prozessorkerne vorhanden sind.
\n"},{"comment":"Nein, die schwebenden
Variationen von bereit
und\nblokiert
beziehen sich darauf, dass Teile des virtuellen\nAddressraums nicht bewusst mehr eingelagert sind, was bei\nlaufenden Prozessen nicht sinnvoll wäre.
Im Rahmen der mittelfristigen Einplanung kann ein\nProzess von Zustand laufend in den Zustand schwebend laufend\nwechseln.
\n","correct":false},{"comment":"Nein, nicht direkt, weil Interrupts und deren Behandlung\neinen Prozess nur unterbrechen und dessen Zustand nicht\nverändern. Es ist jedoch möglich, dass die Behandlung des Interrupts\ndieses zur Folge hätte.
\n","option":"Bei Eintreffen eines Interrupts wird der aktuell laufende Prozess für\ndie Dauer der Interrupt-Abarbeitung in den Zustand blockiert\nüberführt.
\n","correct":false},{"option":"Ein Prozess kann nur durch seine eigene Aktivität vom\nZustand laufend in den Zustand blockiert überführt werden.
\n","comment":"Ja, per Definition kann ein Prozess nur durch sein\neigenes Verhalten in den Zustand blockiert
überführt werden.
Wahr, bspw. wenn dem Prozess Aufgrund ein SIGSEGV
\nzugestellt wird, welches in seinen default Einstellungen den betroffenen\nProzess terminiert.
Das Auftreten eines Seitenfehlers kann dazu führen, dass\nder aktuell laufende Prozess in den Zustand beendet überführt wird.
\n","correct":true},{"correct":false,"option":"Greift ein laufender Prozess lesend auf eine Datei zu und der\nentsprechende Datenblock ist nicht im Hauptspeicher\nvorhanden, dann wird der Prozess in den Zustand bereit überführt.
\n","comment":"Nein, er wird in den Zustand blockiert überführt, da er auf\nBetriebsmittel wartet.
\n"},{"comment":"Doch, wenn die CPU abgegeben wird, wird ein Prozess in bereit\nüberfuhrt, da er die CPU nicht hat
und auf\nkeine Betriebsmittel wartet.
Bei kooperativem Scheduling ist kein direkter Übergang vom Zustand\nlaufend in den Zustand bereit möglich.
\n","correct":false},{"correct":true,"comment":"Ja, aber nicht der Prozess selbst (weil dieser\nmuss die V
-Operation durchführen), sondern ein\nandere Prozess welcher mit der P
-Operation auf eine\nSemaphore wartet, welches gerade den Wert 0 hat.
Die V-Operation eines Semaphors kann bewirken, dass ein\nProzess vom Zustand blockiert in den Zustand bereit überführt wird.
\n"}]},{"question":"Wodurch kann Nebenläufigkeit in einem System\nentstehen?
\n","id":"ZPvO/cT4anuoRb8CTLh2ww","multiple":false,"source":"2013-02","options":[{"comment":"Nein, Seitenflattern ist ein Performanz Problem, wobei Zugriffe auf\nden Speicher verlangsamt werden, weil die Seiten im Hauptspeicher durch\npathologische Zugriffe fälschlicherweise ausgelagert werden, auch wenn\ndiese in naher Zukunft gebraucht werden.
\n","option":"durch Seitenflattern
\n","correct":false},{"comment":"Nein, durch langfristiges Scheduling per se sollte keine\nNebenläufigkeits-Probleme entstehen, welche nicht bereits\ngegeben wären durch gewöhnliches
Scheduling. Ansonsten ist die\nGefahr von problematischen, nebenläufigen Ereignissen im kurzfristigem\nScheduling höher, weil dass die Interferenz zwischen Prozessen\nwahrscheinlicher macht
durch langfristiges Scheduling
\n"},{"option":"durch Compiler-Optimierungen
\n","correct":false,"comment":"Nein, es steht zwar einem Übersetzer frei, unter invarianter Semantik\nProgramme zu transformieren, bspw. um verschiedene Optimierungen\n(Performanz, Speicherbedarf, Größe der Ausführbaren Dateien, …)\numzusetzen, aber Nebenläufigkeiten – aus Sicht der Sprache – welche\nnicht in dem Programm per se gegeben waren,\nsollten dadurch nicht auftauchen. Was möglich ist,\nist das Nebenlaufigkeitsprobleme erst wahrscheinlicher werden,\nwenn ein Programm entsprechend beschleunigt wurde.
\n"},{"option":"durch Interrupts
\n","correct":true,"comment":"Ja, eine Unterbrechnungsbehandlung kann ein Programm\n(bspw. das Betriebsystem) an einer ungeeigneten Stelle unterbrechen, und\nDaten überschreiben, welche nach der Rückkehr in das Hauptprogramm ein\ninkonsistenten Zustand bewirken kann. In diesem Sinne ist es\nvergleichbar zu Signalbehahdlungen in Benutzerprozessen. Aus diesem\nGrund müssen Betriebsysteme in kritischen Intervallen Interrupts\ndeaktivieren können, bspw. auf x86 mit den CLI
\n(Clear Interrupt Flag) und und STI
\n(Set Interrupt Flag) Befehlen.
Man unterscheidet zwischen privilegierten und nicht-privilegierten\nMaschinenbefehlen. Welche Aussage ist richtig?
\n","options":[{"comment":"Eigentlich nein, diese werden nicht direkt von\nAnwendungsprogrammen benutzt, sondern sind dem Betriebsystem\nvorenthalten, damit dieses sinnvoll Ressourcen virtualisieren und\nschützen kann. Das schwierige an dieser Frage ist das\ngrundsätzlich
, womit man meinen könnte, dass ein Befehl\nwie syscall
/int
auf x86/x86_64, welches einen\nTrap auslößt, um Systemaufrufe abzusetzen, auch als priviligiert
\nangesehen werden kann.
Privilegierte Maschinenbefehle dürfen in Anwendungsprogrammen\ngrundsätzlich nicht verwendet werden.
\n"},{"comment":"Nein, es würde zu einer syncrhonen Programmunterbrechung\nführen, weil diese direkt durch den Versuch den Befehl zu interpretieren\nausgelöst werden würde.
\n","correct":false,"option":"Die Benutzung eines privilegierten Maschinenbefehls in einem\nAnwendungsprogramm führt zu einer asynchronen Programmunterbrechung.
\n"},{"option":"Mit nicht-privilegierten Befehlen ist der Zugriff auf Geräteregister\ngrundsätzlich nicht möglich.
\n","correct":null,"comment":"Abhängig davon, was man unter grundsätzlich
versteht; auf\nIntel CPUs werden hierzu gesonderte Befehle benutzt, aber\ngrundsätzlich könnte eine Rechnerarchitektur auch durch\nSpeicherschutz einen nicht-privilegierten Prozess daran hindern mittels\nnicht-priviligierten Befehlen auf Geräteregister zuzugreifen.
Ja, hier muss an das Multilevel Machines
Model\nvon Tannenbaum\ndenken, wo jede Schicht der Implementierung zwischen einer\nproblemorientierte Programmiersprachenebene und digitale\nLogikebene als Interpretation oder Implementierung einer Virtuellen\nMachine angesehen wird.
Privilegierte Maschinenbefehle können durch Betriebssystemprogramme\nimplementiert werden.
\n"}]},{"options":[{"comment":"Nein, das Betriebssystem gibt den Befehl selbst nicht an\ndie CPU weiter, und überprüft daher auch nicht ob die\nAdressen gültig seien.
\n","correct":false,"option":"Das Betriebssystem erkennt die ungültige Adresse bei der Weitergabe\ndes Befehls an die CPU (partielle Interpretation) und leitet eine\nAusnahmebehandlung ein.
\n"},{"correct":false,"comment":"Nein, der Übersetzer kann sich nicht\nimmer sicher sein wo die problematische Code-Stellen sind,\nund generiert (für C) auch nicht den Code um den Fehler\nauszulösen.
\n","option":"Der Compiler erkennt die problematische Code-Stelle und generiert\nCode, der zur Laufzeit bei dem Zugriff einen entsprechenden Fehler\nauslöst.
\n"},{"correct":true,"comment":"Ja, wenn die MMU die Seite nicht auflösen kann, dann\nwird es der CPU ein Trap zustellen und löst damit eine synchrone\nUnterbrechung im Programm aus.
\n","option":"Beim Zugriff über den Zeiger muss die MMU die\nerforderliche Adressumsetzung vornehmen, erkennt die ungültige Adresse\nund löst einen Trap aus.
\n"},{"comment":"Da der Fehler direkt bedingt ist durch das Verhalten des Programms,\nwürde es sich hier um ein Trap
und kein Interrupt
\n(unvorhersebar) handeln.
Der Speicher schickt an die CPU einen Interrupt. Hierdurch wird das\nBetriebssystem angesprungen, das den gerade laufenden Prozess mit einem\nSegmentation fault
-Signal unterbricht.
Was passiert, wenn Sie in einem C-Programm über einen ungültigen\nZeiger versuchen auf Speicher zuzugreifen?
\n","source":"2023-07","multiple":false,"id":"0EXLEc6+2nBny6VjZlYvxQ"},{"multiple":false,"id":"5R68BUY+hb/J5jPsX0CK8w","options":[{"option":"Bei indizierter Speicherung von Dateien ensteht externer Verschnitt\nauf der Platte.
\n","comment":"Nein, weil für Dateien ganze Blöcke vergeben und herumgeschoben\nwerden können, womit externer Verschnitt vermieden wird, weil es\nnicht dazu kommen kann, dass es lücken gibt die zu\nklein
wären für eine Datei.
Ja, weil der Lese-Schreib-Kopf der Festplatte schneller auf\nlokal-nahe Daten in der gleichen Leserichtung zugreifen kann, ist ist\nder Zugriff auch dementsprechend schneller.
\n","correct":true,"option":"Festplatten eignen sich besser für sequentielle als für wahlfreie\nZugriffsmuster.
\n"},{"correct":false,"comment":"Nein, obwohl der Datei Name für ein fileID
im MFT gespeichert\nist, wird es auch in Verzeichnissen gespeichert und erlaubt es ähnlich\nzu einem UFS-Inspiriertem Datei-System, mehrere Namen auf ein\nVolume
zu definieren.
Eine Datei in einem Winows-NT-Dateisystem kann nur genau\neinen Dateinamen haben, da dieser in ihrem Master-File-Table-Eintrag\ngespeichert ist.
\n"},{"comment":"Nein, Verschleis hat nichts mit der technischen Umsetzung des\nSpeichermediums zu tun.
\n","correct":false,"option":"Da SSDs ohne mechanische Komponenten auskommen, gibt es auch durch\nhäufige Schreiboperationen keinen Verschleis.
\n"}],"question":"Welche der folgenden Aussagen zum Thema Dateispeicherung sind\nrichtig?
\n","source":"2023-07"},{"id":"gzS7E3ZRG3h9kO7ruPOyjg","multiple":false,"source":"2023-07","question":"Welches Signal wird bei einer Speicherschutzverletzung versendet?
\n","options":[{"option":"SIGKILL
\n","correct":false,"comment":"signal.h(7p)
sagt Kill (cannot be caught or\nignored)
.
SIGSEGV
\n","comment":"signal.h(7p)
sagt Invalid memory reference
.
signal.h(7p)
sagt Termination signal
.
SIGTERM
\n"},{"option":"SIGABORT
\n","comment":"signal.h(7p)
sagt Process abort signal
.
Man unterscheidet kurz-, mittel- und langfristige Prozesseinplanung.\nWelche Aussage hierzu ist richtig?
\n","options":[{"option":"Wenn ein Prozess auf einen Seitenfehler (page fault) trifft, wird er\nim Rahmen der kurzfristigen Einplanung in den Zustand schwebend\nbereit
überführt, weil er ja unmittelbar nach dem Einlagern der\nSeite wieder weiterlaufen kann.
Nein, das wäre mittelfristige Prozesseinplanung. Ein Prozess im\nZustand schwebend bereit kann keine gerade\neingelagerten Seiten haben, was nicht der Fall sein kann,\nwenn er zuvor im Zustand bereit sein musste.
\n","correct":false},{"correct":false,"comment":"Nein, nicht immer, weil es sein\nkann, dass die Seite nicht eingelagert werden\nkann und daher der Prozess in den finalen Zustand beendet\nübergeht.
\n","option":"Wenn ein Prozess auf einen Seitenfehler (page fault) trifft, wird er\nim Rahmen der kurzfristigen Einplanung immer in den Zustand\nblockiert
überführt, bis die Seite eingelagert wurde.
Wenn der Adressraum eines laufbereiten Prozesses aufgrund von\nSpeichermangel ausgelagert wird (swap-out
), wird der Prozess im\nRahmen der mittelfristigen Einplanung in den Zustand blockiert
\nüberführt, bis die Daten wieder eingelagert werden.
Nein, der Prozess ist weiterhin laufbereit, nur eben schwebend\nbereit.
\n","correct":false},{"option":"Wenn ein Prozess auf Daten von der Platte warten muss, wird er in den\nZustand blockiert
versetzt.
Ja, Prozess blockiert, bis ihm Betriebsmittel zugestellt werden\nkönnen.
\n"}],"id":"g0GeL8aIg+3Ms1wdLgD8NA","multiple":false},{"multiple":false,"id":"6kIdvG0VJdUWvq+pVxboAA","options":[{"option":"Zur Implementierung einer Schlossvariable mit aktivem Warten ist\nkeine Unterstützung durch das Betriebssystem notwendig.
\n","correct":true,"comment":"Ja, kann man zum Beispiel mit CAS umsetzen.
\n"},{"comment":"Nein, vergeudet nicht unbedingt Zeit. Spezifisch dann,\nwenn das einbinden des Schedulers, um eben das passive Warten\numzusetzen, mehr Aufwand benötigen würde, als aktiv zu warten.
\n","correct":false,"option":"Aktives Warten vergeudet gegenüber passivem Warten immer\nCPU-Zeit.
\n"},{"option":"Bei verdrängenden Scheduling-Strategien verzögert aktives Warten nur\nden betroffenen Prozess, behindert aber nicht andere
\n","correct":false,"comment":"Nein, bei passivem Warten würden keine weiteren Prozesse\nverzögert werden, weil der Prozess im Blockieren Zustand ist. Bei\naktivem Warten ist der Prozess bereit und muss\nimmer wieder eingelagert werden um aktiv nach der\nAbbruchbedingung zu prüfen, was den Durchsatz des System verzögert.
\n"},{"correct":false,"comment":"Nein, auf keinen Fall, weil man auf einem kooperativem\nMonoprozessor-System die CPU monopolisieren würde, und wenn man auf eine\nBedingung von einem anderem Faden warten würde, würde man sich in einem\nlive-lock verfangen.
\n","option":"Aktives Warten sollte bei einer nicht-verdrängenden\nScheduling-Strategie auf einem Monoprozessorsystem dem passiven Warten\nvorgezogen werden.
\n"}],"source":"2023-07","question":"Welche Aussage zum Thema Aktiven Warten
ist richtig?
Verdrängende Prozesseinplanung bedeutet, dass das Eintreten des\nerwarteten Ereignisses unmittelbar die Einlastung des wartenden\nProzesses bewirkt.
\n","comment":"Nein, die Verdrängung
bezieht sich auf die Tatsache, dass\neinem Prozess die CPU entzogen werden kann, ohne dessen Unwilling\n(yield
).
Ein Prozess kann sich in realen Systemen\nnie im Zustand beendet befinden, da bei seiner Terminierung\nsämtliche Betriebsmittel freigegeben werden und damit auch der Prozess\nselbst verschwindet.
\n","correct":false,"comment":"Nein, das ist der Zombie Zustand
, es verbleibt auf einem Unix\nSystem darin bis waitpid o.ä. benutzt wird.
Ja, Prozesse können gestoppt beendet werden, unabhängig davon ob\ndiese gerade laufen oder nicht (denke an\nkill -9
).
Prozesse im Zustand blockiert oder bereit können unmittelbar in den\nZustand gestoppt überführt werden.
\n"},{"option":"Einplanungsverfahren lassen sich in drei Kategorien einteilen:\nfedergewichtig, leichtgewichtig und schwergewichtig.
\n","correct":false,"comment":"Nein, das sind Prozess-Arten.
\n"},{"option":"Ein Prozess, der sich im Zustand laufend befindet, kann\nnicht direkt in den Zustand schwebend blockiert überführt\nwerden.
\n","correct":true,"comment":"Ja, weil das im Kontext der mittelfristigen Planung geschehen würde,\nwo der Speicher eines bereits blokierten Prozesses ausgelagert werden\nwürde.
\n"},{"correct":true,"option":"Prozesse im Zustand gestoppt sind der langfristigen Einplanung\nzuzuordnen.
\n"},{"comment":"Ja, mittelfristige Planung wird im Gegensatz zur kurzfristigen\nPlanung durch das Vorhandensein des Speichers von Prozessen im\nHauptspeicher.
\n","correct":true,"option":"Für die mittelfristige Einplanung muss das\nBetriebssystem die Umlagerung (engl. swapping) von kompletten Programmen\nbzw. logischen Adressräumen unterstützen.
\n"},{"option":"Ein Prozess im Zustand erzeugt kann sich selbst durch\ndie Ausführung des Systemaufrufes exec()
in den Zustand\nbereit überführen.
Nein, um exec
auszuführen, müsste der Prozess ja bereits\nim Zustand laufend sein.
Welche der folgenden Aussagen zum Thema Einplanung sind richtig?
\n","multiple":true,"id":"pHfuMspDDx1oMiGMNilAIA"},{"multiple":false,"question":"Wie funktioniert Adressraumschutz durch Eingrenzung?
\n","options":[{"comment":"Nein, das ist nicht was mit Eingrenzung
gemeint\nist. Ansonsten wäre es recht umständlich, die Lücken im physikalischem\nSpeicher welche für Memory-Mapped I/O, den BIOS, PCI, etc. für eine\ndynamische Anzahl an Prozessen auszunutzen.
Der Lader positioniert Programme immer so im\nArbeitsspeicher, dass unerlaubte Adressen mit nicht-existierenden\nphysikalischen Speicherbereichen zusammenfallen.
\n"},{"correct":false,"option":"Begrenzungsregister legen einen Adressbereich im logischen Adressraum\nfest, auf den alle Speicherzugriffe beschränkt werden.
\n","comment":"Nein, bei Eingrenzung ist der Addressbereich im physikalischen\nAdressraum.
\n"},{"option":"Begrenzungsregister legen einen Adressbereich im physikalischen\nAdressraum fest, auf den alle Speicherzugriffe beschränkt\nwerden.
\n","correct":true,"comment":"Ja, Bei Eingrenzung, bzw. Einfriedung
wird ein Teil des\nphysikalischen Speichers mittels Grenzregistern überprüft, noch bevor\nder Addressbus angeprochen wird.
Nein, das umschreibt Segmentierung.
\n","option":"Jedes Programm bekommt zur Ladezeit mehrere Wertepaare aus Basis- und\nLängenregistern zugeordnet, die die Größe aller Segmente des darin\nlaufenden Prozesses festlegen.
\n","correct":false}],"source":"2016-02","id":"PLSBGNIvcV6w9O/lIzPO5A"},{"source":"2016-02","options":[{"comment":"Ja, die Ressource (Daten von der Festplatte) waren nicht\nverfügbar, und waren daher Grund weshalb der Prozess im Blokiertem\nZustand war. Man geht nicht direkt von Blokiert
nach\nLaufend
über, sondern macht den Umweg über Bereit
, d.h.\nder Prozess ist in der Bereitliste vom Scheduler eingeordnet.
Der Prozess hat auf das Einlesen von Daten von der Festplatte\ngewartet, die nun verfügbar sind.
\n","correct":true},{"comment":"Ich glaube das sollte falsch sein, weil ein Prozess als\nsolches nicht aufgrund von Speichermangel in\nden Hintergrundspeicher ausgelagert wird.
\n","correct":null,"option":"Ein Prozess, der zu einem früheren Zeitpunkt aufgrund von\nSpeichermangel auf den Hintergrundspeicher ausgelagert wurde, ist nun\nwieder eingelagert und kann weiterlaufen.
\n"},{"option":"Ein anderer Prozess wurde vom Betriebssystem verdrängt und der\nerstgenannte Prozess wird nun auf der CPU eingelastet.
\n","correct":false,"comment":"Nein, dieser erstgennante Prozess wäre Bereit
gewesen, und\nwürde nun im Zustand Laufend
sein. Der andere Prozess wäre den\nUmgekehrten weg, von Laufend
nach Bereit
übergegangen\n(diesem Fehlt nichts außer die CPU).
Es ist kein direkter Übergang von blockiert nach bereit möglich.
\n","correct":false,"comment":"Nein, es ist kein Überganz von Blokiert
nach Laufend
\nmöglich, aber ein blockierter Prozess kann in Bereit
\nüberführt werden, sobald der Grund für das Blockiertsein aufgelöst\nwurde.
Ein Prozess wird vom Zustand blockiert in den Zustand bereit\nüberführt. Welche Aussage passt zu diesem Vorgang?
\n","id":"VC2IM0Xrq49fmnVGjmouKw"},{"multiple":false,"question":"Wodurch kann es zu Seitenflattern kommen?
\n","options":[{"comment":"Nein, in diesem Fall würde es nur zu einer Auslagerung von Seiten\nkommen, was aber nicht zwingend Seitenflattern
\nbedingen würde.
Wenn die Zahl der residenten Seiten die Größe des physikalischen\nSpeichers überschreitet.
\n","correct":false},{"comment":"Nein, Seitenflattern bezeichnet das pathologische Phänomen, wenn die\nSeitenumlagerungsstrategie eine Menge von Seiten zu häufig Umlagern\nmuss, und damit den Zugriff auf den Speicher verlangsamt. Es an sich hat\nnichts mit dem Dateisystem zu tun.
\n","option":"Durch Programme, die eine Defragmentierung auf der Platte\ndurchführen.
\n","correct":false},{"comment":"Ja, das ist die Definition vom Begriff. Siehe im Wosch Glossar, den\nEintrag Flattern
.
Wenn ein Prozess zum Weiterarbeiten immer gerade die\nSeiten benötigt, die durch das Betriebssystem im Rahmen einer globalen\nErsetzungsstrategie gerade erst ausgelagert wurden.
\n"},{"option":"Wenn zu viele Prozesse im Rahmen der mittelfristigen Einplanung auf\nden Hintergrundspeicher ausgelagert wurden (swap-out).
\n","correct":false,"comment":"Nein, der Begriff ist unabhängig von der Planungsstrategie zu\nverstehen.
\n"}],"source":"2016-02","id":"MvWl3V4D1Jd4RcN/zeA1Vw"},{"source":"2016-02","options":[{"comment":"Nein, Traps können auch durch Systemaufrufe (Quasi-Nachrichten an das\nBetriebsystem) oder durch fehlende aber einlagerbare Speicherseiten\nausgelöst werden.
\n","option":"Die Behandlung eines Traps führt immer zur Beendigung\ndes unterbrochenen Programms, da Traps nur durch schwerwiegende Fehler\nausgelöst werden.
\n","correct":false},{"comment":"Nein, Systemaufrufe treten immer dann deterministisch\nauf, wenn der entsprechende Maschinenbefehl (syscall
auf ,\nint
auf x86, ecall
of RISC-V).
Da das Betriebssystem nicht vorhersagen kann, wann ein\nBenutzerprogramm einen Systemaufruf absetzt, sind Systemaufrufe als\nInterrupts zu klassifizieren.
\n","correct":false},{"option":"Bei der mehrfachen Ausführung eines unveränderten Programms mit\ngleicher Eingabe treten Traps immer an den gleichen Stellen\nauf.
\n","correct":true,"comment":"Ja, das folgt aus dem Determinismus von Traps.
\n"},{"option":"Da Interrupts in keinem Zusammenhang mit dem unterbrochenen Programm\nstehen, muss der Prozessorstatus des unterbrochenen\nProgramms während der Behandlung nicht speziell gesichert\nwerden.
\n","correct":false,"comment":"Doch, weil die Behandlung des Interrupts den Prozessorstatus durchaus\nbeeinflusst, und damit es aber das unterbrochenen Programm\nnicht direkt verändert (es braucht ja nur für die\nBehandlung die CPU für eine kurze Zeit), wird vor der Behandlung der\nZustand des Prozessors gespeichert – bspw. in dem dieser auf dem Stack\nkopiert wird, dann die Unterbrechungsroutine eingeleitet wird, und\ndanach wiederhergestellt wird.
\n"}],"question":"Man unterscheidet bei Programmunterbrechungen zwischen Traps und\nInterrupts. Welche Aussage dazu ist richtig?
\n","multiple":false,"id":"AKlQe/PMhYE14LdoakHBbA"},{"options":[{"option":"Das Arbeitsverzeichnis eines Prozesses definiert die Wurzel des\nhierarchisch organisierten Namensraums in einem Dateisystem.
\n","correct":false,"comment":"Nein, die Wurzel des Namensraums ist (zunächst, siehe\nchroot(2)
) fest und unabhängig von Prozessen und ihren\nArbeitsverzeichnissen.
In einem hierarchisch organisierten Namensraum dürfen gleiche Namen\nin unterschiedlichen Kontexten enthalten sein.
\n","comment":"Ja, so kann es sowohl /home/alice/shopping
\nund /home/bob/shopping
geben. Nur in einem Verzeichnis darf\nein Name einmal vergeben werden.
Ein Benutzer hat immer nur einen Kontext, unabhängig\ndavon ob der Namensraum flach ist oder nicht.
\n","option":"Flache Namensräume erlauben pro Benutzer nur einen Kontext.
\n","correct":null},{"correct":false,"option":"Hierarchische Namensräume werden erzeugt, indem man in einem Kontext\nsymbolische Verweise auf Dateien einträgt.
\n","comment":"Nein, hierarchische Namensräume können auch nur von Hardlinks\naufgespannt werden (wie es der Fall war bevor BSD diese für UNIX\nimplementiert hat).
\n"}],"source":"2016-02","question":"Namensräume dienen u. a. der Organisation von Dateisystemen. Welche\nAussage ist richtig?
\n","multiple":false,"id":"YSRglhzLlSkEGTj9lj+s/A"},{"question":"Welche Seitennummer und welcher Versatz gehören bei einstufiger\nSeitennummerierung und einer Seitengröße von 2048 Bytes zu folgender\nlogischer Adresse: 0xba1d
Nein, weil (0xb << 11) | 0xa1d = 0x5a1d
.
Seitennummer 0xb
, Versatz 0xa1d
.
Seitennummer 0x17
, Versatz 0x21d
.
Ja, weil (0x17 << 11) | 0x21d = 0xba1d
, oder\nalternativ:
(0xba1d & (2048-1)) = 0x21d\n (0xba1d & ~(2048-1)) >> 11 = 0x17
\nDie Idee hier ist, dass man mit einer Seitengröße von 2048 Byte mit\n11 Bit adressieren kann. Die ersten 11 Byte von
\n 0b1011101000011101 = 0xba1d
\nsind
\n 0b01000011101 = 0x21d
\nund damit bleiben für die Page Nummer nur noch
\n 0b10111 = 0x17
\n"},{"correct":false,"option":"Seitennummer 0xba
, Versatz 0x1d
.
Nein, weil (0xba << 11) | 0x1d = 0x5d01d
.
Seitennummer 0x2e
, Versatz 0x21d
.
Nein, weil (0x2e << 11) | 0x21d = 0x1721d
.
Nein, mehrere Prozessinstanzen können das gleiche Programm ausführen,\nzumindest auf einem UNIX™ System, welches keine solchen\nEinschänkungen vorsieht.
\n","correct":false,"option":"Ein Programm kann immer nur von einem\nProzess gleichzeitig ausgeführt werden.
\n"},{"option":"Das Programm ist der statische Teil (Rechte, Speicher, etc.), der\nProzess der aktive Teil (Programmzähler, Register, Stack).
\n","correct":false,"comment":"Nein, der Speicher ist auch aktiv
an der Ausführung beteiligt,\naber ansonsten ist auch die Begriffsunterscheidung hier (für mich)\nnicht klar.
Nein, der Begriff Threads
(Fäden) verstanden als\nLeichtgewichtiger Prozess
, beschreibt einen Ausführungsstrang,\nwelches mit anderen Threads in einem Prozess den gleichen\nSpeicherraum teil. Jedenfalls nennt man ein Programm weder Prozess oder\nThreads (Kategorien-Fehler), sondern ein Programm wird in bzw. von einem\nProzess oder in einem Thread ausgeführt.
Wenn ein Programm nur einen aktiven Ablauf enthält, nennt man diesen\nProzess, enthält das Programm mehrere Abläufe, nennt man diese\nThreads.
\n","correct":false},{"option":"Ein Prozess ist ein Programm in Ausführung - ein Prozess\nkann aber während seiner Lebenszeit auch mehrere\nverschiedene Programme ausführen.
\n","correct":true,"comment":"Ja, das ist die Definition. Ein Prozess kann sein\nProgramm Mittels eines exec
Systemaufrufs auswechseln.
Man unterscheidet die Begriffe Programm und Prozess. Welche der\nfolgenden Aussagen zu diesem Themengebiet ist richtig?
\n","multiple":false,"id":"B7f+c5P5Sh1hltDZoan62w"},{"id":"+gRN3qLn/d5dYXDV23Gvqg","source":"2016-02","options":[{"option":"Die Ersetzungsstrategie MIN ist in der Praxis nur schwer\nrealisierbar, weil Wissen über das zukünftige Verhalten des\nGesamtsystems notwendig ist.
\n","correct":true,"comment":"Ja, MIN (oder B0
, OPT
) müsste die Referenzfolge zuvor\nwissen; der Ansatz ist meist nur zum Vergleich von Strategien\nbrauchbar
.
Bei der Verwendung von globalen Seitenersetzungsstrategien sind\nSeitenfehler vorhersagbar bzw. reproduzierbar.
\n","comment":"Nein, weil bei einer globalen Ersetzungsstrategie verhällt sich ein\nSeitenfehler wie ein Interrupt, weil es nicht\ndirekt vorhersehbar ist anhand vom Verhalten des eigenen Programms.
\n"},{"comment":"Nein, mit free()
wird im Freispeicher ein\nreservierte Speicherbereich zurück gegeben. Es ist darüber hinaus kein\nSystemaufruf, sondern verwaltet Speicher im Userspace.
Mit dem Systemaufruf free()
kann eine\nSpeicherseite in den Freiseitenpuffer eingefügt werden.
Die Ersetzungsstrategie LRU ersetzt die am längsten\nnicht mehr referenzierte Seite.
\n","correct":true,"comment":"Ja, da Akronym LRU – Least Recently Used – deutet darauf\nhin.
\n"},{"option":"Bei der Verwendung von lokalen Seitenersetzungsstrategien sind\nSeitenfehler vorhersagbar bzw. reproduzierbar.
\n","correct":true,"comment":"Ja, weil bei einer lokalen Ersetzungsstrategie ist ein Seitenfehler\nein Trap.
\n"},{"comment":"Nein, FIFO (First In, First Out) kann\nimmer gleich bestimmen welche Seite zu ersetzen ist,\nwährend man bei LRU (Least Recently Used) erst berechnen müsste\nwelche Seite am längsten nicht benutzt wurde.
\n","option":"Die Ersetzungsstrategie LRU benötigt im Vergleich zu FIFO\nimmer weniger Versuche, bis eine zu ersetzende Seite\ngefunden werden kann.
\n","correct":false},{"option":"Lokale Seitenersetzungsstrategien wählen die zu ersetzende Seite\nimmer aus der Menge aller im System verfügbaren\nSeitenrahmen aus.
\n","correct":false,"comment":"Nein, bei einer lokalen Ersetzungsstrategien, ist ein Prozess selbst\ndafür verantwortlich seine eigenen Seiten zu ersetzen.
\n"},{"correct":true,"option":"Bei der Ersetzungsstrategie LFU wird die am seltensten referenzierte\nSeite aus dem Speicher verdrängt.
\n","comment":"Ja, das Akronym – Least Frequently Used – deutet darauf\nhin.
\n"}],"multiple":true,"question":"Welche der folgenden Aussagen zum Thema Seiteneinlagerungs- und\nSeitenersetzungsstrategien ist richtig?
\n"},{"options":[{"comment":"Wenn kein Hardlink
auf eine Datei existiert, dann löscht das\nDateisystem die Datei. Daher muss auf jede\nexistierende Datei mindestens ein Verweis existieren.
Für jede reguläre Datei existiert mindestens ein\nHard-Link im selben Dateisystem.
\n","correct":true},{"comment":"Symbolic Links sind nur verweise auf Dateipfade, wobei die Datei\nhinter dem Dateipfad nichts von diesem Verweis wissen muss. Es ist ja\nauch möglich auf eine nicht-existierende Datei zu verweisen.
\n","option":"Wird der letzte Symbolic Link auf eine Datei gelöscht, so wird auch\ndie Datei selbst gelöscht.
\n","correct":false},{"comment":"Nein, weil Symbolic Links nur Pfade sind, welche das Betriebsystem\ntransparent auflöst, wenn man versucht auf die Datei zuzugreifen, aber\ndiese nichts über das tatsächliche System wissen. Bei Hard-Links ist das\nhingegen nicht der Fall, weil diese die gleiche\nInode-Nummer teilen müssen, was von Datei-System abhängig ist.
\n","option":"Ein Symbolic Link kann nicht auf Dateien\nanderer Dateisysteme verweisen.
\n","correct":false},{"comment":"Hard-Links können auf beides verweisen, nur ist es mit dem\nlink
(bzw. dem ln
Befehl) Systemaufruf dem\nBenutzer nicht erlaubt selbst Verweise auf Verzeichnisse zu\nerstellen. Damit wird sichergestellt, dass der Datei-Baum, der durch\nHard-Link aufgespannt wird, nicht zu einem Graphen\ndegeneriert, was Probleme bereiten würde für Werkzeuge wie\nfind
.
Ein Hard Link kann nur auf Verzeichnisse verweisen,\nnicht jedoch auf Dateien.
\n","correct":false}],"source":"2022-07","id":"pX9XqDJv7cfeIjfHVoUkYw","question":"In einem UNIX-UFS-Dateisystem gibt es symbolische Namen/Verweise\n(Symbolic Links) und feste Links (Hard Links) auf Dateien. Welche\nAussage ist richtig?
\n","multiple":false},{"source":"2022-07","options":[{"comment":"Nein, ein Trap kann auch durch eine nicht\neingelagerte Seite (wo dann mit der MMU versucht wird diese einzulagern,\nund dann das Programm weiter läuft) oder durch einen Systemaufruf\nausgelöst werden.
\n","option":"Ein Trap signalisiert einen schwerwiegenden Fehler und führt deshalb\nimmer zur Beendigung des unterbrochenen Programms.
\n","correct":false},{"comment":"Nein, weil ein Interrupt nichts mit dem Programm zu tun hat, und\ndaher dieses nicht (direkt) abbrechen sollte.
\n","correct":false,"option":"Ein durch einen Interrupt unterbrochenes Programm darf je nach der\nInterruptursache entweder abgebrochen oder fortgesetzt werden.
\n"},{"comment":"Ja. Dazu muss man sich an die Definition vom Programm\nerinnern:
\n\n\nFestlegung einer Folge von Anweisungen für einen Prozessor, nach der\ndie zur Bearbeitung einer (durch einen Algorithmus wohldefinierten)\nHandlungsvorschrift erforderlichen Aktionen stattfinden sollen.
\n
darunter kann auch das Hauptprogramm
vom\nBetriebsystem verstanden werden, welches von einem Trap-Handler (ein\nweiteres Programm) unterbrochen wird. Sollten beide (möglicherweise auf\nverschiedenen Kernen) versuchen synchronisierte Operationen auszuführen,\nkönnen diese sich gleichzeitig verklemmen.
Obwohl Traps immer synchron auftreten, kann\nes im Rahmen ihrer Behandlung zu Wettlaufsituationen mit dem\nunterbrochenen Programm kommen.
\n"},{"comment":"Nein, ein Systemaufruf ist ein Trap, weil diese deterministisch bei\nder Ausführung auftreten, bspw. wenn je nach Rechenarchitektur ein syscall
\n(x86_64) Befehl ausgeführt wird.
Ein Systemaufruf im Anwendungsprogramm ist der Kategorie Interrupt\nzuzuordnen.
\n"}],"multiple":false,"question":"Ausnahmesituationen bei einer Programmausführung werden in die beiden\nKategorien Trap und Interrupt unterteilt. Welche der folgenden Aussagen\nist zutreffend?
\n","id":"s9HyM3B/MD5PhaoYevb9CQ"},{"id":"1S+Cg56zhEhm0Jv5VhZnHA","question":"Welche Aussage zum Thema Systemaufrufe ist richtig?
\n","multiple":false,"options":[{"comment":"Nein, Systemaufrufe sind die Schnittstelle, die das Betriebssystem\nBenutzerprozessen zur Verfügung stellt, um privilegierte Operationen,\nkontrolliert ausführen zu lassen. Benutzerprozesse können (u. a. aus\nSicherheitsgründen) das Betriebssystem nicht in dieser\nHinsicht verändern.
\n","correct":false,"option":"Durch die Bereitstellung von Systemaufrufen, kann ein\nBenutzerprogramm das Betriebssystem um eigene Funktionen erweitern.
\n"},{"comment":"Ja, möchte ein Programm z. B. eine Datei lesen, so sendet es\nnicht selbst z. B. NVMe-Befehle an den Speicher\n(privilegierte Operation, könnte zum Verlust aller Daten führen),\nsondern beauftragt das Betriebssystem (im Fall von POSIX mit\nread(2)
), den Dateiinhalt zu lesen.
Mit Hilfe von Systemaufrufen kann ein Benutzerprogramm\nprivilegierte Operationen durch das Betriebssystem ausführen lassen, die\nes im normalen Ablauf nicht selbst ausführen dürfte.
\n"},{"correct":false,"option":"Die Bearbeitung eines Systemaufrufs findet immer im\nselben Adressraum statt, aus dem heraus der Systemaufruf abgesetzt\nwurde.
\n","comment":"Nein, bei der Bearbeitung eines Systemaufrufs im Systemkern\n(kernel) ist der kernel address space, der\nnicht für Benutzerprozesse sichtbar ist, verfügbar.
\n"},{"comment":"Nein, Benutzerprozesse verwenden Systemaufrufe, um Operationen\nauszuführen, für die sie selbst nicht die Privilegien\nbesitzen.
\n","correct":false,"option":"Benutzerprogramme dürfen keine Systemaufrufe absetzen,\ndiese sind dem Betriebssystem vorbehalten.
\n"}],"source":"2022-07"},{"question":"Bei der Behandlung von Ausnahmen (Traps oder Interrupts)\nunterscheidet man zwei Bearbeitungsmodelle. Welche Aussage hierzu ist\nrichtig?
\n","multiple":false,"id":"CZj7ZkKeT6XymSpp11A6Tw","options":[{"comment":"Nein, der Interrupt wird vom Betriebssystem abgefangen. Dieses\nkann dann einem Prozess ein Signal zustellen. Dieser\nmuss jedoch nicht unbedingt der gerade\nlaufende Prozess sein (Auch Hintergrundprozesse (daemons)\nkönnen sich im Zustand laufend
befinden).
Nach dem Beendigungsmodell werden Interrupts bearbeitet. Gibt man z.\nB. CTRL-C unter UNIX über die Tastatur ein, wird ein Interrupt-Signal an\nden gerade laufenden Prozess gesendet und dieser dadurch beendet.
\n"},{"correct":false,"option":"Das Beendigungsmodell sieht das Herunterfahren des Betriebssystems im\nFalle eines schwerwiegenden Fehlers vor.
\n","comment":"Nein. Es reicht aus, nur den problematischen Prozess zu beenden. Das\nhier beschriebene Herunterfahren würde die Robustheit eines\nBetriebssystems senken.
\n"},{"comment":"Ja. Auch bei Traps wie z. B. einem Seitenfehler, bei dem ein Prozess\nauf eine Seite zugreift, die gerade ausgelagert ist (swapping),\nist das Weiterlaufen des Prozesses, nachdem die Seite wieder eingelagert\nwurde, sinnvoll.
\n","option":"Das Wiederaufnahmemodell ist für Interrupts und Traps gleichermaßen\ngeeignet.
\n","correct":true},{"correct":false,"option":"Interrupts sollten nach dem Beendigungsmodell behandelt werden, weil\nein Zusammenhang zwischen dem unterbrochenen Prozess und dem Grund des\nInterrupts bestehen kann.
\n","comment":"Nein, Interrupts sind unvorhersagbare Ereignisse wie z. B. das\nEingehen eines Netzwerkpaketes oder das Drücken einer Taste auf der\nTastatur. Der aktuell laufende Prozess sollte i. A. nicht\ndirekt wegen einem derartigen Ereignis beendet werden, da dieser\nnicht unbedingt einen Bezug zu einer derartigen Eingabe\nhat.
\n"}],"source":"2022-07"},{"options":[{"correct":true,"option":"Ein Programm kann durch mehrere Prozesse gleichzeitig\nausgeführt werden
\n","comment":"Ja, teste z. B.
\nsleep 5 &\nsleep 5
\nHier wird das Programm sleep
gleichzeitig ausgeführt,\nweswegen dieser Befehl nur 5 Sekunden (statt 10) benötigt.
In einem Prozess kann immer nur ein\nProgramm ausgeführt werden.
\n","correct":false,"comment":"Nein, nach POSIX kann mit exec(3)
ein\nProzess zu einem anderen Programm wechseln.
Ein Prozess kann gleichzeitig mehrere verschiedene\nProgramme ausführen.
\n","correct":false,"comment":"Nein, ein Prozess ist ein Programm in Ausführung. Es\nkann zwar zu einem anderen Programm gewechselt werden,\nmöchte man jedoch nebenläufig ein anderes Programm ausführen,\nmuss man einen neuen Prozess erzeugen (fork(2)
\n+ exec(3)
oder posix_spawn(3)
)
Nein. Der Compiler erzeugt Programme (oder Objektdateien, die zu\nProgrammen gebunden werden), ein Prozess wird aber erst zur Laufzeit vom\nBetriebssystem erstellt.
\n","option":"Der Compiler erzeugt aus mehreren Programmteilen (Module) einen\nProzess.
\n","correct":false}],"source":"2022-07","id":"DTYwPVzMcGHELB0Wj+yyqQ","question":"Welche Aussage zum Thema Programme und Prozesse ist richtig?
\n","multiple":false},{"question":"Ein laufender Prozess wird in den Zustand bereit überführt. Welche\nAussage passt zu diesem Vorgang?
\n","multiple":false,"id":"NlZ+lmiwDgmknbCJNZ7qnQ","options":[{"correct":false,"option":"Es ist kein direkter Übergang von laufend nach bereit möglich.
\n"},{"comment":"Ja, der Prozess könnte noch weiter rechnen, ist also\nbereit.
\n","option":"Der Prozess wird durch einen anderen Prozess verdrängt, oder gibt die\nCPU freiwillig ab.
\n","correct":true},{"option":"Der Prozess wartet auf Daten von der Festplatte.
\n","correct":false,"comment":"Nein, der Prozess ist dann blockiert, bis die Daten gelesen\nsind.
\n"},{"comment":"Nein, der Prozess ist dann blockiert, bis der andere Prozess\nbeendet ist. Eine Ausnahme könnte hier der Aufruf mit dem Parameter\nWNOHANG
darstellen, mit welchem der Systemaufruf sofort\nzurückgibt.
Der Prozess wartet mit dem Systemaufruf waitpid(3)
auf\ndie Beendigung eines anderen Prozesses.
Welche Seitennummer und welcher Offset gehören bei einstufiger\nSeitennummerierung und einer Seitengröße von 1024 (= 210)\nBytes zu folgender logischer Adresse: 0x0802?
\n","multiple":false,"id":"cHIhP6sH8A2NMzY4ORg1Ng","options":[{"comment":"Ja, 0x0802 = 0b0000 10|00 0000 0010
also ist die\nSeitennummer 0b00 0010 = 0x2
und der Offset\n0b00 0000 0010 = 0x2
Seitennummer 0x2, Offset 0x2
\n"},{"option":"Seitennummer 0x8, Offset 0x8
\n","correct":false,"comment":"Nein. Hier sind beide Angaben falsch.
\n"},{"comment":"Nein. Hier ist der Offset falsch.
\n","correct":false,"option":"Seitennummer 0x2, Offset 0x8
\n"},{"correct":false,"option":"Seitennummer 0x8, Offset 0x2
\n","comment":"Nein. Da hier der Offset 10 Bit und kein Vielfaches von 4 hat, darf\nman nicht einfach die Hexadezimaldarstellung an der Grenze\neines nibbles (=\nHalbbyte, 4 Bit, ein Zeichen in Hexadezimaldarsetllung) zerlegen.\nDeswegen ist hier die Seitennummer falsch.
\n"}],"source":"2022-07"},{"question":"Welche Aussage zu UNIX/Linux-Dateideskriptoren ist korrekt?
\n","multiple":false,"id":"Sv72Kzil2EToRXsWdDj7eg","options":[{"correct":true,"option":"Nach dem Aufruf von fork(2)
teilen sich Eltern und\nKindprozess die den gemeinsamen Dateideskriptoren zu Grunde liegenden\nKernel-Datenstrukturen.
Ja, vergleiche zum Beispiel sister
, bei der ein Kindprozess\nfür die Bearbeitung einer Anfrage zuständig war und den Dateideskriptor\nverwendet, der im Elternprozess von accept(3)
zurückgegeben\nwurde.
Da Dateideskriptoren Zeiger auf Betriebssystem-Interne Strukturen\nsind, können diese zwischen Prozessen geteilt werden.
\n","correct":false,"comment":"Der Dateideskriptor ist lediglich ein Wert, der vom Betriebssystem\nals eine Referenz auf einen Wert in einer pro Prozess im kernel\nspace angelegte Datenstruktur interpretiert wird (z. B. ein Index\nin ein Array an Dateideskriptionen). Da diese nicht geteilt\nist, ist auch das Teilen von Dateideskriptoren im Allgemeinen\nnicht zielführend.
\n"},{"comment":"Nein, das wäre die inode
. Der Dateideskriptor ist eine\nReferenz (jedoch kein Pointer) auf eine Datenstruktur im Betriebssystem,\ndie u. a. auch die Position des Prozesses in der Datei enthält.
Der Dateideskriptor enthält die nötigen Metadaten einer Datei und ist\nauf der Festplatte gespeichert.
\n","correct":false},{"comment":"Nein, dieses Flag existiert nicht. Angespielt wird hier auf\nFD_CLOEXEC
, was die beschriebene Wirkung bei einem Aufruf\nvon exec(3)
zeigt.
Das Flag FD_CLOFORK
eines Dateideskriptors sorgt dafür,\ndass der Dateideskriptor bei einem Aufruf von fork(2)
\nautomatisch geschlossen wird.
Welche Aussage über die Koordinierung von kritischen Abschnitten\nunter Unix ist richtig?
\n","multiple":false,"options":[{"comment":"Ja. Signalbehandlung stellt asymmetrische Nebenläufigkeit dar. Der\naktuelle Ausführungsstrang wird also unterbrochen, um zum signal\nhandler zu springen. Wenn dieser nun versucht, ein lock zu\nsperren, das schon vom Hauptprogramm gesperrt wurde, so wartet dieser\nauf das Hauptprogramm, welches jedoch durch die Signalbehandlung\nunterbrochen ist. Es kommt zu einer Verklemmung.
\n","correct":true,"option":"Für die Synchronisation zwischen dem Hauptprogramm und einer\nSignalbehandlungsfunktion sind Schlossvariablen (Locks) ungeeignet.
\n"},{"comment":"Nein. Einerseits ist das Sperren von Interrupts, die ja\nnicht notwendigerweise im Zusammenhang mit dem Prozess\nstehen müssen, eine privilegierte Operation, die dem Betriebssystem\nvorenthalten ist. Andererseits würde dies bei manchen Formen von\nNebenläufigkeit nicht den gewünschten Effekt erzielen, da\nz. B. auf einem Multiprozessorsystem mehrere leichtgewichtige Prozesse\n(kernel-level threads) echt nebenläufig Speicherzugriffe\ndurchführen können, ohne dass einer der Prozesse durch einen Interrupt\nverdrängt wird.
\n","option":"Ein Unix-Prozess kann durch das Sperren von\nUnterbrechungen (Interrupts) den Speicherzugriff in einem kritische\nAbschnitte [sic!] synchronisieren.
\n","correct":false},{"comment":"Nein. Die Ressourcen eines schwergewichtigen Prozesses können\nzwischen verschiedenen leichtgewichtigen Prozessen geteilt sein, die\nnebenläufig einen Aktivitätsstrang ausführen.
\n","option":"In einem Unix-Prozess kann es keinen kritischen\nAbschnitt geben, da immer nur ein Aktivitätsträger pro\nProzess aktiv ist.
\n","correct":false},{"comment":"Nein. es gibt vielerlei Synchronisationsmechanismen für verschiedene\nArten von Nebenläufigkeit, für kritische Abschnitte kann\ninsbesondere auch pthread_mutex
verwendet werden.
Kritische Abschnitte können unter Unix nur mit Semaphoren\nsynchronisiert werden.
\n","correct":false}],"source":"2022-07"},{"source":"2022-07","options":[{"option":"e
liegt im Stacksegment und zeigt in das\nTextsegment.
Ja. e
ist ein Zeiger auf die Funktion f1
.\nFunktionen liegen im Textsegment. Zudem ist e
eine lokale\nVariable, liegt also im Stacksegment.
c
ist mit dem Wert 0 initialisiert.
Nein, nur Variablen der Speicherklasse auto
, also\nglobale Variablen und lokale static
-Variablen werden auf 0\ngesetzt, wenn sie nicht anderweitig initialisiert werden.\nc
ist uninitialisiert.
Nein. Das Ziel von y
ist hier const
,\ny
selbst jedoch nicht. Pointerarithmetik auf y
\nist also erlaubt. Eine Merkregel hierfür lautet
Hier bezöge sich const also auf const
\nbezieht sich auf das Schlüsselwort links davon, außer es steht ganz\nlinks. Dann bezieht sich const
auf das Schlüsselwort rechts\ndavon.int
,\nnicht auf *
. Siehe auch hier
Die Anweisung y++
führt zu einem Laufzeitfehler, da\ny
konstant ist.
Ja. Mit malloc(3)
wird Haldenspeicher allokiert.
d
ist ein Zeiger, der in den Heap zeigt.
a
liegt im Datensegment.
Ja. a
ist eine globale Variable. Globale Variablen\nliegen im Datensegment. a
liegt im Datensegment.
y
liegt im Stacksegment.
Gemäß der x86_64-System V-ABI liegen Funktionsparameter wie\ny
in einem Register, das ist jedoch nicht\nplattformunabhängig garantiert. Ich vermute trotzdem, die erwartete\nAntwort hier ist ja
.
Durch die Verwendung von static
innerhalb einer Funktion\nerzeugt man eine Variable, die zwar nur in diesem Gültigkeitsbereich\nsichtbar ist, bei der jedoch Änderungen in einem Aufruf der Funktion in\nspäteren Aufrufen sichtbar sind. Derartige Variablen liegen im\nDatensegment.
b
liegt im Stacksegment.
Nein, da diese Speicherstelle im Heap liegt und - im Gegensatz zu\nStackspeicher - erst durch den Aufruf von free(3)
ungültig\nwird.
Die Speicherstelle, auf die d
zeigt, verliert beim\nRücksprung aus der Funktion f1()
ihre Gültigkeit.
Welche der Aussagen zu folgendem Programmfragment sind richtig?
\nstatic int a = 2022;\nvoid f1 (const int *y) {\n static int b;\n int c;\n char *d = malloc(0x802);\n void (*e)(const int *) = f1;\n y++;\n //...\n}
\n"},{"multiple":false,"options":[{"comment":"Nein, die P-Operation (vom\nNiederländischen probeer te verlagen - versuche, zu\nverringern) verringert den Wert der Semaphore um 1 und blockiert,\nwenn dies den Wert unter 0 bringen würde, bis eine V-Operation\naufgerufen wird. Daher verwechselt
diese Frage P und\nV.
Die P-Operation eines Semaphors erhöht den Wert des\nSemaphors um 1 und deblockiert gegebenenfalls wartende Prozesse.
\n"},{"correct":true,"comment":"Ja, die V-Operation (ursprünglich vom Niederländischen\nvrijgave - freigeben) erhöht den Wert der Semaphore um 1. Dabei\nwird eventuell eine wartende P-Operation entblockiert.
\n","option":"Die V-Operation eines Semaphors erhöht den Wert des Semaphors um 1\nund deblockiert gegebenenfalls wartende Prozesse.
\n"},{"correct":false,"comment":"Nein, eine binäre Semaphore (Semaphore mit Startwert 1), bei der P\nund V immer paarweise nacheinander aufgerufen werden,\nimplementiert gegenseitigen Ausschluss.
\n","option":"Ein Semaphor kann nur zur Signalisierung von\nEreignissen, nicht jedoch zum Erreichen gegenseitigen\nAusschlusses verwendet werden.
\n"},{"comment":"Nein, eine Semaphore erlaubt dies im Gegensatz zu einem\nmutex, wo das nicht-einhalten dieser Vorschrift als\nProgrammierfehler angesehen wird.
\n","correct":false,"option":"Die V-Operation eines Semaphors kann ausschließlich von\neinem Thread aufgerufen werden, der zuvor mindestens eine P-Operation\nauf dem selben Semaphor aufgerufen hat.
\n"}],"source":"2017-02","question":"Welche Aussage zu Semaphoren ist richtig?
\n","id":"sWoPd6+WK3e53469kkHw6A"},{"source":"2017-02","question":"Welche Seitennummer und welcher Offset gehören bei einstufiger\nSeitennummerierung und einer Seitengröße von 1024 Bytes zu folgender\nlogischer Adresse: 0xc01a
?
Seitennummer 0xc, Offset 0x1a
\n"},{"correct":true,"comment":"1024 = 210 Byte pro Seite, d. h. 6 Bit Seitennummer, 10\nBit Offset. 0xc01a = 0b1100 00|00 0001 1010
also ist der\nOffset 0b00 0001 1010 = 0x1a
und die Seitennummer\n0b0011 0000 = 0x30
.
Seitennummer 0x30
, Offset 0x1a
Nein. Da hier der Offset 10 Bit und damit kein Vielfaches von 4 Bit\nhat, darf man nicht einfach die Hexadezimaldarstellung an\nder Grenze eines nibbles (=\nHalbbyte, 4 Bit, ein Zeichen in Hexadezimaldarsetllung) zerlegen.\nDeswegen ist hier die Seitennummer falsch.
\n","correct":false,"option":"Seitennummer 0xc0
, Offset 0x1a
Seitennummer 0xc01
, Offset 0xa
Welche Aussage über Variablen in C-Programmen ist richtig?
\n","id":"sbKVKfoR/4I7CUTQBw4f1w","source":"2017-02","multiple":false,"options":[{"option":"Lokale automatic-Variablen, die auf dem Stack angelegt werden, werden\nimmer mit dem Wert 0 initialisiert.
\n","correct":false,"comment":"Lokale Variablen sind uninitialisiert, bis sie (eventuell zusammen\nmit der Deklaration) initialisiert werden. Lesender Zugriff auf\nuninitialisierte Werte ist undefiniertes Verhalten. Globale\nmodul-interne Variablen (static
) sind hingegen\nstandardmäßig auf 0 initialisiert.
Wird dem Parameter einer Funktion innerhalb der Funktion ein neuer\nWert zugewiesen, so ändert sich auch der Wert der Variablen, welche in\nder aufrufenden Funktion als Parameter angegeben wurde.
\n","comment":"Nein. C ist call-by-value, übergeben wird also tatsächlich\nder Wert der Variable, nicht etwa eine Referenz darauf\nübergeben. Dass hier beschriebene call-by-reference-Verhalten\nkann z. B. in C++ durch die Verwendung von\n&
(References)\noder in Ada mit IN\nOUT Parameter erzeugt oder in C durch Zeiger nachgebildet\nwerden.
Eine Funktion, die mit dem Schlüsselwort static definiert wird,\nkann nur innerhalb des Moduls aufgerufen werden, in dem sie\ndefiniert wurde, nicht jedoch aus einem anderen Modul\nheraus.
\n","correct":true,"comment":"Ja. static
bei Funktionen und globalen Variablen\nverändert die Sichtbarkeit wie hier beschrieben. (static
\nbei lokalen Variablen in Funktionen sorgt dafür, dass der Wert der\nVariablen Funktionsaufrufe hinweg erhalten bleibt.) Es ist dennoch\nmöglich einen Zeiger auf die Funktion an andere Module zu übergeben,\nwomit man den indirekten Aufruf einer static
Funktion\nerlaubt.
Es ist nicht möglich, Zeiger als Parameter an Funktionen\nzu übergeben.
\n","correct":false,"comment":"Nein, das ist möglich.
\n"}]},{"source":"2017-02","id":"7zsBqJqLnoAdA8CDeHd0+g","question":"Welche der folgenden Aussagen über UNIX-Dateisysteme ist richtig?
\n","options":[{"option":"Der Name einer Datei wird in ihrem Dateikopf (inode)\ngespeichert.
\n","correct":false,"comment":"Nein, der Name wird in dem Verzeichnis gespeichert, das die Datei\nenthält. Es können auch mehrere Verzeichnisse Einträge mit\nunterschiedlichen Namen haben, die auf dieselbe inode\nverweisen.
\n"},{"option":"In einem Verzeichnis darf es keinen Eintrag geben, der auf das\nVerzeichnis selbst verweist.
\n","comment":"Nein. Jedes Verzeichnis enthält sogar mindestens einen solchen\nEintrag (.
, der Selbstverweis).
Nein, auf eine reguläre Datei muss nur mindestens ein\nhard link verweisen, damit sie nicht gelöscht\nwird. Die Aussage gilt nur für Verzeichnisse, die immer\neinen Verweis auf sich selbst (.
) beinhalten und den\nVerweis des Elternverzeichnisses innehaben.
Auf eine Datei in einem Dateisystem verweisen immer\nmindestens zwei hard-links.
\n"},{"correct":true,"comment":"Ja, das kann z. B. mit ln datei auch-datei
\nfür eine Datei datei
im aktuellen Arbeitsverzeichnis\nerzielt werden, indem die neue Datei auch-datei
erstellt\nwird welches sich die gleiche inode teilt.
Innerhalb eines Verzeichnisses können mehrere Verweise auf den selben\ninode existieren, sofern diese unterschiedliche Namen\nhaben.
\n"}],"multiple":false},{"source":"2017-02","question":"Welche der folgenden Aussagen zum Thema persistenter Datenspeicherung\nsind richtig?
\n","id":"dfKr+p4GFKHxIjrimJNGGQ","options":[{"comment":"Nein, eventuell ist der Platz nach dem Ende der Datei bereits belegt,\nweswegen sie nicht in-place vergrößert werden\nkann.
\n","correct":false,"option":"Bei kontinuierlicher Speicherung ist es immer problemlos\nmöglich, bestehende Dateien zu vergrößern.
\n"},{"option":"Bei indizierter Speicherung kann es prinzipbedingt\nnicht zu Verschnitt kommen.
\n","correct":false,"comment":"Nein, hier ist einer Datei eine bestimmte Anzahl an Blöcken\nzugeordnet. Ist die Datei kleiner als diese Blöcke, so liegt Verschnitt\nvor.
\n"},{"correct":true,"comment":"Ja, das ist möglich.
\n","option":"Bei verketteter Speicherung mittels FAT-Ansatz kann die\nVerkettungsinformation redundant gespeichert werden, um die\nFehleranfälligkeit zu reduzieren.
\n"},{"option":"Im Vergleich zu den anderen Verfahren ist bei indizierter Speicherung\ndie Positionierzeit des Festplatten-Armes beim Zugriff auf\nalle Datenblöcke einer Datei minimal.
\n","correct":false,"comment":"Nein, das wäre bei sequentieller Speicherung der Fall. Die Blöcke\neiner Datei bei indizierter Speicherung liegen nicht\nnotwendigerweise nah beieinander.
\n"},{"option":"Beim Einsatz von RAID 1 kann eine der beteiligten\nPlatten ausfallen, ohne dass das Gesamtsystem ausfällt.
\n","correct":true,"comment":"Ja, RAID 1 verteilt die Daten redundant über zwei oder mehr Platten.\nFällt eine Platte aus, so gibt es noch mindestens eine Kopie.
\n"},{"option":"Beim Einsatz von RAID 0 kann eine der beteiligten\nPlatten ausfallen, ohne dass das Gesamtsystem ausfällt.
\n","correct":false,"comment":"Nein, RAID 0 verteilt die Daten per striping\nnicht redundant auf die Platten, sondern erzielt nur einen\nGeschwindigkeitsvorteil, dadurch dass auf mehrere Platten gleichzeitig\ngeschrieben oder von mehreren Platten gleichzeitig gelesen werden\nkann.
\n"},{"option":"Journaling-Dateisysteme garantieren, dass auch nach einem\nSystemausfall alle Metadaten wieder in einen konsistenten\nZustand gebracht werden können.
\n","comment":"Ja, auch die Transaktionalität der Änderung von Metadaten wird\ndadurch erzielt, dass Beginn und Fertigstellung aller Änderungen am\nDateisystem in einem Journal aufgezeichnet werden, das beim Hochfahren\nauf Vollständigkeit aller Transaktionen überprüft wird.
\n","correct":true},{"comment":"Ja, bei Festplatten (HDDs) muss auf\nphysikalischer Ebene der Lese-/Schreibarm sich an der Stelle befinden,\nan der die gewünschten Daten auf der Magnetscheibe stehen. Bei\nwahlfreiem Zugriff muss dieser zwischen den\nnicht beieinanderliegenden Sektoren bewegt werden, bei\nsequentiellem Zugriff kann entlang der Spur gelesen\nwerden.
\n","correct":true,"option":"Festplatten eignen sich besser für sequentielle als für wahlfreie\nZugriffsmuster.
\n"}],"multiple":true},{"multiple":true,"options":[{"correct":true,"comment":"Ja, bei kooperativer Einplanung muss das Programm per\nSystemaufruf die Ressource CPU abgeben. Ein unkooperatives Programm\nkann dies unterlassen, und die CPU monopolisieren.
\n","option":"Bei kooperativer Einplanung kann es zur Monopolisierung\nder CPU kommen
\n"},{"option":"Bei der Verwendung des Round-Robin-Verfahrens kann der\nKonvoi-Effekt nicht auftreten.
\n","comment":"Nein, der Konvoieffekt existiert auch hier, da die Vergabe der\nZeitscheiben reihum wie bei FCFS funktioniert. Prozesse mit\nlangen Rechenstößen nutzen hier ihre Zeitscheibe voll aus, während\nE/A-intensive Prozesse benachteiligt sind.
\n","correct":false},{"option":"Der Einsatz des FCFS-Verfahrens setzt kooperative Prozesse\nvoraus.
\n","correct":true,"comment":"Ja, FCFS ist ein kooperatives Einplanungsverfahren. Ein\nunkooperativer Prozess könnte hier die CPU monopolisieren.
\n"},{"correct":false,"comment":"Nein, probabilistische Einplanungsverfahren arbeiten mit\nAbschätzungen der benötigten Stoßlängen.
\n","option":"Die Verwendung probabilistischer Einplanungsverfahren ist nur\nmöglich, wenn dem Planer alle Prozesse und ihre\nCPU-Stoßlängen im Voraus bekannt sind.
\n"},{"option":"In einem asymmetrischen Multiprozessorsystem ist der Einsatz\nasymmetrischer Einplanungsverfahren obligatorisch.
\n","correct":true,"comment":"Ja. Man betrachte z. B. den Fall CPU + GPU. Ein Prozess, der auf der\nCPU rechnen möchte, kann nicht unbedingt auch\nauf der GPU rechnen. Deswegen ist der Einsatz einer Bereitliste für\nalle Rechenkerne (symmetrisches Planungsverfahren) hier\nunmöglich. Stattdessen müssen zumindest für GPU und CPU separate\nBereitlisten existieren. Dies zeichnet asymmetrische Planungsverfahren\naus.
\n"},{"correct":false,"comment":"Nein. offline Algorithmen sind alle\nEingabedaten wie z. B. die zu planenden Prozesse im Voraus bekannt.\nDamit sind sie für interaktiven Betrieb ungeeignet, da dort zur Laufzeit\nvorher unbekannte Anforderungen auftreten.
\n","option":"Statische (off-line) Einplanungsverfahren sind besonders für den\nEinsatz in interaktiven Systemen geeignet.
\n"},{"option":"Virtual-Round-Robin benachteiligt E/A-intensive Prozesse zu Gunsten\nvon rechenintensiven Prozessen.
\n","comment":"Nein. Bei VRR werden Prozesse, die eine Ein- oder Ausgabe\nbeenden, bevorzugt eingeplant. Bei Ende einer Zeitscheibe werden dann\nzuerst die Prozesse auf der Vorzugsliste eingelastet.
\n","correct":false},{"option":"Beim Einsatz des multilevel-queue-Verfahrens (MLQ) werden die\nProzesse nach ihrem Typ in separate Bereitlisten aufgeteilt, die jeweils\neine eigene lokale Einplanungsstrategie verwenden.
\n","comment":"Ja, bei diesem Verfahren werden mehrere Bereitlisten für\nunterschiedliche Arten von Prozessen (z. B. System-, Dialog- und\nStapelprozesse) verwendet. Jede dieser Listen verwendet eine lokale\nEinplanungsstrategie. (Um zwischen den Listen zu wechseln wird\nzusätzlich eine globale Strategie verwendet).
\n","correct":true}],"source":"2017-02","question":"Welche der folgenden Aussagen zur Einplanung von Prozessen sind\nrichtig?
\n","id":"Xlrba5A4D3Pcvl52oD6Z1g"},{"question":"Welche Aussage über Funktionen der exec()
-Familie ist\nrichtig?
Dem Vater-Prozess wird die Prozess-ID des Kind-Prozesses\nzurückgeliefert.
\n","correct":false,"comment":"Nein, bei exec
wird ein Programm innerhalb von einem\nProzess ersetzt. Die Funktion kehrt nur im Fehlerfall zurück, und\nkommuniziert nichts direkt an den Vater-Prozess.
Nein, weil exec
Funktionen keine\nFunktionszeiger nehmen, sondern ein Verweis auf eine Datei, in welchem\ndas auszuführende Programm drin steht.
Der an exec()
übergebene Funktionszeiger wird durch\neinen neuen Thread im aktuellen Prozess ausgeführt.
Ja, weil dann das alte Programm im Prozess ersetzt wurde, und\nnicht mehr weiter laufen könnte.
\n","correct":true,"option":"Falls kein Fehler auftritt, kehrt der Aufruf von exec()
\nnicht zurück
Nein, weil exec
keine neuen Prozesse\nerstellt.
exec()
erzeugt einen neuen Kind-Prozess und startet\ndarin das angegebene Programm.
Dem Vater-Prozess wird die Prozess-ID des Kind-Prozesses\nzurückgeliefert.
\n"},{"option":"Der Kind-Prozess bekommt die Prozess-ID des Vater-Prozesses.
\n","correct":false,"comment":"Nein, es bekommt den festen Wert 0; der Eltern-Prozess\nkann mit getppid
(eindeutig) bestimmt\nwerden.
Nein, im Fehlerfall (d.h. es konnte kein Kind erstellt werden)\nbekommt der Eltern-Prozess eine Fehler mit.
\n","correct":false,"option":"Im Fehlerfall wird im Kind-Prozess -1 zurückgeliefert.
\n"},{"option":"Der Rückgabewert ist in jedem Prozess (Kind und Vater)\njeweils die eigene Prozess-ID.
\n","correct":false,"comment":"Nein, Kind bekommt 0, damit es weiß es ist das Kind und Vater bekommt\ndie PID vom Kind.
\n"}],"multiple":false,"question":"Welche Aussage über den Rückgabewert von fork()
ist\nrichtig?
Welche Aussage über das aktuelle Arbeitsverzeichnis (Current Working\nDirectory) trifft zu?
\n","options":[{"correct":false,"comment":"Nein, weil ein aktuelles Verzeichnis wird einem Prozess\nzugeordnet.
\n","option":"Jedem UNIX-Benutzer ist zu jeder Zeit ein aktuelles Verzeichnis\nzugeordnet.
\n"},{"correct":true,"option":"Pfadnamen, die nicht mit dem Zeichen /
\nbeginnen, werden relativ zu dem aktuellen Arbeitsverzeichnis\ninterpretiert.
Nein, das ändert den CWD von dem aufrufendem Prozess.
\n","option":"Mit dem Systemaufruf chdir()
kann das\naktuelle Arbeitsverzeichnis eines Prozesses durch seinen Vaterprozess\nverändert werden.
Besitzt ein UNIX-Prozess kein Current Working Directory, so beendet\nsich der Prozess mit einem Segmentation Fault.
\n"}],"multiple":false},{"multiple":false,"options":[{"comment":"Ja, weil das Scheduling innerhalb vom Prozess stattfindet, und damit\nunabhängig vom Betriebsystem ist.
\n","correct":true,"option":"Bei User-Threads ist die Scheduling-Strategie nicht\ndurch das Betriebssystem vorgegeben.
\n"},{"option":"Kernel-Threads können Multiprozessoren nicht\nausnutzen.
\n","comment":"Doch, weil das Betriebsystem diese kennt und in der Lage ist diese\nauf verschiedene Kerne einzulagern.
\n","correct":false},{"correct":false,"comment":"Nein, weil dieses Umschalten keine privilegierte\nOperation ist.
\n","option":"Die Umschaltung von User-Threads ist eine privilegierte Operation und\nmuss deshalb im Systemkern erfolgen.
\n"},{"comment":"Nein, ein Kernel-Thread kann auch den gleichen\nSpeicherraum mit anderen Threads teilen (bspw. im Kontext von echtem\nMulti-Threading, siehe Pthread).
\n","correct":false,"option":"Zu jedem Kernel-Thread gehört ein eigener, geschützter\nAdressraum.
\n"}],"question":"Welche der folgenden Aussagen zum Thema Threads ist richtig?
\n","id":"+Xgqc/zqJ+o2ZXuj5Cf+Jg","source":"2018-07"},{"source":"2012-02","id":"1yyoQAWp/BGlizlDK+7zZg","multiple":false,"question":"Nehmen Sie an, der Ihnen bekannte Systemaufruf stat(2)
\nwäre analog zu der Funktion readdir(3)
mit folgender\nSchnittstelle implementiert:
struct stat *stat(const char *path);
\nWelche Aussage ist richtig?
\n","options":[{"comment":"Nein, die Idee von diesem stat
wäre, dass anstatt selbst\nden Speicher bereitzustellen, das Betriebsystem oder die Libc dafür\nsorgen müsste den Speicherbereitzustellen. Das Problem dabei ist, dass\nSysteme hierfür pro Prozess nur einemal den Speicher statisch\nallozieren, und dann zwischen Aufrufen geteilt werden kann. Mehrere\nAufrufe der Funktion überschrieben also alte Werte. Jedenfalls ist es\nmöglich und notwendig auf den Speicher zuzugreifen, und der Inhalt\nsollte bis zu dem nächstem Aufruf von diesem stat
\ngültig bleiben, damit auch der Inhalt definiert.
Ein Zugriff über den zurückgelieferten Zeiger liefert völlig\nzufällige Ergebnisse oder einen Segmentation fault.
\n"},{"comment":"Ja, anstatt selbst den Speicher bereitzustellen, wie die die\ngewöhnliche Signatur von stat
es andeutet:
int stat(char *pathname, struct stat *statbuf);
\nwürde diese Implementierung den Speicher selbst bereitstellen müssen.\nIn diesem Speicher wären dann die Informationen nach dem bekannten\nstruct stat
Typen einsehbar.
Der Systemaufruf liefert einen Zeiger zurück, über den die aufrufende\nFunktion direkt auf eine Datenstruktur zugreifen kann, welche die\nDateiattribute enthält.
\n","correct":true},{"comment":"Es ist schwer eine ästhetische Frage mit ja
oder nein
\nzu beantworten. Grundsätzlich stimmt die Aussage, dass es möglich wäre\nauf den internen Speicher des Betriebsystems zuzugreifen, wenn es so\nimplementiert werden würde, und das Betriebsystem den Speicherschutz\nentsprechend einrichten würde. Für gewöhnlich (oder zumindest wie es in\nder Regel readdir(3)
umgesetzt wird), sollte der Speicher\nfür den struct stat
Rückgabewert im Prozess selbst\ngespeichert sein, und nicht im Betriebsystemkern.
Solch eine Schnittstelle ist nicht schön, da dadurch die\naufrufende Funktion auf internen Speicher des Betriebssystems zugreifen\nkönnte.
\n"},{"comment":"Nein, readdir
verspricht nicht den Speicher\ndynamisch auf der Halde anzulegen, darf daher auch\nnicht mit free(3)
aufgeräumt werden.
Der Aufrufer muss sicherstellen, dass er den\nzurückgelieferten Speicher mit free(3)
wieder freigibt,\nwenn er die Dateiattribute nicht mehr weiter benötigt.
In einem UNIX-UFS-Dateisystem gibt es symbolische Namen/Verweise\n(Symbolic Links). Welche Aussage ist richtig?
\n","options":[{"comment":"Nein, in dieser Antwort wurden die beiden Systemaufrufe vertauscht.\nstat(2)
löst die Verweise auf, während\nlstat(2)
sich bewusst
ist, ob eine Datei ein Verweis\nist oder nicht, und sich weigert Verweisen zu folgen.
Der Grund für diese Unterscheidung versteht man am besten mit dem\nhistorischem Kontext. Obwohl MULTICS, der vorgänger von UNIX™ bereits symbolische Verweise\nunterstützt hat, wurden diese in Unix nicht\nnachimplementiert, um das System einfacher zu halten. Es gab daher auch\nkeine Unterschiedung, welche den Namen Hard Link
\nnotwendig gemacht hätte. Mit BSD 4.1 wurden auf Unix-Artigen Systemen\nSymbolic Links
implementiert (d.h. der Systemaufruf\nsymlink
wurde hinzugefügt), damit aber diese sich gut in\ndas bestehende System integrieren, wurden Symlinks bei allen bis dahin\nbestehenden Anwendungen automatisch aufgelöst, und dann nur bei\nout out
Systemaufrufen wie eben lstat
gesondert\nbehandelt, wo es eben notwendig war (bspw. bei find
, wo\nSymbolische Verweise den Datei-Baum zu einem allgemeinem Digraphen\ndegenerieren lassen kann, und damit Tiefensucht nicht\nzwingend erfolgreich terminieren muss).
Der Systemaufruf stat()
liefert im Gegensatz zum\nSystemaufruf lstat()
die Dateiattribute des symbolischen\nVerweises und nicht die Attribute vom Ziel des\nVerweises.
Nein, ein symbolischer Verweise kann einen belibigen\nPfad enthalten, egal ob die Refernz dabei wirklich existiert, auf dem\ngleichem System liegt, welchen Typ die Datei hat (inklusive andere oder\nsogar der gleiche Verweis!) oder sich in der Zwischenzeit geändert\nhat.
\n","correct":false,"option":"Ein symbolischer Verweis kann ausschließlich auf\nreguläre Dateien verweisen.
\n"},{"comment":"Ja, wenn der Symbolischer Verweis auf ein Verzeichnis beziehen\nsollte, aber dieses Verzeichnis nicht existiert, wird das\nBetriebsystem dann transparent
den Verweis auflösen, und dann\nFestestellen, dass es das Verziechnis nicht gibt. Hier ein\nBeispiel:
$ ln -s /this/directory/does/not/exist ~/link\n $ ls -ld ~/link\n lrwxrwxrwx 1 philip philip 13 Feb 18 12:53 link -> /this/directory/does/not/exist\n $ ls ~/link\n ls: cannot access 'link': No such file or directory
\nwo No such file or directory
die englische Fehlermeldung für\nden Fehlercode ENOENT
ist.
Beim Zugriff auf einen Symbolic Link kann ein No such\nfile or directory.
-Fehler auftreten (errno==ENOENT
),\nobwohl der Symbolic Link existiert.
In jedem Inode ist ein Referenzzähler gespeichert,\nwelcher die Anzahl der Symbolic Links angibt, die auf ihn verweisen.
\n","correct":false,"comment":"Nein, der nlink
Zähler betrifft die Anzahl der Hard\nLinks auf eine Datei. Es wird protokoliert, damit das Dateisystem\nwissen kann ob der Speicher für die Datei von der\nFestplatte gelöscht werden kann. In diesem Sinne ähnelt es dem Ansatz\nvon Reference\nCountin den Hochsprache für die Automatische Speicherbereinung\neinsetzen.
Sie kennen den Begriff Seitenflattern (Thrashing). Welche Aussage ist\nrichtig?
\n","options":[{"comment":"Nein, das ist ein anderes Problem, welches durch den Kontext-Wechsel\n(egal ob zwischen Benutzer-Prozessen oder zwischen User-Space und\nKernel-Space) die Beschleunigung des TLBs verliert.
\n","option":"Als Seitenflattern bezeichnet man das wiederholte Löschen und Neuladen\ndes Translation-Look-Aside-Buffer (TLB), ausgelöst durch häufigen\nProzesswechsel.
\n","correct":false},{"comment":"Ja, es handelt sich hierbei um ein Problem in der\nAuslagerungsstrategie der Speicherverwaltung. Es trifft sozusagen die\nResonanzfrequenz
, und verlangsamt Speicherzugriffe welche bei\neiner anderen Strategie keien Zugriffe auf externen Speicher benötigen\nmüssten.
Als Seitenflattern bezeichnet man das wiederholte Einlagern einer erst\nvor kurzem verdrängten Speicherseite. Die Prozesse verbringen als Folge\ndie meiste Zeit mit dem Warten auf die Behebung von Seitenfehlern.
\n"},{"comment":"Nein, Seitenflattern hat hört man nicht, und es kann\nauch auf Thin-Client auftreten, insofern diese die möglichkeit haben\nSeiten ein- und auszulagern.
\n","option":"Seitenflattern erkennt man an der starken Geräuschentwicklung der\nFestplatte, da auf Grund häufiger Seitenzugriffe der Lesekopf ständig neu\npositioniert wird. Bei Systemen ohne Festplatte (z. B. Thin-Clients)\nkann das Seitenflattern nicht auftreten.
\n","correct":false},{"comment":"Doch, bspw. im Extreemfall von nur drei Seiten, wo nur zwei\neingelagert sein könnten. Würden diese zyklisch angesprochen werden (1,\n2, 3, 1, 2, 3, …), würde immer die Seite auf die als\nnächstes zugegriffen wird ausgelagert werden.
\n","correct":false,"option":"Bei Verwendung der LRU-Seitenersetzungstrategie kann\nSeitenflattern prinzipbedingt nicht auftreten.
\n"}],"id":"kxbMKl547c0l18MfjnD7cA","source":"2012-02","multiple":false},{"multiple":false,"source":"2012-02","id":"HIHjTQKHgjsd8AazBz36rg","options":[{"option":"Der zu verwaltende Speicher wird in Speichereinheiten\nunterschiedlicher Größe unterteilt.
\n","correct":false,"comment":"Nein, einer Bitliste (oder Bitkarte) werden Hohlräume\nfester Größe
gespeichert, wobei jedes Bit die Belegung\neines solchen Holraums designiert.
Ja, insofern keine zusätzlichen Hillfsstrukturen wie ein\nzuletzt freigegeben
index verwaltet wird, ist es unter umständen\nnotwendig die gesammte Bitliste abzusuchen, um ein Speicherinterval der\npasenden Größe zu finden.
Zur Suche nach freiem Speicher kann es nötig sein, die\ngesamte Bitliste zu durchsuchen.
\n","correct":true},{"comment":"Nein, es ist keine gesonderte Zusammenfassung notwendig,\nweil die Verwaltungsstrukturen außerhalb des verwalteten Speichers\nliegen. Damit benachbarte Speicherintervalle zusamengefasst werden\nkönnen bei der Vergabe des Speichers, müssen diese nur alle\nunbelegt gewesen sein.
\n","option":"Das Zusammenfassen von benachbarten freien Speichereinheiten ist\nbesonders aufwändig.
\n","correct":false},{"correct":false,"option":"Je feiner die Granularität der Speichereinheiten ist, desto kürzer\nist die Bitliste.
\n","comment":"Nein, granularität ist inverse proportional zur Länge der Bitliste.\nJe feinere Granularität, d.h. mit jedem Bit wird auf\nweniger Speicher verweisen, benötigt eine längere Bitliste,\ndamit der gleiche Speicher-Interval abgedeckt werden kann.
\n"}],"question":"Welche Aussage bezüglich der Freispeicherverwaltung mittels einer\nBitliste ist richtig?
\n"},{"options":[{"comment":"Nein, andersherum. Ein logischer Adressraum ist ein zusammenhängender\nAdressbereich. Der virtuelle Adressbereich setzt auf diesen auf, indem\nAdressen, die nicht auf den Speicher abgebildet werden\nkönnen, beim Zugriff einen Adressübersetzungsfehler auslösen. Die\nZuordnung vom logischen zum realen Adressraum kann somit\nals totale Funktion betrachtet werden, im Gegensatz dazu\nkann die Zuordnung vom virtuellen zum realen Adressraum als\npartielle Funktion auf den logischen Adressen betrachtet werden (vgl.\nSP1 B Vl. 2 S. 12 ff., 27).
\n","option":"Virtuelle Adressräume sind Voraussetzung für die Realisierung\nlogischer Adressräume.
\n","correct":false},{"correct":false,"comment":"Nein, durch Speichervirtualisierung können Seiten auf den\nHintergrundspeicher ausgelagert werden (swapping).
\n","option":"Der virtuelle Adressraum kann nie größer\nsein als der im Rechner vorhandene Hauptspeicher.
\n"},{"correct":false,"option":"Die maximale Größe des virtuellen Adressraums kann\nunabhängig von der verwendeten Hardware frei gewählt werden.
\n","comment":"Nein, z. B. ist diese auf einem 32-Bit-System in der Regel auf\nhöchstens 2³² Datenwörter beschränkt (In der Praxis also nur 4 GiB).
\n"},{"option":"Der physikalische Adressraum ist durch die gegebene\nHardwarekonfiguration definiert.
\n","comment":"Ja, jede physikalische Adresse korrespondiert zu einer\ntatsächlichen Stelle im Hauptspeicher, von dem eine bestimmte Menge in\neinem System verbaut ist.
\n","correct":true}],"question":"Welche der folgenden Aussagen zum Thema Adressräume ist richtig?
\n","id":"+OrslvdvJq0RVKg4AQl9Vg","multiple":false,"source":"2020-02"},{"id":"ZW4e12RJeno1deyEYXzhbw","options":[{"comment":"Ja. C ist call-by-value, da Funktionsparameter als Kopie und\nnicht als Referenz weitergegeben werden. Zeiger sind jedoch\nReferenzen auf Speicherstellen im Adressraum. Erhält eine Funktion also\neinen Zeiger als Wert, so kann sie mit dem Ziel des Zeigers\nso verfahren, als hätte sie das Ziel selbst per Referenz erhalten.
\n","option":"Zeiger können verwendet werden, um in C eine call-by-reference\nÜbergabesemantik nachzubilden.
\n","correct":true},{"comment":"Nein, void pointer zeigen auf Daten mit unspezifiziertem\nTyp. Ein void*
muss jedoch zuerst zu einem\nZeiger auf einen nicht-void
-Wert gecastet werden, bevor er\ndereferenziert werden kann, oder Pointerarithmetik durgeführt werden\nkann.
Zeiger vom Typ void*
existieren in C nicht, da solche\nZeiger auf Nichts
keinen sinnvollen Einsatzzweck hätten.
Ein Zeiger kann zur Manipulation von Daten in\nschreibgeschützten Speicherbereichen verwendet werden.
\n","comment":"Nein. Wird versucht, schreibend auf einen schreibgeschützten Bereich\nzuzugreifen, so verhindert dies die MMU, unabhängig davon, mit welchem\nProgrammierkonzept der Zugriff versucht wurde.
\n","correct":false},{"comment":"Nein, ein Zeiger wird immer noch als Wert an eine\nFunktion übergeben, d. h. es wird eine Kopie des Zeigers in das\nentsprechende Register oder auf den Stack abgelegt. Das ein Zeiger eine\nReferenz auf eine Speicherstelle ist, spielt hierbei\nkeine Rolle. Beispiel: Würde die Aussage stimmen, so würde\ndas folgende Programm 10
ausgeben. Es gibt jedoch 5
\naus.
static int b = 10;\n\nstatic void pointers_are_values_too(int* arg) {\n arg = &b; // arg zeigt hier auf b, ptr in main bleibt aber unverändert.\n}\n\nint main(void) {\n int a = 5;\n int* ptr = &a; // ptr zeigt auf a.\n pointers_are_values_too(ptr);\n printf("%d\\n", *ptr); // ptr zeigt immer noch auf a.\n}
\n","option":"Die Übergabesemantik für Zeiger als Funktionsparameter ist\ncall-by-reference.
\n","correct":false}],"question":"Welche Aussage zu Zeigern in C-Programmen ist richtig?
\n","source":"2020-02","multiple":false},{"question":"Welche der folgenden Aussagen über Einplanungsverfahren ist\nrichtig?
\n","options":[{"correct":false,"option":"Beim Einsatz präemptiver Einplanungsverfahren kann\nlaufenden Prozessen die CPU nicht entzogen werden.
\n","comment":"Nein, das wäre kooperative Einplanung. Bei präemptiver Einplanung\nkann einem Prozess durch einen Timer-Interrupt die CPU\nentzogen werden (Präemption).
\n"},{"comment":"Nein, diese betrachten nur die ungefähren Stoßlängen.
\n","option":"Probabilistische Einplanungsverfahren müssen die exakten\nCPU-Stoßlängen aller im System vorhandenen Prozesse kennen.
\n","correct":false},{"comment":"Ja, bei kooperativer Einplanung kann der laufende\nProzess erst gewechselt werden, wenn das Programm kooperativ ist und die\nCPU abgibt. Ein unkooperatives Programm kann dies\nunterlassen, und die CPU für eine unbegrenzte Zeit in Anspruch\nnehmen.
\n","option":"Bei kooperativer Einplanung kann es zur Monopolisierung\nder CPU kommen.
\n","correct":true},{"option":"Asymmetrische Einplanungsverfahren können ausschließlich auf\nasymmetrischen Multiprozessor-Systemen zum Einsatz kommen.
\n","comment":"Nein, asymmetrische Planung (eine Bereitliste pro Prozessor)\nmuss zwar auf asymmetrischen Multiprozessorsystemen (z. B.\nCPU und GPU) eingesetzt werden, kann jedoch auch auf\nsymmetrischen Multiprozessorsystemen, bei welchen jeder Prozessor\ngleichermaßen dieselben Programme ausführen kann, eingesetzt werden.\n(vgl. SP1 C IX.2 S. 11 ff.)
\n","correct":false}],"id":"PnpHyPj3do3Y23Z08z1dfg","source":"2020-02","multiple":false},{"id":"hIl7x2N1XsKayUpWzvqc0g","multiple":false,"source":"2016-06","options":[{"correct":false,"option":"Im realen Adressraum sind alle theoretisch möglichen\nAdressen auch gültig.
\n","comment":"Nein, weil der reale Addressraum Lücken haben kann, bedingt durch den\nSpeicher.
\n"},{"option":"Der Zugriff auf eine virtuelle Adresse, die zum Zeitpunkt des\nZugriffs nicht im Hauptspeicher abgebildet ist, führt zu\neinem Trap.
\n","correct":true,"comment":"Ja, das Betriebsystem kann dann versuchen die Seite\neinzulagern, oder einen Speicherfehler an den Prozess\nweiterzuleiten.
\n"},{"comment":"Nein, der virtuelle Adressraum abstrahiert über dem realem\nAddressraum, und kann vortäuschen (/virtualisieren/) die\ngesamte Wortbreite adressierbar zu machen.
\n","correct":false,"option":"Die Größe eines virtuellen Adressraums darf die Größe des vorhandenen\nHauptspeichers nicht überschreiten.
\n"},{"comment":"Nein, alle Seiten haben die gleiche Größe (Ausnahme:\nHuge-Pages, welche ein Vielfaches größer sind), damit diese leichter\nein- und ausgelagert werden können.
\n","correct":false,"option":"Bei Seitennummerierung besitzt jede Seite eine\nunterschiedliche Größe.
\n"}],"question":"Welche Aussage zum Thema Adressräume ist richtig?
\n"},{"source":"2016-06","multiple":false,"id":"a4/J6X7S2sbSW+uNHZQi5g","question":"Ein laufender Prozess wird in den Zustand blockiert überführt. Welche\nAussage passt zu diesem Vorgang?
\n","options":[{"comment":"Nein, weil ein blockierter Prozess kann später weiter\nlaufen, sobald die Ursache, d.h. eine fehlende Ressource, behoben\nwurde.
\n","correct":false,"option":"Der Prozess terminiert.
\n"},{"correct":false,"option":"Es ist kein direkter Übergang von laufend nach blockiert möglich.
\n","comment":"Nein, ein laufender Prozess kann direkt blockiert werden\n(ohne bspw. über bereit
zu gehen), wenn ein blockierender\nSystemaufruf (read(2)
, accept(2)
,\nwait(2)
, …) getätigt wird.
Der Prozess wartet auf Daten von der Standardeingabe.
\n","correct":true,"comment":"Ja, weil das den Prozess so lange blockiert, bis diese Daten\nverfügbar sind.
\n"},{"comment":"Nein, der Prozess muss nicht (sofort) auf\neiner anderen CPU eingelastet werden.
\n","correct":false,"option":"Der bisher laufende Prozess wurde vom Betriebssystem verdrängt und\nein anderer Prozess auf der CPU eingelastet.
\n"}]},{"question":"Welche Aussage zu Seitenersetzungsstrategien ist richtig?
\n","options":[{"correct":false,"option":"Bei der Seitenersetzungsstrategie FIFO wird immer die\nzuletzt eingelagerte Seite ersetzt.
\n","comment":"Nein, First In, First Out wird die älteste Seite\nausgelagert.
\n"},{"comment":"Nein, der Deskriptor muss dahingehend angepasst werden,\num anzudeuten dass die Seite wieder präsent ist.
\n","option":"Beim Auslagern einer Speicherseite muss der zugehörige\nSeitendeskriptor angepasst werden, beim Einlagern einer Seite ist das\njedoch nicht nötig.
\n","correct":false},{"option":"Bei der Seitenersetzungsstrategie LRU wird die Seite ersetzt, welche\nam längsten nicht mehr referenziert wurde.
\n","correct":true,"comment":"Ja, Least Recently Used wird die älteste unbenutzte Seite\nausgelagert.
\n"},{"correct":false,"option":"Beim Einsatz der Seitenersetzungsstrategie FIFO kann es\nnicht zu Seitenflattern kommen.
\n","comment":"Doch, wenn die neuste Seite (First In) immer\nausgelagert wird (First Out), dann werden bei hoher Last\nimmer die gleichen Seiten ein- und ausgelagert, was man\nunter Seitenflattern
versteht.
Welche Aussage zum Thema Synchronisation ist richtig?
\n","options":[{"correct":false,"comment":"Nein, P und V können von beliebigen, auch unterschiedlichen, Threads\naus aufgerufen werden.
\n","option":"Die V-Operation kann auf einem Semaphor nur von dem\nThread aufgerufen werden, der zuvor auch die P-Operation aufgerufen\nhat.
\n"},{"correct":true,"option":"Durch den Einsatz von Semaphoren kann ein\nwechselseitiger Ausschluss erzielt werden.
\n","comment":"Ja, eine Semaphore mit initialem Wert von 1 (binäre Semaphore)\nimplementiert mutual exclusion, wenn P und V immer\npaarweise nacheinander aufgerufen werden.
\n"},{"option":"Ein Semaphor kann ausschließlich für mehrseitige\nSynchronisation (multilateral synchronisation) verwendet\nwerden.
\n","comment":"Nein, das würde bedeuten, dass man damit nur\nSynchronisationsmechanismen implementieren kann, bei denen jeder Zugriff\nund nicht nur Entnahmezugriffe auf das Betriebsmittel dem\nwechselseitigen Ausschluss unterliegt. (vgl. [10.1 S.14]) Jedoch lässt\nsich z. B. eine blockierende Warteschlange mit nichtblockierender\nEntnahme implementieren, bei welcher die Semaphore nur Konsumenten bei\neiner leeren Warteschlange blockiert.
\n","correct":false},{"correct":false,"option":"Einseitige Synchronisation (unilateral synchronisation)\nerfordert immer Betriebssystemunterstützung.
\n","comment":"Nein, diese kann zum Beispiel ohne Betriebssystemaufrufe\ndurch ein spin lock realisiert werden.
\n"}],"multiple":false,"source":"2023-02"},{"id":"gSh+jUti3oVEZ8vzBiMB5w","question":"Sie kennen den Translation-Lookaside-Buffer (TLB). Welche Aussage ist\nrichtig?
\n","source":"2023-02","multiple":false,"options":[{"correct":true,"option":"Verändert sich die Speicherabbildung von logischen auf physikalische\nAdressen aufgrund einer Adressraumumschaltung, so werden auch die Daten\nim TLB ungültig.
\n","comment":"Ja, weil die zwischengespeicherten Seitenaddressen nicht\nmehr mit dem neuem logischem Addressraum zusammenhängen würden.
\n"},{"option":"Der TLB verkürzt die Zugriffszeit auf den physikalischen Speicher da\nein Teil des möglichen Speichers in einem schnellen Pufferspeicher\nvorgehalten wird.
\n","comment":"Nein, im TLB werden nur die Addressen der Seiten gespeichert, um das\nNachschlagen in der MMU zu vermeiden, und nicht den\nSpeicher selbst.
\n","correct":false},{"correct":false,"option":"Der TLB puffert Daten bei der Ein-/Ausgabebehandlung und beschleunigt\ndiese damit.
\n","comment":"Nein, der TLB hat nichts mit den Daten per se zu tun, sondern\nbeschleundigt nur den Zugriff auf häufig benutzte Seiten.
\n"},{"correct":false,"comment":"Nein, ist kein Eintrag im TLB zu finden, wird die Adresse von der MMU\naufgelöst.
\n","option":"Wird eine Speicherabbildung im TLB nicht gefunden, wird\nder auf den Speicher zugreifende Prozess mit einer Schutzraumverletzung\n(Segmentation Fault) abgebrochen.
\n"}]},{"options":[{"option":"Mittels fork()
erzeugte Kindprozesse können in einem\nMultiprozessor-System nur auf dem Prozessor ausgeführt werden, auf dem\nauch der Elternprozess ausgeführt wird.
Nein, es ist dem Scheduler ganz überlassen zu entscheiden, auf\nwelchen Prozessoren ein Prozess laufen soll. Ein Prozess\nmuss auch nicht ganz auf einem Kern oder nur\nauf einem Kern laufen
\n","correct":false},{"option":"Der Aufruf von fork()
gibt im Elternprozess die\nProzess-ID des Kindprozesses zurück, im Kindprozess hingegen den Wert\n0.
Ja, das steht auch so in der Man-Page. Die Annahme ist hier, dass\nkein Fehler aufgetreten ist.
\n","correct":true},{"option":"Threads, die mittels pthread_create()
erzeugt wurden,\nbesitzen jeweils einen eigenen Adressraum.
Nein, Kind-Threads (im Kontext von der Pthread Bibliothek.) teilen\nden Addressraum mit dem Eltern-Thread. Prozesse haben eigene\nAddressräume.
\n","correct":false},{"correct":false,"option":"Die Veränderung von Variablen und Datenstrukturen in einem mittels\nfork()
erzeugten Kindprozess beeinflusst auch die\nDatenstrukturen im Elternprozess.
Nein, allgemein nicht, außer der Benutzer richtet dieses spezifisch\nein (Siehe shm_open(3)
), was aber ohne weiteres\nnicht der Fall ist.
Welche Aussage zu Prozessen und Threads ist richtig?
\n"},{"id":"gJEufQY9MVQkXjIuCe1z9w","question":"Welche der folgenden Informationen wird typischerweise in dem\nSeitendeskriptor einer Seite eines virtuellen Adressraums gehalten?
\n","source":"2023-02","options":[{"comment":"Ja, so setzt das Betriebsystem bspw. um, dass ein Text Segment\nausführbar aber nicht schreibbar ist.
\n","option":"Die Zugriffsrechte auf die jeweilige Seite (z. B. lesen, schreiben,\nausführen).
\n","correct":true},{"correct":false,"option":"Die Identifikation des Prozesses, dem die Seite zugeordnet ist.
\n","comment":"Nein, das Seiten existieren unabhängig von Prozessen und müssten per\nse nicht dafür benutzt werden, um logische Speicherräume\nauf Betriebsystemen mit unabhängigen Prozessen umzusetzen.
\n"},{"correct":false,"option":"Die Zuordnung zu einem Segment (Text, Daten, …).
\n","comment":"Nein, dieses wird muss man sich nicht in\ndem Seitendeskriptor merken, weil es nur wichtig ist, dass die Seite\nsich gemäß dem Verständnis von diesen Segmenten verhält (lesbar,\nausfübar, …).
\n"},{"correct":false,"comment":"Nein, diese Zuordnung findet nicht im Seitendeskriptor\nstatt, sondern im Betriebsystem.
\n","option":"Die Position der Seite im virtuellen Adressraum.
\n"}],"multiple":false},{"id":"XMRly4v1KUYUNuqHqGP6Mw","multiple":false,"options":[{"comment":"Nein, laufender Prozess gibt CPU mit Systemaufruf ab.
\n","option":"Bei kooperativem Scheduling sind Prozessumschaltungen unmöglich, wenn\nein Prozess in einer Endlosschleife läuft. Selbst wenn er bei\njedem Schleifendurchlauf einen Systemaufruf macht.
\n","correct":false},{"correct":false,"comment":"Nein, mit dem Begriff online
ist nicht gemeint,\ndass die Schedulingverfahren mit einem Netzwerk interagieren, sondern\neine Klasse von Algorithmen, welche ihre Daten zur Ausführungszeit\nerhalten, im Gegensatz zu offline
Algorithmen, welche von Anfang\nan alle Daten zur Verfügung haben.
Online-Schedulingverfahren sind für den Einsatz in Rechnern ohne\nNetzwerkschnittstelle ungeeignet.
\n"},{"comment":"Ja, spezifisch Timer-Interrupts werden dazu benutzt um selbst\nnicht-kooperative Programme unterbrechen zu können. Wenn diese\nAnkommen, welches die Ausführung zum Betriebsystem, und das\nBetriebsystem kann den Scheduler anstoßen, damit dieser\nbeliebige Prozesse ein- und auslagern kann.
\n","option":"Verdrängende Schedulingverfahren können nur mit Hilfe von\nUnterbrechungen realisiert werden.
\n","correct":true},{"comment":"Nein, es ist je nach Anwendung möglich diese zu vorhersagen\n(beispielsweise im Embedded-Kontext), wo die Verfahren dann durchaus\nrelevant sein können. Die zielt darauf hinaus zu verleiten, nur über\nDialog-Betrieb zu denken.
\n","option":"Deterministische Schedulingverfahren sind nur in der Theorie\nrelevant, da die genaue Länge der CPU-Stöße nie\nvorhergesagt werden kann.
\n","correct":false}],"source":"2021-07","question":"Welche der folgenden Aussagen über Schedulingverfahren ist\nrichtig?
\n"},{"options":[{"correct":true,"comment":"Ja, dieses ist der Fall für schwer- und leichtgewichtige Prozesse,\naber nicht mehr für federgewichtige, wo die\nSchedulingstrategie durch einen Scheduler im User-Space umgesetzt\nwird.
\n","option":"Bei schwergewichtigen Prozessen ist die Schedulingstrategie durch das\nBetriebssystem vorgegeben.
\n"},{"correct":false,"comment":"Nein, teilen sich einen Adressraum. Dieses wäre bei schwergewichtigen\nProzessen der Fall.
\n","option":"Jeder federgewichtige Prozess (User-Thread) und jeder\nleichtgewichtige Prozess (Kern-Thread) hat seinen eigenen, geschützten\nAdressraum.
\n"},{"option":"Bei Blockade eines schwergewichtigen Prozesses werden\nalle anderen schwergewichtigen Prozesse, die das selbe\nProgamm ausführen, ebenfalls blockiert.
\n","comment":"Nein, schwergewichtige Prozesse sind unabhängig voneinander, d.h. sie\nhaben einen eigenen Ausführungsfaden. Bei federgewichtigen Prozessen\nwürde das Problem bestehen (beschränkt auf den Kontext von einem\nProzess).
\n","correct":false},{"option":"Unabhängig von leichtgewichtigen Prozessen (Kernel-Threads) können\nfedergewichtige Prozesse (User-Threads) Multiprozessoren ausnutzen.
\n","comment":"Nein, federgewichtige Prozesse (engl. oft user threads
)\nkönnen höchstens so viele Kerne ausnutzen, wie es leichtgewichtige\nProzesse gibt, insofern der Scheduler auch darauf ausgelegt ist die\nfedergewichtigen Prozesse zwischen Kernen bzw. leichtgewichtigen\nProzessen hin und her zu schalten.
Welche der folgenden Aussagen zum Thema Prozesse und Threads ist\nrichtig?
\n","source":"2022-07"},{"options":[{"comment":"Nein, wie in der Hacking Übung gezeigt wird, ist es möglich\nüber den Speicher eines Arrays hinweg zu lesen und zu schreiben, was mit\ndem richtigem Wissen ausgenutzt werden kann. C als Sprache gibt\nnicht vor, welches verhalten richtig ist (Undefined\nBehaviour), und könnte prinzipiell zur Laufzeit oder insofern\nmöglich statisch vorhersagen ob es zu einem solchem Fehler kommt, und\ndas dann entsprechend Behandeln (wie im Fall von anderen Sprachen mit\nhöhere Typsicherheit: Java, Ada, Rust, …).
\nEin Fehler wie ein Segmentation-Fault hängt mit der\nSpeichervirtualisierung, und nicht mit dem Sprach-Konzept\neines Arrays zusammen, und muss daher nicht\nauftreten, wenn der Speicher hinter dem Array verfügbar ist, auch wenn\nder Inhalt aus sprachlicher Sicht nicht definiert ist.
\n","option":"Ein Pufferüberlauf eines lokalen Arrays wird immer zu\neinem Segmentation Fault führen und kann somit\nkeine sicherheitskritischen Auswirkungen haben.
\n","correct":false},{"correct":false,"comment":"Doch, aber diese sind nur nicht sichtbar (außer im Fall\nvon Lokalen Funktionen), und müssten als Speicherreferenzen übergeben\nwerden. Alternativ könnte man mit Wissen über die ABI die Adresse von\nVariablen aus einem anderem Stack Frame im gleichem Thread berechnen.\nAber inhärent gibt es allgemein hierzu keine Einschränkung\nmittels Speicherschutzmechanismen.
\n","option":"Es ist nicht möglich auf lokale\nautomatic
-Variablen zuzugreifen, die sich im Stack-Frame einer\nanderen Funktion befinden.
Bei rekursiven Funktionsaufrufen kann der Speicher des\nStack-Frames in jedem Fall wiederverwendet werden, weil die\ngleiche Funktion aufgerufen wird.
\n","comment":"Nein, das ist nur dann möglich wenn die Funktionen endrekursiv sind,\nund der Übersetzer in der Lage ist diese zu entrekursivieren (Tail\nCall Optimisation). Allgemein benötigen Rekursive Funktionen den\nSpeicher der mit jedem Aufruf angelegt wird, um ihr\nErgebnis zu bestimmen, bspw. eine naive Implementierung der\nFakultätsfunktion
\nunsigned fact(unsigned n)\n{\n if (n <= 1) {\n return 1;\n }\n return n * fact(n-1);\n}
\nSpeichert sich auf dem Stack alle Werte von\nn
bis 1
, und multipliziert diese am Ende\nzusammen beim Abwickeln des Aufrufbaums. Würde der Stack-Frame\nwiederbenutzt werden, würde jeder Aufruf die Speicherstelle\nüberschreiben wo der Wert von n
aus jedem\nvorherigem Aufruf auch gespeichert wäre, und das Endergebnis wäre damit\nverfälscht (in dem Fall wäre es n
quadriert).
Wenn in einem UNIX-Prozess mehrere Threads parallel laufen, benötigt\njeder von ihnen einen eigenen Stack.
\n","comment":"Ja. Wenn die Anzahl der Threads nicht statisch bekannt\nist (wie in C mit Pthreads im Allgemeinem der Fall ist), dann wird der\nSpeicher für jeden Thread dynamisch auf der Halde angelegt.
\n"}],"multiple":false,"id":"a6n3kGqrCeOhCeoDHp6bnA","question":"Für lokale Variablen, Aufrufparameter usw. einer Funktion wird bei\nvielen Prozessoren ein Stack-Frame angelegt. Welche Aussage ist\nrichtig?
\n","source":"2022-07"},{"source":"2022-07","question":"Welche der folgenden Aussagen zum Thema persistenter Datenspeicherung\nsind richtig?
\n","id":"q44G0kjUS7fn4B2fW6CWww","multiple":true,"options":[{"comment":"Nein, bei Zugriffen, die weiter hinten
gespeichert sind,\nkönnte es länger dauern.
Bei verketteter Speicherung dauert der wahlfreie Zugriff auf eine\nbestimmte Dateiposition immer gleich lang, wenn\nCachingeffekte außer Acht gelassen werden.
\n","correct":false},{"comment":"Ja.
\n","option":"Bei verketteter Speicherung mittels FAT-Ansatz kann die\nVerkettungsinformation redundant gespeichert werden, um die\nFehleranfälligkeit zu reduzieren.
\n","correct":true},{"correct":false,"option":"Journaling-Dateisysteme sind immun gegen defekte Plattenblöcke.
\n","comment":"Nein.
\n"},{"correct":false,"option":"Bei indizierter Speicherung kann es prinzipbedingt\nnicht zu Verschnitt kommen.
\n","comment":"Doch, es kann zu Verschnitt kommen, da der Speicher in\nBlöcke unterteilt wird. (Verschnitt: manche Speicherblöcke bei\nAufteilung von Daten können nur zum Teil gefüllt werden)
\n"},{"comment":"Ja, dynamisches Erweitern schwierig, weil es das umherbewegen ganzer\nDateien benötigen könnte, welche jeweils alle wieder in\nfreien, kontinuierlichen Speicherbereichen gelegt werden müssten. Das\nwird besonders dann erschwert, wenn mehre Prozesse versuchen lesend oder\nschreibend auf das Dateisystem zuzugreifen.
\n","option":"Bei kontinuierlicher Speicherung von Daten ist es unter Umständen mit\nenormem Aufwand verbunden, eine bestehende Datei zu vergrößern.
\n","correct":true},{"correct":false,"comment":"Nein. Allgemein hat die Positionierzeit nichts direkt mit dem\nDateisystem zu tun. Ein Dateisystem könnte so ausgelegt sein, um große\nSprünge des Festplatten-Armes zu vermeiden, bspw. bei kontinuierlicher\nSpeicherung.
\n","option":"Im Vergleich zu den anderen Verfahren ist bei indizierter Speicherung\ndie Positionierzeit des Festplatten-Armes beim Zugriff auf\nalle Datenblöcke einer Datei minimal.
\n"},{"comment":"Ja, mit Hilfe der Log-File.
\n","option":"Journaling-Dateisysteme garantieren, dass auch nach einem\nSystemausfall alle Metadaten wieder in einen konsistenten\nZustand gebracht werden können.
\n","correct":true},{"correct":true,"option":"Festplatten eignen sich besser für sequentielle als für wahlfreie\nZugriffsmuster.
\n","comment":"Ja, wegen dem Lese-Schreib-Kopf, der Daten, die nebeneinander stehen,\nschneller lesen kann, als Daten, die an verschiedenen Orten gespeichert\nsind.
\n"}]}]