Wie erstellt man ein Programm, das mehrere Threads gleichzeitig ausführen kann?
Mehrere Threads in einem Programm zu verwenden, ist kein Selbstzweck, sondern es hat folgende Vorteile:
es ist eine bessere Nutzung der Prozessorleistung möglich
man bekommt kürzere Reaktionszeiten
die Struktur der Software wird übersichtlicher und verständlicher
Das folgende Beispiel ist der Praxis entnommen. Der in den Bildern gezeigte Programmcode (zum Vergrößern bitte auf die Bilder klicken) ist extrem gekürzt, um die Grundstruktur hervorzuheben. Es handelt sich um einen Agenten, der per Kommando gesteuert die Software von an einen CAN-Bus[1] angeschlossenen Baugruppen aktualisieren kann (Programmiersprache ist C unter Linux):
Zur Funktion des Programms:
die Main-Task nimmt Kommandos über stdin entgegen. Je nach Kommando steuert sie die Updater-Task oder sie sendet eine CAN-Nachricht.
die Updater-Task bedient einen Update-Auftrag und sendet dazu CAN-Nachrichten direkt auf den CAN-Bus. Ihren Input vom CAN-Bus bekommt sie über die CAN-Input-Task.
Hintergrund: die Updater-Task lädt ein File und führt den Update-Vorgang eigenständig durch. Dies entlastet den Host-Prozess von der komplexen Aufgabe, ein SW-Update durchzuführen.
ein weiteres Merkmal: Während der Dauer eines Software-Updates wird die betreffende Baugruppe von der stdin/stdout-Schnittstelle isoliert. Für alle anderen Baugruppen findet gleichzeitig der gewohnte Telegrammverkehr via stdin/stdout statt.
die CAN-Input-Task empfängt CAN-Nachrichten und leitet sie an die Updater-Task oder via stdout an den Host-Prozess weiter.
die Zeitgeber-Task bietet Funktionen zur Zeitüberwachung für die Updater-Task und steuert außerdem einen Zeittakt für die Aussendung eines Lebenszeichens.
für die Synchronisation des Zugriffs auf gemeinsam benutzte Daten und Betriebsmittel (CAN-Output, stdout) genügt ein einziger Mutex[2]. Außerdem sind alle Daten, für welche ein konkurrierender Zugriff möglich ist, als volatile deklariert.
die Updater-Task bekommt über einen "bedeutungslosen" Semaphor[3] signalisiert, dass sie erneut alle logischen Bedingungen auswerten soll (zum Beispiel Empfang einer CAN-Nachricht oder ein Timeout).
Vorab einige Definitionen:
Das Hauptprogramm:
Die weiteren Threads:
Im Wesentlichen geht es darum, zu zeigen, wie diese Threads ordnungsgemäß gestartet und beendet werden. Abgesehen von der ganzen Programmlogik habe ich 2 weitere Punkte unterschlagen:
die Bedienung des "Signal"-Mechanismus[4] (nicht ganz einfach)
ein Hilfsmittel, um einen mehrfachen Programmstart zu verhindern (Lock-File)
Fußnoten
[1] Controller Area Network – Wikipedia
[2] Mutex – Wikipedia
[3] Semaphor (Informatik) – Wikipedia
[4] Signal (Unix) – Wikipedia