QNX RTOS: Ein wenig über Mikrokerne, Threads und Prozesse

    Da meine erste kleine Überprüfung des QNX-Echtzeitbetriebssystems ergab, dass bei den Bewohnern von Habr Interesse besteht, habe ich mich entschlossen, die Notizenreihe fortzusetzen. Es scheint mir, dass es sich lohnt, ein wenig über die Systemarchitektur von QNX6 zu sprechen. Ich denke, es lohnt sich zu definieren, was ein Mikrokernel ist und welche Aufgaben er löst. Im Verlauf der Erzählung werden auch zwei Mythen in Bezug auf QNX entlarvt. Aber zuerst ...

    Ein bisschen über POSIX


    Mit der Veröffentlichung jeder neuen Version von QNX (und es sollte beachtet werden, dass die erste Version von QNX RTOS 1981 erschien) nutzten die Entwickler ihre bisherigen Erfahrungen und verbesserten das System, auch für Entwickler. Aus diesem Grund unterstützt QNX Neutrino POSIX 1003.1-Standards wie Thread-Management, Echtzeiterweiterungen, zusätzliche Echtzeiterweiterungen und Anwendungsumgebungsprofile (AEP).

    Warum spreche ich darüber? Sehr einfach. Ich möchte zwei Dinge anmerken, die für QNX charakteristisch sind und mit POSIX zusammenhängen. Es wird angenommen, dass jedes POSIX-Betriebssystem UNIX verbirgt. Und wenn ja, dann ist ein solches System zu umständlich und kann nicht in eingebetteten Lösungen verwendet werden. Bei QNX ist dies jedoch nicht der Fall. Der POSIX-Standard beschreibt eine Schnittstelle, keine Implementierung. Dies bedeutet, dass unter der POSIX-Ebene alles versteckt werden kann, einschließlich des Mikrokerns.

    Der zweite Punkt, auf den ich näher eingehen möchte, ist wahrscheinlich offensichtlich. Dies sind natürlich die Vorteile, die POSIX in QNX bietet:
    • Wiederverwendung von Code. Einmal entwickelter, debuggter und getesteter Code für ein POSIX-Betriebssystem kann auf einem anderen POSIX-System, einschließlich QNX, wiederverwendet werden.
    • "Portabilität" von Programmierern. Ein mit POSIX und UNIX vertrautes Entwickler- oder Entwicklungsteam kann problemlos mit der Entwicklung eines eingebetteten Echtzeitsystems beginnen (ich meine natürlich QNX). Schließlich kennen sie die meisten Betriebssysteme bereits.
    Wir können also den Schluss ziehen, dass POSIX in QNX mehrere Vorteile bietet.

    Wahrer Kern


    QNX RTOS basiert auf einer Mikrokernel-Architektur. Ich denke, es lohnt sich, anzuhalten und vor dem Fortfahren zu bestimmen, was der Mikrokern ist (zumindest in der QNX-Terminologie). Der Begriff Mikronukleus ist seit einiger Zeit sehr populär und viele Systeme, die einen kleinen Kern enthalten, werden als Mikronuklei bezeichnet. Und wenn der Kern noch kleiner ist, spricht man von einem Nanokern. Dies gilt nicht ganz für QNX. Die geringe Größe des Kernels ist nicht das Hauptziel. Die Idee ist, dass viele Funktionen des Betriebssystems (einschließlich vertrauter Funktionen wie zum Beispiel der Dateisystemunterstützung) aus dem Kernel in den Bereich der Benutzeranwendungen verlagert werden. Und der Mikrokernel selbst führt nur einen kleinen Satz von Funktionen aus, von denen die meisten eine Inter-Tasking-Interaktion ermöglichen:
    • Messaging (dies ist die Hauptsache, die der Mikrokern tut);
    • Flow-Management;
    • Scheduling (Flüsse);
    • Synchronisation (Streams);
    • Signalmanagement;
    • Timer-Verwaltung.
    Bitte beachten Sie, dass auch die Prozesskontrolle nicht vom Mikrokernel, sondern vom Prozessadministrator durchgeführt wird (der jedoch mit dem Mikrokernel zu einem Modul zusammengefasst ist). Ist das nicht der wahre Kern des Systems?

    Was ich oben aufgeführt habe, ist alles, was der QNX-Mikrokern tut. Dinge wie Netzwerktreiber oder Festplattenunterstützung befinden sich in separaten Modulen, die wie normale Benutzerprozesse ausgeführt werden und funktionieren. Mit allen daraus resultierenden Vorteilen (gegenüber Systemen auf Basis eines monolithischen Kerns). Und was sind diese Vorteile? Sehr einfach:
    • Der Quellcode eines Mikronukleus ist viel kleiner als der eines monolithischen Kernels, was bedeutet, dass der Kernel leichter zu debuggen und zu testen ist.
    • Der Mikrokern erhöht die Modularität. Das endgültige Zielsystem kann einfach nach Ihren Anforderungen konfiguriert werden. Es reicht aus, die Manager zu starten, die benötigt werden.
    • Der Mikrokern verbessert die Systemzuverlässigkeit. Wenn im Treiber ein Fehler auftritt, führt dies nicht zum Zusammenbruch des Systems (und des Mikrokerns), und der Treiber selbst kann jederzeit neu gestartet werden, ohne das gesamte System neu zu starten.

    Mythos: QNX-Mikrokernel ist in Assembler geschrieben


    Unter einigen Entwicklern wird angenommen, dass die hohe Leistung und Kompaktheit des QNX Neutrino-Mikrokerns das Ergebnis der Erstellung in Assemblersprache ist. Aber das ist nicht so. Der Mikrokernel ist fast vollständig in C geschrieben. Leistung und Kompaktheit sind die Konsequenzen der Verwendung gut etablierter Algorithmen und Strukturen.

    Prozesse und Threads in QNX


    Gemäß der POSIX-Spezifikation unterstützt QNX RTOS Streams. Darüber hinaus steuert der QNX-Mikrokern nur Threads, und es sind Threads, die als minimale „Ausführungseinheit“ betrachtet werden können. Jeder Prozess in QNX kann einen oder mehrere Threads enthalten. In diesem Sinne kann ein Prozess als ein Behälter von Fäden angesehen werden.

    Im einfachsten Fall kann (und sollte) ein Prozess einen Thread enthalten. Manchmal ist jedoch die parallele Ausführung mehrerer Algorithmen in einem Prozess erforderlich. Ich werde ein kleines Beispiel von QNX geben. Der Dateisystem-Manager kann Anforderungen von mehreren Clients (anderen Prozessen) gleichzeitig empfangen und verarbeiten. Wenn der Manager in einem Thread arbeitet, muss der zweite ihn kontaktierende Client auf den Abschluss des zuvor angeforderten Vorgangs warten. Glücklicherweise arbeitet der Dateisystem-Manager in QNX in mehreren Threads, sodass Sie mehrere Anwendungen gleichzeitig und parallel bedienen können.

    Alle Prozesse in QNX sind voneinander isoliert und werden in einem eigenen virtuellen Adressraum ausgeführt. Die Memory Management Unit (MMU) ist für die Implementierung eines solchen Schutzes verantwortlich. Das Vorhandensein des MMU-Geräts im Prozessor ist eine Voraussetzung für das Starten von QNX. Zur gleichen Zeit arbeiten Threads eines Prozesses in einem Adressraum.

    Es gibt Systeme, die gemäß dem Schema implementiert sind, wenn alle Aufgaben im System Flüsse sind, die im selben Adressraum arbeiten. Dies erleichtert zum einen die Interprozesskommunikation. Andererseits kann jeder Fehler in einem Thread zum Zusammenbruch des gesamten Systems führen. Das Debuggen und Warten eines Systems, das auf diesem Prinzip basiert, ist weitaus schwieriger.

    Mythos: Der QNX-Mikrokernel wechselt langsam den Kontext zwischen Prozessen


    Ursprünglich erschienen Threads auf UNIX-Systemen als Lösung für das Problem, dass der Kontext zwischen Prozessen zu langsam wechselt. Höchstwahrscheinlich ist seitdem allgemein anerkannt, dass der Kontextwechsel zwischen Prozessen sehr langsam ist. Und da bei der Verwendung eines Mikrokerns und beim Senden von Nachrichten mehr Kontextwechsel durchgeführt werden als bei der Verwendung eines monolithischen Kernels, wird eine einfache Schlussfolgerung gezogen: QNX ist langsam. Die QNX-Neutrino-Architektur behebt jedoch das Problem der Kontextumschaltleistung. Und in QNX gibt es praktisch keinen Unterschied in der Geschwindigkeit des Kontextwechsels zwischen Prozessen und Threads.

    Wie der Strom lebt


    Während der Ausführung des Prozesses können Threads dynamisch erstellt und gelöscht werden. Wenn Sie beispielsweise einen Thread erstellen pthread_create(), werden die erforderlichen Ressourcen von der Funktion zugewiesen und initialisiert, und der Thread beginnt mit der angegebenen Funktion im Adressraum des Prozesses. Am Ende eines Streams, beispielsweise mit einer Funktion, werden pthread_exit()Ressourcen freigegeben.

    Während der Thread ausgeführt wird, kann er sich in zwei Zuständen befinden: bereit (ready) oder blockiert (locked). Aber in der Tat gibt es verschiedene Gründe , aus denen die Strömung in der Ableitung von Informationen über Prozesse und Threads mit dem Befehl blockiert werden pidin(QNX-spezifische Version des Dienstprogramms ps) können wir verschiedene Zustände beobachten, zum Beispiel, senden, empfangen, SIGWAITINFO, nanosleep und andere. In diesem Zustand habe ich beispielsweise jetzt USB-Manager-Threads:

    # pidin -P io-usb
         pid tid name               prio STATE       Blocked
        4101   1 proc/boot/io-usb    10o SIGWAITINFO
        4101   2 proc/boot/io-usb    21r RECEIVE     1
        4101   3 proc/boot/io-usb    10o RECEIVE     4
        4101   4 proc/boot/io-usb    10r NANOSLEEP
        4101   5 proc/boot/io-usb    10o RECEIVE     4

    Hier ist pid die Prozesskennung (Prozess-ID) im System, tid ist die Threadkennung (Thread-ID) im Prozess, prio ist die Thread-Prioritätsnummer und die Planungsdisziplin, STATE ist der Thread-Status, Blockiert ist der Wert abhängig vom Grund für die Blockierung. In dem obigen Beispiel befinden sich die Threads 2, 3 und 5 in einem Empfangsblockierungszustand (d. H. Sie sind bereit, Nachrichten von anderen Threads zu empfangen).

    Nachwort


    Ich habe versucht, über die Vorteile von POSIX und ein wenig über die Rolle des QNX-Mikrokerns zu sprechen. Hoffe das war interessant. Eigentlich wäre es schön, über Planungsdisziplinen und Mechanismen der Interaktion zwischen Aufgaben zu sprechen, aber ich dachte, es wäre besser, dies in getrennten Themen zu tun, damit all diese Informationen nicht zu einem Durcheinander werden. Ich verspreche, dass es beim nächsten Mal interessanter wird.

    Und vieles mehr. Wenn sich jemand für QNX interessiert, kann alles, was ich beschrieben habe und noch viel mehr in der Systemarchitektur von QNX Neutrino nachgelesen werden. Diese Dokumentation ist in elektronischer Form auf der Website www.qnx.com (in englischer Sprache) verfügbar , und es gibt auch eine russische Übersetzung in gedruckter Form:
    1. Echtzeit-Betriebssystem QNX Neutrino 6.3. Systemarchitektur. ISBN 5-94157-827-X
    2. Echtzeit-Betriebssystem QNX Neutrino 6.3. Benutzerhandbuch. ISBN 978-5-9775-0370-9

    Jetzt auch beliebt: