In vielen Referenzen zu Betriebssystemen wird angegeben, dass bei kooperativem (im Gegensatz zu präventivem) Multitasking ein Prozess die CPU so lange hält, bis er sich explizit freiwillig ausschaltet. Wenn ein laufender Prozess eine E / A-Anforderung ausführt, die nicht sofort erfüllt werden kann (z. B. eine noch nicht verfügbare Tastatureingabe), setzt der Scheduler sie dann aus oder behält er die CPU tatsächlich bei, bis die Anforderung bearbeitet werden kann?
[Bearbeitet, um "Blöcke auf E / A" durch "Führt eine E / A-Anforderung aus, die nicht sofort erfüllt werden kann."]
operating-systems
process-scheduling
Ellen Spertus
quelle
quelle
Antworten:
In einer wirklich "kooperativen" Umgebung und ohne Hardwareschutz könnte ein Prozess die E / A blockieren und die Steuerung erst wieder freigeben, wenn die E / A ausgeführt wurde (oder die Steuerung überhaupt nicht freigeben). Windows 3.1 sah beispielsweise so aus: Wenn ein einzelner Benutzerprozess den gesamten Computer übernehmen und verhindern wollte, dass etwas anderes ausgeführt wird, könnte dies der Fall sein.
Auf einem System mit Multitasking erwarten Sie jedoch, dass die E / A-Befehle der System-API die Kontrolle über den Prozessor abgeben, wenn sie aufgerufen werden. Wenn ein ausgeführter Prozess die E / A blockiert und davon ausgegangen wird, dass der Prozess die normalen System-APIs verwendet, können andere Prozesse ausgeführt werden, bis die E / A abgeschlossen ist, und der ursprüngliche Prozess wird schließlich fortgesetzt, sobald die E / A abgeschlossen ist . Mit anderen Worten, das Aufrufen einer blockierenden E / A-Funktion ist eine Möglichkeit, mit der sich ein Prozess in einem kooperativen System freiwillig aussetzen kann.
quelle
Das Blockieren von E / A entspricht in etwa dem Anhalten Ihres Prozesses. Im Kontext des Linux-Kernels führt die Ausführung eines E / A-Systemaufrufs, wie z. B.,
read()
dazu, dass einsysenter
oder ein Interrupt-Handler ausgelöst wird, um nach diesem E / A zu suchen, unddo_sys_read()
letztendlich aufruft . Wenn hier die aktuelle Anfrage nicht sofort erfüllt werden kann, ruftsched()
die Funktion auf, die dann einen anderen Prozess ausführen kann.Im Kontext eines kooperativen Systems würde ich erwarten, dass der Kernel, wenn Sie aus irgendeinem E / A-Grund einen Systemaufruf ausführen, eine andere Aufgabe auswählt und diese ausführt, wenn die Anforderung nicht erfüllt werden kann. Dieses Dokument bietet Hintergrundinformationen. Wenn Sie auf E / A gewartet haben, können Sie für immer auf diese E / A warten. Die Idee der kooperativen Zeitplanung ist, dass Sie häufig
sched()
die Methode "Relinquish-the-CPU" oder die entsprechende Methode aufrufen, wenn Sie CPU-intensive Aufgaben ausführen.Überlegungen zum Kernel-Modus werden interessanter. Auf Architekturen, auf denen sie verfügbar sind, wie z. B. auf bestimmten eingebetteten Plattformen , werden Interrupt-Handler weiterhin als Reaktion auf Hardware- oder Software-Interrupts aufgerufen. Es ist normalerweise möglich, die Interrupt-Behandlung implementierungsseitig zu deaktivieren , aber das hat auch Nachteile.
quelle
In dem kooperativen Planungsmodell (vorzugsweise
cooperative multitasking
) gibt es kein Konzept eines Planers in dem Sinne, dass das Betriebssystem keine Kontrolle darüber hat, wie lange der Prozess ausgeführt wird.Eine richtig programmierte Anwendung würde die CPU freiwillig auf E / A verzichten. Schlecht geschriebene Anwendungen warten jedoch möglicherweise nur auf E / A und blockieren so andere Prozesse.
PS: Dieser Ansatz wurde später von den meisten Betriebssystemen zugunsten von Preemptive-Scheduling (das über einen externen Scheduler verfügte) aufgegeben, und jetzt haben wir alle möglichen unterschiedlichen Scheduling-Algorithmen, die von verschiedenen Betriebssystemen verwendet werden.
EDIT: Meine Antwort basierte auf der Planung, wie sie in ihrer ursprünglichen Form beschrieben wurde (vor Jahren: P). Wie Gilles bemerkte, verwenden einige Systeme immer noch kooperatives Scheduling. Und es gibt einen Scheduler. Ich bin nicht sicher, ob diese Systeme COS in seiner reinen und ursprünglichen Form verwenden.
quelle
Kooperatives Multitasking impliziert, dass ein ausführender Kontext die Kontrolle explizit an den Scheduler abgeben muss und auf Wunsch einen Kontextwechsel verhindern kann.
Die meisten Implementierungen führen explizit eine Kontextumschaltung für jeden Systemaufruf durch, der nicht umgehend zurückgegeben wird, und häufig auch, wenn dies der Fall ist, um die Fairness der Prozessorzuweisung zu erhöhen.
In der Regel ist es nur möglich, dass fehlgeschlagene Prozesse (oder die absichtliche Verweigerung des Dienstes für den Rest des Systems) ein häufiges Wechseln von Aufgaben verhindern.
Pre-Emission ist, wie Gilles erklärt, eine Einschränkung der Systemarchitektur, die eine zeitgesteuerte Unterbrechung der aktiven Task und erzwungene Kontextwechsel verhindert.
quelle