Interrupt
In der Informatik versteht man unter einem Interrupt (englisch to interrupt, „unterbrechen“ nach lateinisch interruptus, dem Partizip Perfekt Passiv von interrumpere, unterbrechen) eine kurzfristige Unterbrechung der normalen Programmausführung,[1] um einen, in der Regel kurzen, aber zeitlich kritischen, Vorgang abzuarbeiten.
Das auslösende Ereignis wird Unterbrechungsanforderung (englisch Interrupt Request, IRQ) genannt. Nach dieser Anforderung führt der Prozessor eine Unterbrechungsroutine aus (auch Unterbrechungsbehandlung genannt, engl. interrupt handler, interrupt service routine oder kurz ISR). Die Unterbrechungsroutine wird (bei entsprechenden Prozessoren) mit erweiterten Privilegien ausgeführt. Im Anschluss an die Unterbrechungsroutine wird der vorherige Zustand des Prozessors (inkl. Privilegierung) wiederhergestellt und die unterbrochene Programmausführung dort fortgeführt, wo sie unterbrochen wurde.
Interrupts (genauer: Hardware-Interrupts) werden durch asynchrone externe Ereignisse ausgelöst.[2] Asynchron bedeutet in diesem Zusammenhang, dass die laufende Programmausführung nicht an immer der gleichen Stelle unterbrochen wird. Im Gegensatz dazu kann ein Interrupt bei vielen Prozessoren auch durch den laufenden Programmcode selbst mittels eines Maschinenbefehls ("INT nn") ausgelöst werden (Software-Interrupt). Effektiv ist dies eher mit einem Unterprogramm-Aufruf zu vergleichen; einzelne Betriebssysteme implementieren so Systemaufrufe.
Beispiele
Die Tastatur sendet eine Unterbrechungsanforderung, wenn eine Taste gedrückt wurde. Dazu wird ein Signal auf den Bus oder direkt an einen nur dafür vorgesehenen Prozessorpin (IRQ-Eingang) gelegt.[3] Die Unterbrechungsroutine kann daraufhin das jeweilige Zeichen von der Tastatursteuerung lesen und es an die jeweilige Anwendung weiterleiten.
Weitere Beispiele, bei denen Geräte eine Unterbrechungsanforderung generieren:
- Netzwerkkarte: wenn Daten empfangen wurden und im Puffer bereitliegen
- Festplatte: wenn die vorher angeforderten Daten gelesen wurden und abholbereit sind (das Lesen von der Festplatte dauert relativ lange)
- Grafikkarte: wenn das aktuelle Bild fertig gezeichnet wurde
- Soundkarte: wenn wieder Sound-Daten zum Abspielen benötigt werden, bevor der Puffer leer wird.
Geschichte
Ältere Computermodelle hatten keine Interrupts.[4] Um 1958 gab es erste Modelle mit Interrupts, ein Beispiel war die Electrologica X1.[5]
Zweck
Ein Interrupt dient dazu, auch während ein anderes Programm (z. B. eine Anwendung) abgearbeitet wird, auf eine Ein- oder Ausgabe (etwa von Tastatur, Festplatte, Netzwerk oder Zeitgeber) sofort reagieren zu können. Die Interface-Hardware muss nur einen Interrupt auslösen, wenn die nächste Operation auf dem Interface (Hardware) nicht möglich ist, beispielsweise bei Puffer leer (Ausgabe), Puffer voll (Eingabe), bei Fehlermeldungen der Interface-Hardware oder einem Ereignis ohne Datentransfer (z. B. Timer).
Vorteile gegenüber dem Polling
Neben Interrupts gibt es lediglich die Technik des programmierten (zyklischen) Abfragens (Polling), um den Status von Ein-/Ausgabegeräten, Prozessen oder anderem zu erfahren. Diese Methode ist zwar einfacher und benötigt keine zusätzliche Hardware, ist allerdings sehr viel ineffizienter als die Arbeit mit Interrupts, da sie die CPU sehr häufig in Anspruch nimmt. Zudem hängt die Reaktionsgeschwindigkeit beim Polling davon ab, wie viel Zeit zwischen den Abfragen vergeht, dies kann bei Situationen, die eine sofortige Reaktion verlangen, kritisch sein. Bei Multitasking-Betriebssystemen ist das Polling als alleinige Methode nicht möglich.
Die Standard-Analogie für Interrupts im Alltag ist eine Tür mit Klingel: Während man seine Aufgaben erledigt, kann man jederzeit durch die Klingel unterbrochen werden, wenn ein Gast eine „Abarbeitung“ wünscht, und sich ihm dann zuwenden. Beim Polling – also ohne Klingel – müsste immer wieder an die Tür gelaufen werden, um nachzuschauen, ob Besuch da ist oder nicht. Beim Erhitzen von Milch hingegen ist es wohl besser, nicht erst auf den „Interrupt“ des Überkochens zu warten, sondern den Prozess regelmäßig zu überwachen.
Anwendungsbeispiele
Als Beispiel für eine Anwendung von Interrupts kann man sich einen Prozessor vorstellen, der, nachdem er einer Hardwarekomponente einen Auftrag gegeben hat, nicht aktiv auf deren Antwort wartet (Polling), sondern so lange andere Aufgaben erledigt, bis ihn jene Hardwarekomponente von sich aus durch einen Interrupt wieder auf sich aufmerksam macht. Ohne Interrupts wären beispielsweise präemptive (=verdrängen von laufenden Programmen) Multitasking-Betriebssysteme unmöglich, da Programme ohne sie nicht mehr unterbrochen, vom Betriebssystem umgeschaltet (Timesharing) und Ein-/Ausgabegeräte nicht mehr bedient werden könnten.
Funktionsweise
Um ein Interrupt auslösen zu können, muss die an den Hauptprozessor (CPU) angeschlossene Hardware interruptfähig sein, d. h., bei Eintreffen eines bestimmten Ereignisses über die sogenannte Interrupt-Leitung ein Ausgangssignal (elektrische Spannung an einem Ausgangs-Pin) erzeugen. Die CPU hat im Allgemeinen getrennte Pins für maskierbare Interrupts (INTR) und nicht maskierbare Interrupts (NMI). Da bei nicht maskierbaren Interrupts zusätzlich noch die Interrupt-Nummer an die CPU übermittelt werden muss, haben viele Systeme einen Interrupt-Controller, an den diese Aufgabe delegiert wird, falls das Peripheriegerät das nicht selbst übernehmen kann.
Nicht maskierbarer Interrupt
Beim Auslösen des NMI maskiert die CPU die maskierbaren Interrupts und springt an eine vom CPU-Hersteller für NMI vorgegebene Adresse, die sich je nach Computer meist im Festwertspeicher befindet. Die dort hinterlegte ISR (Interrupt Service Routine) veranlasst dann meistens einen Neustart des Systems oder eine globale Fehlerbehandlung. Dies ist abhängig vom BIOS. Anwendungssoftware hat keinerlei Einfluss auf das Verhalten beim Eintreffen eines NMI. Auch die Systemsoftware kann nicht verhindern, dass ein NMI behandelt wird.
Maskierbarer Interrupt
Erscheint an diesem meistens mit NMI bezeichnete Pin ein Signal ([Vcc]) während Interrupts aktuell nicht maskiert sind (bei x86 ist dann das Interrupt-Flag (IF) gesetzt), so maskiert die CPU alle maskierbaren Interrupts und liest die Nummer des angeforderten Interrupts vom Systembus (Intel64-Hardware unterscheidet 256 Interrupt-Nummern). Dort muss der Anforderer die Nummer vor der Anforderung anlegen. Die CPU konsultiert damit dann die Interrupt-Vektortabelle und entnimmt dieser die Adresse der zugehörigen Interrupt-Service-Routine. Diese gehört zur Treibersoftware der auslösenden Hardware. Diese Routine muss bei Ausführung zuerst den gesamten gefährdeten Verarbeitungskontext, also die Prozessorregister, die sie benutzen wird, sichern. Anschließend erfolgt die eigentliche Behandlung des Interrupts und schließlich die Rückspeicherung des Kontextes und Rücksprung hinter die Anweisung, die zuletzt vor der Behandlung des Interrupts ausgeführt wurde. Beim Rücksprung erfolgt auch die Demaskierung der Interrupts. Dafür gibt es eine besondere Interrupt-Return-Anweisung aus dem CPU-Befehlssatz, die anstelle der normalen Return-Anweisung verwendet wird. Der Ablauf entspricht technisch insgesamt dem eines normalen Unterprogramm-Aufrufs mit ergänzender Behandlung der Interrupt-Maskierung.
Durch Software ausgelöster Interrupt
Bei vielen Prozessoren lässt sich die Interrupt-Behandlung auch durch einen Maschinenbefehl ("INT nn") auslösen. Ebenso wie bei Hardware-Interrupts erreicht der Prozessor bei der Behandlung der Unterbrechungsanforderung eine höhere Privilegierungsebene, mit der die Unterbrechungsroutine ausgeführt wird. So implementieren einzelne Betriebssysteme Systemaufrufe.
Latenz
Die Zeit zwischen dem Anlegen des IRQ-Signals und dem Beginn der entsprechenden Verarbeitung nennt man Latenz. Für einen IRQ der höchsten vergebenen Priorität hängt die Latenz vor allem von der Hardware ab – mit Schattenregistern kann der Kontextwechsel in einem Taktzyklus gelingen –, für IRQs mit geringerer Priorität von der Ausführungsdauer der bevorzugten Interrupt-Routinen. Echtzeitbetriebssysteme sind so organisiert und konfigurierbar, dass damit Echtzeitanforderungen leichter und beweisbar erfüllt werden können.
Maskierung
Unterbrechungsanforderungen können zeitweise von der CPU ignoriert werden, zum Beispiel wenn gerade ein anderer Interrupt behandelt wird. Dies kann für gewisse zeitkritische und synchronisierende Routinen z. B. in Gerätetreibern notwendig sein. Diese Maskierung gilt für alle Interrupts bis auf die nicht maskierbaren (NMI: Non Maskable Interrupt), die für spezielle Fälle vorgesehen sind (Stromausfall, Hardwarefehler usw.), und für die sogenannten Software-Interrupts, die durch einen Befehl in einem Programm ausgelöst werden (z. B. 'int IRQNUMMER' bei x86 – dieser Befehl wird beispielsweise von Linux genutzt, um von normalen Anwendungen über Systemaufrufe (syscalls) in den Kernel-Modus zu wechseln).
Asynchronität
Externe Interrupts (Hardwareinterrupts) sind gegenüber dem unterbrochenen Programm grundsätzlich asynchron, d. h., die Ausführung des Programms befindet sich an einer unbestimmten Stelle, wenn der Interrupt auftritt. Daher dürfen Interrupts ohne besondere synchronisierende Maßnahmen keinen direkten Einfluss auf Programme (oder Programmvariablen) oder auf Geräte (z. B. Festplatten) ausüben. ISRs sind keine Tasks im Sinne des Betriebssystems. Für ISRs ist weiter darauf hinzuweisen, dass nur mit besonderen Softwarekonzepten innerhalb der ISR die Interruptmaskierung aufgehoben (Interrupt enable) werden darf, da sowohl eine Interruptschachtelung durch fremde ISRs als auch eine Wiedereintrittsmöglichkeit (Reentrance) des gleichen Interrupts geschaffen wird.
Einige Prozessoren kennen spezielle Befehle, um sogenannte „Software-Interrupt“ aus einem laufenden Task heraus auszulösen, die außer den besonderen Ein- und Rücksprungbedingungen wie Unterprogrammaufrufe wirken und daher auch nicht asynchron sind. Das Gleiche gilt für Traps, die von der CPU bei Fehlern (geschützte Zugriffe, verbotene Instruktionen (z. B. Division durch Null), Singlestep Debugging, Memory-Management-Ereignisse, aber auch als Standard-Schnittstelle zu Betriebssystem-Aufrufen usw.) selbst ausgelöst werden und sinnvollerweise den gleichen Mechanismus benutzen.
Interrupt-Service-Routinen als Programmierprinzip
Insbesondere bei hardwarenahen ereignisgesteuerten Anwendungen, wie sie in eingebetteten Systemen üblich sind, ist eine mögliche Vorgehensweise, mehr oder weniger die gesamte Funktionalität des Systems in die Interrupt-Routinen bzw. in von diesen angestoßene Tasks zu verlegen. Der Prozessor kann dabei typischerweise in einen energiesparenden Ruhezustand (Idle State oder Leerlauf) versetzt werden, aus dem er bei Interruptanforderungen (also bei externen Ereignissen) erwacht. Das Hauptprogramm besteht im Extremfall nur noch aus einem Initialisierungsteil, welcher nach dem Systemstart durchlaufen wird, gefolgt von einer Endlosschleife, in der – abgesehen vom Aktivieren des o. g. Ruhezustands – nichts passiert.
Ablauf
Im Interruptzyklus der CPU wird der alte (unterbrochene) Befehlszähler-Stand (bei Intel Codesegment und Instruction Pointer) und bei einigen Architekturen auch das Statusregister auf dem Stack gespeichert. Nun muss bestimmt werden, welche Quelle die Unterbrechungsanforderung ausgelöst hat. Bei den meisten CPUs wird die Quelle innerhalb des Interruptzyklus über einen Wert auf dem Datenbus, der üblicherweise vom Interrupt-Controller gesetzt wird, identifiziert, dadurch der zugehörige Interruptvektor gefunden und der Sprung zu der passenden Unterbrechungsroutine (ISR) ausgelöst. Vor oder während der ISR muss noch die bearbeitete Unterbrechungsanforderung (IRQ) gelöscht werden, damit sie nicht erneut ausgelöst wird. Bei Intel(=PC)-kompatiblen Architekturen erfolgt dies durch Input/Output-Instruktionen innerhalb der Unterbrechungsroutine. So können u. U. ohne besondere Maßnahmen in der Software wegen der kurzen Laufzeit bis zur Löschinstruktion auch echte IRQs mit gelöscht werden. Bei einigen CPU-Architekturen, insbesondere bei Mikrocontrollern, kann es mehrere Interrupteingänge geben, wobei hier der Interrupt-Controller schon integriert ist. Bei einfachen CPUs erfolgt nur der IRQ und der Interruptzyklus, wobei per Software überprüft werden muss, welche Quelle der Auslöser war und dementsprechend welche Routine abzuarbeiten ist.
Stehen bis zum Zeitpunkt des Interruptzyklus mehrere IRQs von mehreren Quellen an, so wird mittels eines Auswahlverfahrens durch die Hardware (Interrupt-Controller) der Vektor der wichtigsten Unterbrechungsanfrage bestimmt und abgearbeitet. Im Anschluss folgt die Bearbeitung der anderen noch anstehenden IRQs.
Prinzipieller Ablauf beim Auftreten einer Unterbrechungsanfrage (Übergang von Hardware auf Software):
- Solange entweder der Interrupteingang der CPU oder der Einzelinterrupt auf dem Interrupt Controller maskiert ist, passiert nichts weiter. Interruptanforderungen werden auch nur nach Ablauf der gerade laufenden Instruktion akzeptiert. Normalerweise bleiben Interruptanforderungen bestehen, bis sie akzeptiert werden.
- Hardware (Interruptlogik des Interrupt-Controllers) bestimmt den Interruptvektor des aktivierten IRQs mit der höchsten Priorität, der nicht maskiert ist.
- Die CPU akzeptiert die Unterbrechungsanforderung und führt den Interruptzyklus durch, in dessen Verlauf (je nach CPU) der Interruptvektor vom Datenbus gelesen wird. Danach wird der Interrupteingang automatisch maskiert und somit gesperrt, damit nicht beliebig viele geschachtelte Interruptsequenzen auftreten können und den Stack überlaufen lassen.
- Im Interruptzyklus der CPU wird der alte (unterbrochene) Befehlszähler-Stand (bei x86 Codesegment cs und Instruction Pointer eip) und bei einigen Architekturen auch das Statusregister auf dem Stack gespeichert. Der neue Befehlszählerstand wird aus bestimmten Speicherstellen oder aus einer Interrupttabelle gelesen, deren Index aus dem Interruptvektor bestimmt wird. Die Vektoren selbst stellen im letzteren Fall jedoch nicht die indirekten Einsprungadressen dar.
- Die Software der Interrupt-Service-Routine (ISR) startet und muss zunächst die Inhalte aller Register, die sie selbst benutzen wird (ggf. auch das Statusregister, wenn es nicht automatisch gesichert wurde) auf den Stack kopieren, da sonst die Daten der unterbrochenen Tasks nicht wiederhergestellt werden können. (Wenn dabei Fehler gemacht werden, führt das zu zufälligen Fehlerauswirkungen in fremden Programmen, die nur schwer verfolgt werden können!)
- Die eigentliche Interrupt-Service-Routine läuft nun ab. Je nach Aufgabe werden z. B. Ein- und/oder Ausgabendaten gepuffert z. B. in einem Ringpuffer; hierbei gehen üblicherweise Zeitbezüge verloren, nicht aber Reihenfolgen. Bei Bedarf kann evtl. nach Aufruf einer speziellen Betriebssystemfunktion durch die ISR ein entsprechender Task durch den Scheduler des Betriebssystems gestartet (geweckt) werden. Da das eine Zeit dauert, kann evtl. zwischenzeitlich der gleiche Interrupt erneut auftreten, was im Algorithmus der ISR zu berücksichtigen ist, falls die Interrupts nicht ohnehin maskiert bleiben.
- Die Software der ISR stellt alle von ihr gesicherten Register wieder her (englisch to restore).
- Die ISR beendet sich durch einen Rücksprung (RTI), der das Rückspeichern des alten Befehlszählers und ggf. des alten Statusregisters vom Stack bewirkt und der dadurch wieder seinen Stand wie vor der Unterbrechung hat (so als wäre nichts gewesen). Durch die Rückspeicherung des Statusregisters (das auch das Interrupt-Mask-Bit enthält) ist die Interruptlogik unmittelbar bereit, weitere IRQs zu akzeptieren.
- Die aufgerufene Task kann nun die weitere Bearbeitung der gepufferten Daten übernehmen.
Kategorisierung von Interrupts
Es wird zwischen präzisen Interrupts und unpräzisen Interrupts unterschieden. Präzise Interrupts halten die Maschine in einem wohldefinierten Zustand, unpräzise nicht.[6]
Ein Software-Interrupt ist ein Programmbefehl, der so wirkt wie ein Hardware-Interrupt, man spricht von einem expliziten Interrupt-Auftrag. Ein Hardwareinterrupt wird dagegen von außen über einen IRQ-Kanal oder -Pin an den Prozessor eingeleitet.[1]
Auch nach ihrem Auslöser werden Interrupts unterschieden:[7]
- Die Ein-/Ausgabegeräte können ein Signal schicken, dass sie mit ihrer Aufgabe fertig sind oder einen Fehler hatten.
- Das Programm kann durch arithmetischen Überlauf, das Teilen durch Null, den Versuch, einen unerlaubten Maschinencode auszuführen, oder eine Referenz auf ein Ziel außerhalb des erlaubten Bereichs einen Interrupt auslösen. Hierbei schlägt eine prozessorinterne Fehlererkennung an und aktiviert den Interrupt auf prozessorinternen, aber rein hardwaremäßigen Signalwegen.
- Der Timer erlaubt dem Betriebssystem, Aufgaben regelmäßig zu erledigen. Dazu werden laufende Programme unterbrochen. So kann ein Timer sowohl in den Prozessor eingebaut sein als auch als externer Baustein vorliegen, in beiden Fällen wirkt sein Ablaufen wie ein Ein-/Ausgabeereignis.
Ein weiterer Unterschied besteht in der Realisierung auf der signalverarbeitenden Ebene:
- Bei level-sensitiven Interrupts reagiert der Prozessor anhaltend und solange auf ein Interrupt-Signal, wie dessen vorgesehener Logikpegel anliegt, aktiv-high und aktiv-low sind mögliche Umsetzungen.
- Bei flanken-sensitiven Interrupts wird das Ereignis durch den Wechsel des Logikpegels selbst angezeigt und dann vom Prozessor für eine vorgegebene Zeitspanne gehalten, normal sind einige wenige Taktzyklen.
Prozessor-Interrupts werden auch als Exceptions bezeichnet und können in drei Typen eingeteilt werden:[8]
- Aborts sind sehr wichtige Fehler, z. B. Hardwarefehler,
- Fehler (Faults) treten vor Abschluss einer Anweisung auf,
- Traps treten nach Abschluss einer Anweisung auf (Einsatz beim Debuggen).
Hardware-Beispiel x86-Architektur
Alle Intel-Prozessoren haben einen Interrupt-Signaleingang für maskierbare Interrupts. Um mehrere Interruptquellen anschließen zu können, gibt es einen eigenen Interrupt-Controller-Baustein (z. B. den Programmable Interrupt Controller, PIC), der mehrere Interrupt-Eingänge besitzt und zu einem Signal zusammenführt. Außerdem ist er über interne Register konfigurierbar, sodass er je nach ausgelöstem Interrupt im CPU-Interruptzyklus verschiedene, vorgegebene Interruptvektoren auf den Bus legt, die die CPU dann einliest. Bei neueren Prozessoren sind all diese Funktionalitäten mit in den Kern des Hauptprozessors integriert.
Bei x86-Prozessoren sind 256 verschiedene Interruptvektoren möglich. Der Interruptvektor wird im Interruptzyklus des Prozessors als 8-Bit-Wert vom Datenbus gelesen. Bei x86-Prozessoren sind die Vektoren selbst nicht die indirekten Einsprungadressen. Der Vektor wird vielmehr im Real-Mode mit 4 multipliziert (binäres Verschieben), damit für jeden Vektor 32-Bit-Sprungadressen untergebracht werden können, zu denen dann gesprungen wird. Im Protected-Mode wird mit 8 multipliziert, weil ein Deskriptoreintrag 8 Bytes lang ist. Im Real Mode befindet sich die Interrupttabelle in dem ersten Kilobyte des Hauptspeichers (0000h:0000h-0000h:03FFh). Jede Interruptnummer benötigt 4 Bytes: 2 Bytes für das Codesegment und 2 für den Offset innerhalb des Segments. Im Protected Mode der CPU wird die Position der Tabelle durch die Interrupt-Deskriptor-Tabelle festgelegt. Hier werden für jeden Interrupt 8 Bytes für den Deskriptor-Eintrag der ISR benötigt.
Bei modernen Systemen (zum Beispiel PCI-Systemen) können sich in der Regel mehrere Geräte einen Interrupteingang teilen (Interrupt-Sharing genannt). Die Behandlungsroutine für einen solchen Interrupt muss dann alle Treiber, deren Geräte diesen Interrupt ausgelöst haben könnten, aufrufen (am IRQ kann dies nicht festgestellt werden). Dabei kann es zu Problemen kommen, wenn einzelne Treiber zu lange aktiv sind, und in der Zwischenzeit im Gerät, welches den Interrupt ursprünglich ausgelöst hat, beispielsweise der Puffer voll wird und überläuft. Im schlimmsten Fall führt dies zu einem Datenverlust.
Bei modernen Peripheriegeräten vergeben der Computer und das Betriebssystem selbst die IRQ-Nummern (PnP = Plug-and-Play-Geräte); während bei alten Steckkarten, beispielsweise bei ISA-Karten, die IRQ-Eingänge von Hand eingestellt werden müssen oder fest auf den Karten verdrahtet sind.
Unter Linux kann man die Interrupts mit folgendem Befehl abfragen: cat /proc/interrupts
Unter Windows (XP und neuer) kann man die Interrupts mit folgendem Befehl abfragen: msinfo32.exe
→ Hardwareressourcen → IRQs
IRQ | Verwendung |
---|---|
0 | System-Taktgeber |
1 | Tastatur |
2 | Kaskadiert zu IRQ 9 (für 8–15) |
3 | COM 2, 4, 6, 8 (EIA-232/RS-232) |
4 | COM 1, 3, 5, 7 |
5 | LPT 2 (IEEE 1284) oder Soundkarte |
6 | Diskettenlaufwerk (Floppy) |
7 | LPT 1 |
8 | Echtzeituhr (RTC) |
9 | Zu IRQ 2 umgeleitet (aber auch VGA und NIC, IRQ 16–23) |
10 | Frei ggf. PCI-Bus |
11 | Frei ggf. Adaptec-SCSI |
12 | PS/2 (Maus, andere Eingabegeräte) |
13 | Mathematischer Coprozessor (FPU) |
14 | Primärer IDE oder ATA |
15 | Sekundärer IDE oder ATA |
Siehe auch
Weblinks
Einzelnachweise
- A. Metzlar: BIOS. Das Praxisbuch. Franzis, 2004, ISBN 978-3-7723-6706-9, S. 379.
- W. Stallings: Operating Systems: Internals and Design Principles. Prentice Hall International, 2000, ISBN 978-0-13-031999-9, S. 136.
- A. Tanenbaum: Moderne Betriebssysteme. Pearson Studium, 2009, ISBN 978-3-8273-7342-7, S. 406.
- W. Stallings: Operating Systems: Internals and Design Principles. Prentice Hall International, 2000,ISBN 978-0-13-031999-9, S. 62.
- E. W. Dijkstra: My recollection of operating system design. (PDF; 1013 kB) EWD 1303, 2000, S. 15
- A. Tanenbaum: Moderne Betriebssysteme. Pearson Studium, 2009, ISBN 978-3-8273-7342-7, S. 109.
- W. Stallings: Operating Systems: Internals and Design Principles. Prentice Hall International, 2000, ISBN 978-0-13-031999-9, S. 17.
- A. Metzlar: BIOS. Das Praxisbuch. Franzis, 2004, ISBN 978-3-7723-6706-9, S. 85.