Was ist der Unterschied zwischen Kontextwechsel und Interruptbehandlung?

Ich bin ein Embedded-Entwickler. Ich habe nicht mit RTOS/Linux gearbeitet. Ich ging RTOS-Konzepte durch, als ich über „Kontextwechsel“ stolperte. Ich verstehe, dass beim Kontextwechsel alle Register zusammen mit PC (Programmzähler) im Stapel gespeichert werden, bevor ein anderer Thread in den Prozessor geladen wird. Geschieht nicht etwas Ähnliches, wenn ein Interrupt auftritt (in einem Controller, der kein Betriebssystem verwendet)?

Wie unterschiedlich sind diese beiden Begriffe?

AFAIK, auf den meisten Mikrocontrollern erfolgt die Kontextspeicherung bei einem Interrupt in der Hardware, während die Kontextspeicherung in einem RTOS in der Software erfolgt
Ein Interrupt-Handler muss möglicherweise nicht den gesamten Thread-Zustand speichern (er hat relativ wenig Arbeit zu tun). Einige ISAs stellen Shadow/Banked (MIPS/ARM)-Register bereit, um Overhead beim Sichern/Wiederherstellen zu vermeiden oder automatisch eine begrenzte Menge an Status zu speichern (was vergleichbar ist mit Shadow/Banked-Registern). (Übrigens erweitert MIPS MultiThreading Application Specific Extension Shadow Register Sets (31 GPRs) in Thread-Kontexte.) [Zu kurz für eine Antwort, aber eine schnelle Antwort.]
Jedem Kontext ist normalerweise ein eigener Stapel zugewiesen, sodass es schneller ist, zu ihnen zu wechseln, als alle Registerwerte vor dem Umschalten auf dem Stapel speichern und sie danach ausgeben zu müssen. Die Interrupt-Handler in einem Mikrocontroller müssen dies oft manuell im Code tun, aber wenn Sie ein RTOS auf dem Mikrocontroller wie uCOS-II/III von Jean C. Labrosse verwenden, hat jede Aufgabe/jeder Kontext seinen eigenen Stack und „Kontext“.
@PaulA.Clayton können Sie Ihre Antwort erläutern, ich habe keine Ahnung, wie ein Thread läuft, nur ein Verständnis auf höchster Ebene. trotzdem danke

Antworten (2)

Es gibt keinen grundlegenden Unterschied, es ist eher eine Frage des Grades – der Menge an Kontext, die gespeichert werden muss.

Wenn ein RTOS-Thread-Kontextwechsel auftritt, muss der gesamte CPU-Zustand, den ein Thread verwenden könnte, gespeichert werden. Dies umfasst normalerweise alle CPU-Register, einschließlich Flag- oder Statusregister, sodass der Thread nach ihrer Wiederherstellung fortgesetzt wird, als ob nie etwas passiert wäre.

Wenn ein Interrupt auftritt, gibt es immer noch einen Kontextwechsel, aber nur der Kontext, den der Interrupt-Handler tatsächlich verwenden muss, muss gespeichert und anschließend wiederhergestellt werden. Wenn Sie Ihren Interrupt-Handler in einer Hochsprache schreiben, entspricht dies ziemlich genau einem vollständigen Thread-Kontextwechsel, da es keine Einschränkungen dafür gibt, welche Ressourcen ein solcher Interrupt-Handler berühren könnte. Wenn Sie Ihren Interrupt-Handler jedoch in Assemblersprache schreiben, können Sie genau verfolgen, welche Register er berührt, und nur diese speichern. Dadurch kann die Ausführung des Interrupt-Handlers extrem schnell erfolgen, was seine Auswirkungen auf den Rest des Systems verringert und/oder ihm ermöglicht, Interrupts mit einer höheren Rate zu verarbeiten.

Selbst wenn ein Interrupt-Handler in einer Hochsprache geschrieben ist, kann der Compiler, wenn der Handler keinen externen Code aufruft, von dem der Compiler nichts "kennt", Code zum Speichern/Wiederherstellen von Registern generieren, der diese Register ignoriert werden vom Interrupt-Handler selbst nicht verwendet. Da die Natur eines "vollständigen" Kontextwechsels darin besteht, die Ausführung beliebigen Codes zu ermöglichen, muss er alle Register speichern/wiederherstellen, unabhängig davon, ob der Compiler etwas weiß, das sie tatsächlich verwendet.

Sowohl Interrupts als auch Kontextwechsel sind Interrupts. Der Hauptunterschied besteht darin, was nach dem Interrupt oder Kontextwechsel passiert.

Bei einem Interrupt wird der aktuelle Zustand (oder Kontext) in einem temporären Bereich (normalerweise, aber nicht immer, dem Stack) gespeichert. Die ISR erledigt dann ihre Aufgabe, und der Zustand wird dann wiederhergestellt und die Interrupt-Routine kehrt zurück. Das Entscheidende dabei ist, dass die ISR genau dort ansetzt, wo sie im selben Thread aufgehört hat .

Ein Kontextwechsel sieht genauso aus wie ein Interrupt. Der Zustand wird wie gewohnt im Stack gespeichert. Der Speicherort dieses Stacks und alle zusätzlichen Zustandsinformationen werden jedoch an anderer Stelle (im Thread ) gespeichert . Ein neuer Datensatz von einem anderen Thread wird dann durch die aktuellen Daten ersetzt und die ISR kehrt zurück. Hier kehrt die ISR jedoch nicht dorthin zurück, wo sie aufgehört hat, sondern dorthin zurück, wo der neu eingeschaltete Thread unterbrochen wurde, als während seiner Ausführung das letzte Mal ein Kontextwechsel stattfand.

Es ist diese Änderung des Rückkehrortes und der Daten, die, abgesehen davon, was der Inhalt der ISR sein kann, eine ISR von einem Kontextwechsel unterscheidet.