Die Artikel Interrupt, Unterbrechungsanforderung und Unterbrechungsroutine überschneiden sich thematisch. Hilf mit, die Artikel besser voneinander abzugrenzen oder zu vereinigen. Bitte äußere dich in der Diskussion über diese Überschneidungen, bevor du diesen Baustein entfernst. Nachtigall 14:53, 5. Mai 2007 (CEST) |
In der Informatik versteht man unter Interrupt (lat. interruptus, Unterbrechung) die kurzfristige Unterbrechung eines Programms, um eine andere, meist kurze, aber zeitkritische Verarbeitung durchzuführen.
Das auslösende Ergeignis wird Unterbrechungsanforderung (Interrupt Request, IRQ) genannt. Danach wird die Unterbrechungsroutine (Interrupt Service Routine, ISR) ausgeführt. Anschließend wird die Ausführung des Programms an der Unterbrechungsstelle fortgesetzt.
Inhaltsverzeichnis |
Sinn eines Interrupts ist es, auf Ein-/Ausgabe-Ereignisse (Signale) (z. B. von Tastatur, Maus, Festplatte, Netzwerk, Zeitgeber/Timer usw.) (schnell) reagieren zu können, während ein anderer Programmcode (z. B. von Anwendungsprogrammen) abgearbeitet wird. Von der Interface-Hardware wird nur ein Interrupt ausgelöst bzw. ist nur dann erforderlich, 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 selbst ohne Datentransfer (z. B. Timer).
Neben Interrupts gibt es lediglich die Technik des programmierten (zyklischen) Abfragens (Polling), um den Status von Ein-/Ausgabegeräten, Prozessen, etc. zu erfahren. Diese Methode ist zwar einfacher und benötigt keine zusätzliche Hardware, ist jedoch auch wesentlich ineffizienter als das Arbeiten mit Interrupts, da dabei ständig CPU-Leistung belegt wird. Bei Multitasking-Betriebssystemen ist das Polling als alleinige Methode nicht möglich.
Ein Beispiel für eine Anwendung von Interrupts lässt sich bei einem Prozessor darstellen, der, nachdem er einen Auftrag an eine Hardwarekomponente ausgegeben hat, nicht aktiv auf die Antwort warten muss (Polling), sondern in der Zwischenzeit andere Aufgaben erledigen kann, um später mittels Interrupt durch jene Hardwarekomponente wieder zu dieser Ein-/Ausgabeaktion zurückgeholt zu werden. Ohne Interrupts wären beispielsweise auch präemptive (=verdrängen von laufenden Programmen) Multitasking-Betriebssysteme nicht möglich, da Programme sonst nicht mehr unterbrochen, vom Betriebssystem umgeschaltet (Timesharing) und Ein-/Ausgabegeräte nicht mehr bedient werden können.
Ausgelöst werden externe Interrupts (Hardwareinterrupts) durch Elektronikkomponenten (Interrupt-Controller) mittels eines so genannten Interrupt-Requests (=IRQ, „Unterbrechungsanforderung“), einer Signalisierung an den Interrupt-Signaleingang der CPU. Wenn eine Unterbrechungsanforderung von der CPU angenommen wird (nach dem Ende einer laufenden Instruktion und sofern der Interrupt nicht deaktiviert („maskiert“) ist), läuft eine feste Sequenz, der Interruptzyklus, ab. 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 gesichert. Nun muss die auslösende Quelle der Unterbrechungsanforderung bestimmt werden. 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 Interrupt-Service-Routine (ISR) ausgelöst. Vor oder während der ISR muss noch der bearbeitete IRQ gelöscht werden, damit er nicht erneut ausgelöst wird. Bei Intel(=PC)-kompatiblen Architekturen erfolgt dies durch I/O-Instruktionen innerhalb der ISR. (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 auch 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 (meist durch Prioritätsverfahren, seltener durch Zufallsverfahren; jedoch nicht nach einer Reihenfolge). Im Anschluss folgt die Bearbeitung der anderen noch anstehenden IRQs.
Durch Hardware ausgelöste (externe) Interrupts sind durch eine spezielle Instruktion insgesamt maskierbar, d. h. die Annahme kann durch Software unterbunden (maskiert) bzw. wieder freigegeben werden. (Das kann für gewisse zeitkritische und synchronisierende Routinen z. B. in Gerätetreibern notwendig sein.) Bei den meisten CPU-Architekturen sind für Sonderfälle (Stromausfall, Speicherfehler usw.) auch nicht-maskierbare Interrupts (non maskable I. =NMI) implementiert, die immer einen Sprung des Prozessors in die Interruptroutine auslösen. Ohne besondere Maßnahmen können diese NMIs auch ihre eigene Service-Routine (ISR) unterbrechen, was zu erheblichen Softwareproblemen führen kann. Damit dies nicht bei normalen (maskierbaren) Interruptanfragen passiert, maskiert die Interruptlogik in der CPU im normalen Interruptzyklus noch vor dem Einsprung in die ISR die Interrupts automatisch aus. Nach Ausführung der ISR wird mit dem Rücksprung in das unterbrochene Programm immer der alte Zustand (durch Rückspeicherung des Statusregisters) wiederhergestellt.
Externe Interrupts sind gegenüber dem unterbrochenen Programm grundsätzlich asynchron, d. h. sie treten zu einem unbestimmten Zeitpunkt auf. Daher dürfen Interrupts ohne besondere synchronisierende Maßnahmen keinen direkten Einfluss auf Programme (oder Programmvariablen) oder auf Geräte (z. B. Harddisk) 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 so genannte Software-„Interrupts“ aus einer 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.
Insbesondere bei hardwarenahen ereignisgesteuerten Anwendungen, wie sie z. B. in eingebetteten Systemen üblich sind, wird u. U. praktisch die Programmausführung des Systems in die Interrupt-Routinen (bzw. in von diesen angestoßene Tasks) verlegt. Der Prozessor wird in einen energiesparenden Schlafzustand (Idle State) gelegt, aus dem er bei Interruptanforderungen (also bei externen Ereignissen) erwacht – das eigentliche ‚Hauptprogramm‘ besteht dann 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. Schlafzustands) gar nichts passiert.
Prinzipieller Ablauf beim Auftreten einer Unterbrechungsanfrage (Übergang von Hardware auf Software):
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 (Datenverarbeitung) 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 Descriptoreintrag 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.