
Wir untersuchten Multitasking, die Eigenschaft des Betriebssystems, mehrere quasi unabhängige Programme gleichzeitig auszuführen. Bevor wir uns die Aufgaben genauer ansehen, müssen wir uns mit den Begriffen befassen.
Frühere Artikel in der Reihe:
Artikel 2. RTOS: Struktur und Echtzeitmodus
Artikel 1. RTOS: Einführung.
Wir verwenden das Wort "Aufgabe", obwohl es keine genaue Bedeutung hat. Andere Begriffe, "Fluss" und "Prozess", sind spezialisierter, und Sie sollten verstehen, was sie bedeuten und wie sie sich unterscheiden.
Viele in eingebetteten Anwendungen verwendete RTOSs verwenden ein Multithread-Modell. Es können mehrere Threads gleichzeitig ausgeführt werden, die denselben Adressraum belegen:

Dies bedeutet, dass das Umschalten des Kontexts in erster Linie das Umschalten von einem Satz von Prozessorregistern zu einem anderen bedeutet. Es ist einfach und schnell. Die potenzielle Gefahr besteht darin, dass jeder Thread auf Speicher zugreifen kann, der zu anderen Threads oder zum RTOS selbst gehört.
Eine Alternative ist das Multiprozessmodell. Wenn mehrere Prozesse ausgeführt werden, hat jeder Prozess seinen eigenen Adressraum und Sie können nicht auf Speicher zugreifen, der anderen Prozessen oder RTOS zugeordnet ist:

Dies macht das Umschalten des Kontexts schwieriger und zeitaufwendiger, da das Betriebssystem die Speicherverwaltungseinheit, den Speichermanager (English Memory Management Unit, MMU), entsprechend konfigurieren muss. Natürlich ist eine solche Architektur nur mit einem Prozessor möglich, der MMU unterstützt. Die Prozesse werden von "Hochleistungs" RTOS und den meisten Desktop-Betriebssystemen unterstützt. Darüber hinaus kann jeder Prozess die Aufteilung in mehrere Threads unterstützen, diese Eigenschaft wird jedoch in normalen eingebetteten Anwendungen selten verwendet.
Wenn eine MMU verfügbar ist, kann ein Kompromiss erzielt werden:

Viele "Streaming" -RTOS unterstützen MMUs, um den Speicher vor unbefugtem Zugriff zu schützen. Während sich die Aufgabe im Kontext befindet, sind nur ein Teil ihres Codes / ihrer Daten und die erforderlichen Abschnitte des RTOS „sichtbar“. Die verbleibenden Speicherblöcke sind deaktiviert, und ein Zugriffsversuch führt zu einem Notfall (für normale Personen) / einer Ausnahme (für Programmierer). Dies macht das Umschalten des Kontexts etwas schwieriger, aber die Anwendung selbst ist sicherer. Dieser Modus kann als "Thread Protected Mode" oder "Lightweight Process Mode" bezeichnet werden.
Planer
Wie wir wissen, wird die Illusion der gleichzeitigen Ausführung von Aufgaben erreicht, indem Prozessorzeit zugewiesen wird, um jede der Aufgaben zu erledigen. Dies ist die Kernfunktion des Kernels. Die Methode zur Zeitverteilung zwischen Aufgaben wird als "Planung" bezeichnet. Scheduler - Software, die bestimmt, an welche nächste Aufgabe die Steuerung übertragen werden soll. Die Logik des Schedulers und der Mechanismus, der bestimmt, wann und was ausgeführt werden soll, ist der Planungsalgorithmus. In diesem Abschnitt werden verschiedene Planungsalgorithmen vorgestellt. Die Aufgabenplanung ist ein umfangreiches Thema, dem viele Bücher gewidmet sind. Wir werden das notwendige Minimum bereitstellen, um zu verstehen, was ein bestimmtes RTOS in dieser Hinsicht bieten kann.
Zum Abschlussplaner ausführen (RTC)
Der RTC-Scheduler (Run-to-Completion) ist sehr einfach und verbraucht nur minimale Ressourcen. Dies ist ein idealer Service, wenn er die Anforderungen der Anwendung erfüllt. Unten sehen Sie eine Grafik für ein System, das den RTC-Scheduler verwendet:

Der Scheduler ruft abwechselnd die Funktionen der obersten Ebene jeder Aufgabe auf. Die Task steuert den Prozessor (unterbricht ihn), bis die Funktion der obersten Ebene die Rückgabe der return-Anweisung ausführt. Wenn das RTOS das Anhalten von Aufgaben unterstützt, werden derzeit angehaltene Aufgaben nicht ausgeführt. Dieses Thema wird im folgenden Artikel behandelt, siehe "Anhalten einer Aufgabe".
Ein großer Vorteil des RTC-Schedulers ist neben der Einfachheit ein einzelner Stapel und die Portabilität des Codes (Assembly ist nicht erforderlich). Der Nachteil ist, dass die Aufgabe den Prozessor „übernehmen“ kann, sodass eine sorgfältige Entwicklung des Programms erforderlich ist. Trotz der Tatsache, dass jedes Mal, wenn die Aufgabe von Anfang an ausgeführt wird (im Gegensatz zu anderen Schedulern, mit denen Sie die Arbeit vom Haltepunkt aus starten können), können Sie mithilfe statischer "Status" -Variablen, die die Logik jedes nachfolgenden Aufrufs bestimmen, mehr Flexibilität erreichen.
Scheduler Round Robin (RR)
Der RR-Scheduler ("Karussell") ähnelt RTC, ist jedoch flexibler und daher komplexer:

Im Fall des RR-Schedulers muss die Task die return-Anweisung jedoch nicht in der Funktion der obersten Ebene ausführen. Sie kann den Prozessor jederzeit durch einen RTOS-Anruf freigeben. Dieser Aufruf bewirkt, dass der Kernel den Kontext der aktuellen Aufgabe (alle Register, einschließlich des Stapelzeigers und des Befehlszeigers) speichert und den Kontext der nächsten Aufgabe in die Warteschlange lädt. In einigen RTOSs kann der Prozessor in Erwartung der Verfügbarkeit der Kernelressource freigegeben werden (Pause der Aufgabe). Das ist komplizierter, aber das Prinzip ist dasselbe.
Die Flexibilität des RR-Schedulers wird durch die Fähigkeit bestimmt, Aufgaben ab dem Zeitpunkt der Unterbrechung weiterhin auszuführen, ohne Änderungen am Anwendungscode vorzunehmen. Für Flexibilität müssen Sie weniger Portabilität des Codes und einen separaten Stapel für jede Aufgabe bezahlen.
Time Slice Scheduler (TS)
Scheduler TS (Zeitscheibe - "Zeitscheibe") auf ein komplexeres Niveau als RR. Die Zeit ist in Zeitfenster (Intervalle, Zeitscheiben) unterteilt, in denen jede Aufgabe innerhalb des zugewiesenen Intervalls ausgeführt werden kann:

Zusätzlich zu der Möglichkeit, den Prozessor freiwillig freizugeben, kann die Aufgabe durch einen Aufruf des Schedulers unterbrochen werden, der vom Systemzeitgeber-Interrupt-Handler ausgeführt wird. Die Idee, jeder Aufgabe einen festen Zeitraum zuzuweisen, ist sehr attraktiv (soweit möglich): Sie ist leicht zu verstehen und sehr vorhersehbar.
Der Nachteil des TS-Schedulers besteht darin, dass der Prozentsatz der für jede Aufgabe zugewiesenen CPU-Zeit unterschiedlich sein kann, je nachdem, ob andere Aufgaben angehalten werden und andere Teile der Steckplätze frei sind:

Der TS-Scheduler kann vorhersehbarer werden, wenn Aufgaben im Hintergrund implementiert werden. Die Hintergrundaufgabe kann anstelle einer angehaltenen Aufgabe ausgeführt werden und das Zeitintervall einnehmen, in dem die Aufgabe freigegeben wird (oder sich selbst pausiert).

Offensichtlich sollte die Hintergrundaufgabe keine zeitkritische Arbeit ausführen, da der ihr zugewiesene Anteil der Prozessorzeit absolut unvorhersehbar ist: Sie kann niemals geplant werden.
Bei einer solchen Lösung wird davon ausgegangen, dass jede Aufgabe vorhersagen kann, wann sie erneut geplant wird. Wenn Sie beispielsweise Slots für 10 ms und 10 Aufgaben haben, weiß die Aufgabe, dass sie nach 100 ms weiterhin ausgeführt wird, wenn sie freigegeben wird. Mit dieser Lösung können Sie Zeitzyklen (Timings) für Anwendungsaufgaben flexibler konfigurieren.
Das RTOS kann für jede Aufgabe unterschiedliche Zeitfenster bereitstellen. Dies bietet mehr Flexibilität, ist aber auch so vorhersehbar wie bei einer festen Intervallgröße. Eine andere Möglichkeit besteht darin, mehr als ein Intervall für dieselbe Aufgabe zuzuweisen, wenn Sie den Anteil der zugewiesenen Prozessorzeit erhöhen müssen.
Prioritätsplaner
Die meisten RTOS unterstützen eine prioritätsbasierte Planung. Die Idee ist einfach: Jede Aufgabe erhält Priorität, und zu jeder Zeit wird die Aufgabe, die die höchste Priorität hat und zur Ausführung „bereit“ ist, an den Prozessor übertragen:

Der Scheduler wird gestartet, wenn ein Ereignis auftritt (z. B. ein Interrupt oder ein Aufruf eines bestimmten Kernel-Dienstes), das eine Aufgabe mit hoher Priorität zwingt, "bereit" zu werden. Es gibt drei Umstände, unter denen der Scheduler zu arbeiten beginnt:
• Die Aufgabe ist ausgesetzt. Der Scheduler muss die nächste Aufgabe planen.
• Eine Aufgabe bereitet eine Aufgabe mit höherer Priorität vor (mithilfe eines API-Aufrufs).
• Ein Interrupt-Handler (Interrupt Service Routine, ISR) bereitet eine Aufgabe mit höherer Priorität vor. Dies kann ein Interrupt-Handler für ein E / A-Gerät oder das Ergebnis eines Systemzeitgebers sein.
Die Anzahl der Prioritätsstufen variiert (von 8 bis zu mehreren hundert), die Schwellenwerte variieren ebenfalls: Einige RTOS nehmen die höchste Priorität als 0 wahr, während in anderen 0 die niedrigste Priorität bezeichnet.
Einige RTOS erlauben nur eine Aufgabe auf jeder Prioritätsstufe. andere erlauben einige, was die zugehörigen Datenstrukturen erheblich verkompliziert. Bei vielen Betriebssystemen können Sie die Prioritäten von Aufgaben zur Laufzeit ändern, was die Prozesse weiter verkompliziert.
Composite Scheduler
Wir haben mehrere Planer untersucht. Viele kommerzielle RTOS bieten jedoch noch ausgefeiltere Lösungen, die die Eigenschaften mehrerer Algorithmen gleichzeitig aufweisen. Beispielsweise kann ein RTOS mehrere Aufgaben auf jeder Prioritätsstufe unterstützen und dann mithilfe von TS die Zeit auf mehrere vorgefertigte Aufgaben auf der höchsten Ebene aufteilen.
Aufgabenzustände
Zu einem bestimmten Zeitpunkt wird nur eine Aufgabe ausgeführt. Zusätzlich zu der Prozessorzeit, die für den Interrupt-Handler (mehr dazu im nächsten Artikel) oder den Scheduler aufgewendet wird, ist die "aktuelle" Aufgabe die Aufgabe, deren Code gerade ausgeführt wird und deren Daten durch die aktuellen Registerwerte gekennzeichnet sind. Möglicherweise sind andere Aufgaben „startbereit“ und werden vom Scheduler berücksichtigt. In einem einfachen RTOS mit dem RTC-, RR- oder TS-Scheduler ist das alles. Häufiger und immer mit einem Prioritätsplaner können Aufgaben jedoch auch angehalten werden. Dies bedeutet, dass sie vom Planer erst berücksichtigt werden, wenn sie wieder aufgenommen werden und sich in einem Zustand der "Bereitschaft" befinden.
Unterbrechen Sie eine Aufgabe
Das Anhalten einer Aufgabe kann recht einfach sein: Die Aufgabe wird von selbst angehalten (durch Aufrufen der API) oder von einer anderen Aufgabe angehalten. Durch einen anderen API-Aufruf kann eine angehaltene Aufgabe von einer anderen Aufgabe oder einem Interrupt-Handler fortgesetzt werden. Dies ist eine "bedingungslose" oder "reine" Suspension. Einige Betriebssysteme nennen diese Aufgabe "Schlaf".
Das RTOS kann der Aufgabe die Möglichkeit geben, für einen bestimmten Zeitraum anzuhalten (einzuschlafen), wonach es (gemäß der Systemuhr) fortgesetzt wird. Dies kann als "Einschlafen" bezeichnet werden.
Wenn das RTOS das Blockieren von API-Aufrufen unterstützt, kann eine komplexere Suspendierung verwendet werden. Ein solcher Aufruf ermöglicht es der Aufgabe, einen Dienst oder eine Ressource anzufordern, die sie sofort erhält, wenn sie verfügbar ist. Andernfalls wird es ausgesetzt, bis es verfügbar ist. Es können auch Zeitüberschreitungen definiert werden, bei denen die Aufgabe fortgesetzt wird, wenn die Ressource für einen bestimmten Zeitraum nicht verfügbar ist.
Andere Aufgabenzustände
Viele RTOS unterstützen andere Staaten, aber Konzepte und Definitionen variieren stark. Zum Beispiel ist der Status "beendet", was einfach bedeutet, dass die externe Funktion der Aufgabe beendet wurde (entweder durch Rückgabe des Codes oder einfach durch Ausfüllen des externen Funktionsblocks). Damit die abgeschlossene Aufgabe wieder ausgeführt werden kann, muss sie wahrscheinlich irgendwie zurückgesetzt werden.
Eine weitere Option ist der abgeschlossene Status. Dies ähnelt einer vollständigen Unterbrechung (rein), außer dass die Aufgabe zum Neustart zurückgesetzt werden muss.
Wenn das RTOS das dynamische Erstellen und Löschen von Aufgaben unterstützt (siehe folgenden Artikel), impliziert dies einen anderen möglichen Status der Aufgabe - "gelöscht".
Als wir an unserem eigenen Echtzeit-Betriebssystem OSRV MAX arbeiteten (zuvor veröffentlichte Artikel darüber), stieß unser Team auf den Blog von Colin Walls, einem Experten für Mikroelektronik und Firmware bei Mentor Graphics. Artikel schienen interessant, übersetzten sie für sich selbst, aber um nicht "an den Tisch zu schreiben", beschlossen sie, sie zu veröffentlichen. Ich hoffe, sie werden Ihnen auch nützlich sein. Wenn ja, planen wir, alle übersetzten Artikel in der Reihe zu veröffentlichen.
Über den Autor: Colin Walls ist seit über dreißig Jahren in der Elektronikindustrie tätig und widmet sich die meiste Zeit der Firmware. Heute ist er Firmware-Ingenieur bei Mentor Embedded (einer Abteilung von Mentor Graphics). Colin Walls spricht häufig auf Konferenzen und Seminaren, Autor zahlreicher technischer Artikel und zweier Bücher über Firmware. Lebt in Großbritannien. Colins professionelles Blog: blogs.mentor.com/colinwalls , E-Mail: colin_walls@mentor.comDer erste und der zweite Artikel des Zyklus sind
hier veröffentlicht.