bekanntlich ist ein RTOS im Grundprinzip ein präemptiver Scheduler für Multithreading mit einem speziellen Algorithmus für Echtzeit-Unterstützung.
Allerdings haben heutige RTOSe (z.B. Zephyr, RT-Thread usw) ja eine große Anzahl an zusätzlichen Komponenten und Middlewares wie z.B. Networking, Dateisysteme, Power Management, Treiber für externe interne & externe Peripherie, Kryptographie, OTA-Updates usw.
"Eigentlich" sind diese Zusatz-Komponenten ja orthogonal zum Scheduler und nicht wirklich von diesem abhängig.
Präemptives Multithreading ist außerdem schwierig sicher handzuhaben durch Race Conditions, Deadlocks & Co - es ist sehr leicht, subtile Fehler einzubauen, die nur sehr selten auftreten und kaum zu finden sind.
Wenn ich also diese zusätzlichen Komponenten/Libraries nutzen möchte, aber eben kein präemptives Scheduling haben möchte, hat man kaum eine Option, richtig? Dinge wie Flash-Filesystems sind immer in synchron implementiert in der Annahme, dass ein präemptives Scheduling im Hintergrund läuft.
Was gibt es für Möglichkeiten, solche Komponenten (Networking, Flash-Filesysteme, Peripherie-Treiber) ohne präemptives Scheduling zu nutzen? Neben der Flickschusterei für jeden Aspekt eine Bibliothek zu finden und diese irgendwie unter einen Hut zu bringen?
PS: Interessanterweise scheint die Echtzeit-Fähigkeit von RTOSen in der Praxis eine geringe Rolle zu spielen. Welcher Scheduling-Algorithmus dort arbeitet, wie lange genau ein Task braucht usw. wird anscheinend selten betrachtet. Im Studium war das allerdings das Einzige, was über RTOSe gelehrt wurde... Der "RT"-Teil in "RTOS" scheint nur von akademischem Interesse zu sein?
Was gibt es für Möglichkeiten, solche Komponenten (Networking,
Flash-Filesysteme, Peripherie-Treiber) ohne präemptives Scheduling zu
nutzen? Neben der Flickschusterei für jeden Aspekt eine Bibliothek zu
finden und diese irgendwie unter einen Hut zu bringen?
Vielleicht sind dem Adam Dunkels seine Protothreads was für dich.
Wenn ich also diese zusätzlichen Komponenten/Libraries nutzen möchte,
aber eben kein präemptives Scheduling haben möchte, hat man kaum eine
Option, richtig?
Nö. VxWorks kann diesen Anspruch erfüllen. Dort kann man den Scheduler entsprechend konfigurieren. Probiert hab ich diese Option selber nie.
Und VxWorks kostet Geld, viel Geld ;)
Und ich bin mir sicher dass es noch andere RTOS gibt die nur mit kooperativem Scheduler laufen können.
Wenn ich also diese zusätzlichen Komponenten/Libraries nutzen möchte,
aber eben kein präemptives Scheduling haben möchte, hat man kaum eine
Option, richtig? Dinge wie Flash-Filesystems sind immer in synchron
implementiert in der Annahme, dass ein präemptives Scheduling im
Hintergrund läuft.
nicht immer, bei Mbed wurde das teilweise getrennt.
In Mbed 2 war das OS nur ein API das Komponenten wie DitalIn/Out, Serial, I2C, CAN, Software Timer und mehr abstrahiert hat. Einen RT Scheduler konnte man optional dazubauen. Das hatte den Nachteil das die Basic OS Komponenten nicht threadsafe waren und diese Kombi mit Vorsicht zu geniessen war.
In Mbed 5/6 wurde der Scheduler (RTX von ARM) fest eingebaut und Threads berücksichtigt. Mbed 5 wurde dadurch aber sehr fett und viele kleine Controller waren damit nicht mehr geeignet.
Dann wurde Mbed 6 besser modularisiert und der RT Teil einfach konfigurierbar im Build gemacht. In der Variante baremetal hat man dann wieder nahezu alles an Treibern, aber eben ohne den Scheduler und die RTOS nötigen Dinge wie Semaphore, Mailboxen usw. Nur im Ethernet Code wird das RT und Features wie EventFlags verwendet, daher ist das nur in der RTOS Variante nutzbar. Obwohl, soviel wird da nicht mit Threads gemacht und es könnte auch ohne gehen. Aber bei Controllern mit EMAC hat man üblicherweise auch genug Resourcen für das RTX, und man muss ja keine weiteren Threads starten. Praktisch ist es aber schon.
Bei ohne RTX gibt es im baremetal trotzdem die EventQueues, damit kann man kooperative Scheduling elegant lösen. In die EventQueue kann man Funktionen reinwerfen die dann in der mainloop ausgeführt werden, auch gut um Code aus ISR vom Interruptcontext zu entkoppeln. Hier wird der Komfort den C++ bietet genutzt, die EventQueues sind absolut genial.
Ich hab das so aus der Erinnerung geschrieben, die aber trügt (glaube ich jetzt). Es geht kein kooperatives Multitasking, sondern man kann dem Scheduler nur sagen, er soll Round Robin arbeiten, nicht kooperativ.
Der Poster hat leider viel weniger wie gar keine Ahnung. Ein RTOS ist speziell fuer Echtzeit gemacht. Genau deswegen wird's verwendet, fuer nichts anderes. Allerdings sollte man einige Punkte beachten.
Ein Echtzeit System muss nicht maximal schnell sein, sondern zuverlaessig schnell mit einer definierten maximalen Reaktionszeit.
Also nichts mit zufaelligen Garbage collector, welcher wie auch immer lange braucht. Oder ein Systemupdate reinzieht und den Rechner auf irgendwelche Zeit blockiert.
Je nach Einsatzumfeld reichen vielleicht 10ms Reaktionszeit. Bei einem Auto moechte man eher bei 1ms liegen.
Ein Stueck Hardware ist eine Ressource und muss natuerlich richtig geshart werden. Resp man hat einen Thread pro Ressource und dieser bedient die Hardware Funktionalitaet. Ungeteilt. Also, die Ethernet Schnittstelle ist ein Thread. Andere Threads mit Bedarf werden von diesem bedient. Wann der seine Zeitscheibe bekommt ist weniger wichtig.
Desgleichen das Filesystem. Allenfalls stellt das schon das RTOS sicher, und sonst muss man's eben selbst machen.
Was gibt es für Möglichkeiten, solche Komponenten (Networking,
Flash-Filesysteme, Peripherie-Treiber) ohne präemptives Scheduling zu
nutzen? Neben der Flickschusterei für jeden Aspekt eine Bibliothek zu
finden und diese irgendwie unter einen Hut zu bringen?
Selber schreiben. Wenn man kein Multithreading hat und dennoch verschiedenen Aufgaben parallel abzuarbeiten hat, dann muss man jede Aufgabe in kleinere Teilaufgaben zerstückeln und diese dann häppchenweise und/oder asynchron ausführen. Asynchrone Architekturen sind aber nicht jedermanns Sache, da muss man oft um die Ecke denken. Deswegen wird sehr oft einfach ein RTOS benutzt und es gibt nicht so viele fertige Libraries dafür.
RTOS macht das einfacher, hat dafür aber auch Nachteile, jeder Thread benötigt einen eigenen Stack, Kontextwechsel und Synchronisation kosten Performance.
Von der Laufzeit Seite her kann man "Parallelität" bzw Preämptive Systeme aber auch anders erreichen. Z.b mit Interrupten. Im Usermode führt man alles aus, was langsam ablaufen und damit synchron umgesetzt werden kann und im Interruptmode das wo es Zeitanforderungen gibt. Aber auch Polling kann eine Option sein und ist nicht unbedingt schlechter. Z.b. kann man eine "Aufgabe" in Teilaufgaben aufteilen und das in eine Zustandsmachine verpacken. Dann "pollt" man einfach in der Hauptschleife alle Zustandsmaschinen nacheinander. Das ist dann kooperatives Multitasking.
Ich selbe nutze meist Queues mit Funktionspointern + Interrupte. Jede Teilaufgabe kommt in eine Funktion und wenn die halt ausgeführt werden muss, dann wird der Funktionspointer in die FIFO geworfen. Die "main" Funktion macht nichts weiter als auf die Queues (können mehrere sein, z.B. hochpriore und niederpriore) zu schauen und sich dort die Funktionsspointer rauszuziehen und auszuführen. Eine weitere Queue enthält dann noch die (Software)Timer...
Die Frage ist, was willst Du genau nutzen? Solche RTOS Betriebssystem sind halt in der Regel primär Taskswitcher, willst Du mehr musst Du das bei vielen woanders her holen.
Es gibt zum Beispiel viele Dateisystemsroutinen welche Du, völlig unabhängig vom Betriebssystem, verwenden kannst. Zum Beispiel so was hier, falls Du FAT haben möchtest. https://github.com/FullFAT/FullFAT
Für Spezialanwendungen kann es aber einfacher sein, mal eben selbst ein Minimalstdateisystem zu stricken.
Willst Du Netzwerk haben, so wird es etwas schwieriger, da es im Allgemeinen sinnvoll ist, wenn Dein Netzwerkstack Dinge im Hintergrund machen kann. Damit kann beispielsweise die ARP-Anfrage rechtzeitig bevor der ARP-Cache ausläuft gemacht werden. Auch bei Protokollen wie TCP (eine Art 1-Stream SCTP) kann es sinnvoll sein, wenn der Stack einen Thread hat, der sich um Retransmissions u.Ä. kümmert.
Asynchrone Architekturen
sind aber nicht jedermanns Sache, da muss man oft um die Ecke denken.
Ich denke mal, das ist das Grundproblem.
Schlimmer noch: es muss noch nicht mal echte Asynchronität und die damit verbundenen Probleme sein. Viele Möchtegern-Programierer kommen ja nicht mal mit einem Ereignis-gesteuerten Programmierschema zurecht, was ordentlich innerhalb eines einzigen Threads/Tasks abgearbeitet wird, also simplen state machines.
Wenn die Kontrollstruktur nicht als solche im Code steht, sind die aufgeschmissen und begreifen nicht mehr, was da eigentlich passiert.
Nicht schlimm, nicht jeder ist zum Programmierer geboren. Aber: Die sollten dann auch einfach nicht programmieren. Es ist ihnen nicht gegeben.
Präemptives Multithreading ist außerdem schwierig sicher handzuhaben
durch Race Conditions, Deadlocks & Co - es ist sehr leicht, subtile
Fehler einzubauen, die nur sehr selten auftreten und kaum zu finden
sind.
Vielleicht solltest Du 3 Dinge trennen:
Die verschiedenen Eigenschaften eines RTOS (z.B. verschiedene Arten von Schedulern)
Dein Nutzen des RTOS (Abhängig von Deinen Kenntnissen)
die "Zusatzfunktionen" des RTOS
In Autosar z.B. sind "Basic Tasks" nichts anderes als Funktionen, die aufgerufen werden und ohne jedes Warten durchlaufen (müssen).
Wenn Du mit einer Task auskommst, dann brauchst Du Dich um die allermeisten Dinge gar nicht zu kümmern und kannst trotzdem die "Zusatzfunktionen" nutzen, da die ja von Leuten implementiert wurden, die das RTOS kennen.
Wenn Du mehrere Tasks brauchst, gibt es unzählige Pattern, um typische Fallstricke zu umschiffen. Die meisten haben auch vorher schon mehrere Tasks und Prioritäten gehabt und sie "Interrupt-Routine" genannt. Viele Probleme sind ähnlich oder gleich. Fang einfach an. Oft mit einer Loop und davon entkoppelter GUI. Spring ins kalte Wasser, je eher lernst Du schwimmen.
Wenn irgendwas X mal gemacht werden soll, dann will ich da eine zählende
for Schleife sehen.
Ohne wenn und aber!
Wenn Deine Schleife auf einem System mit kooperativen Multitasking laufen soll und nicht das ganze System während der Ausführungszeit der Schleife blockiert sein soll, dann hast Du mit der Einstellung ein Problem.
Ein schönes Beispiel für kooperatives Multitasking waren die 16-Bit-Versionen von Windows. Gut beschrieben in der zweiten Ausgabe von Charles Petzolds "Programming Windows" von 1990 oder in der dritten Ausgabe von 1992*.
Wenn ich mich recht erinnere, gab es das Buch auch mal als Beigabe zu einer Version des 16-Bit-Borland-C/C++-Compilers (die mit dem guten halben Meter Papier)
Wenn irgendwas X mal gemacht werden soll, dann will ich da eine zählende
for Schleife sehen.
Ohne wenn und aber!
Wenn Deine Schleife auf einem System mit kooperativen Multitasking
laufen soll und nicht das ganze System während der Ausführungszeit der
Schleife blockiert sein soll, dann hast Du mit der Einstellung ein
Problem.
Nein, habe ich nicht!
Siehe:
Arduino F. schrieb im Beitrag #7718678:
Vielleicht sind dem Adam Dunkels seine Protothreads was für dich.
Habe mir eine Abwandlung davon gebaut, die auch auf kleinen AVR ganz gut zu nutzen ist.
Allerdings haben heutige RTOSe (z.B. Zephyr, RT-Thread usw) ja eine
große Anzahl an zusätzlichen Komponenten und Middlewares wie z.B.
Networking, Dateisysteme, Power Management, Treiber für externe interne
& externe Peripherie, Kryptographie, OTA-Updates usw.
"Eigentlich" sind diese Zusatz-Komponenten ja orthogonal zum Scheduler
und nicht wirklich von diesem abhängig.
Auch wenn es eigentlich schon beantwortet wurde, hier nochmal am Beispiel von embOS. Gilt aber genauso für FreeRTOS, etc.
Du kannst ein reines RTOS wie embOS benutzen. Das ist der Scheduler inkl. passender API, um Tasks laufen zu lassen, zu synchronisieren, usw.
https://www.segger.com/doc/UM01001_embOS.html
Aus Sicht des RTOS ist das alles Applikation, d.h., ob ein Filesystem läuft oder deine Applikation ist dem RTOS egal. Wenn z.B. das Filesystem in mehreren Tasks genutzt werden soll, muss es thread-safe sein.
Die Embedded Software kannst du auch ohne RTOS, als bare metal, laufen lassen (oder auch mit jedem anderen RTOS). Dann ist aber deine Applikation dafür verantwortlich, dass alle Teile deiner Applikation den Echtzeitanforderungen entsprechen. Es gibt Embedded Software wie z.B. USB Host, die ohne RTOS nur schwer umsetzbar sind.
Präemptives Multithreading ist außerdem schwierig sicher handzuhaben
durch Race Conditions, Deadlocks & Co - es ist sehr leicht, subtile
Fehler einzubauen, die nur sehr selten auftreten und kaum zu finden
sind.
Natürlich kann es Probleme geben, aber dem würde ich nicht zustimmen. Ansonsten würden RTOS ja nicht in sicherheitskritischen Produkten eingesetzt werden.
Was ich in der Praxis eher sehe, ist, dass manche Entwickler sich ihren eigenen Scheduler entwickeln, weil auch ihre komplexe Applikation Echtzeitanforderungen hat. Aber dann kann man auch direkt ein RTOS einsetzen
Aus Sicht des RTOS ist das alles Applikation, d.h., ob ein Filesystem
läuft oder deine Applikation ist dem RTOS egal. Wenn z.B. das Filesystem
in mehreren Tasks genutzt werden soll, muss es thread-safe sein.
Diese Anforderung bedingt, dass für jede Task/Thread ein Stack Bereich reserviert werden muss.
Damit ist der Speicher die begrenzende Ressource.
Wenn da kein Mange herrscht, dann gut.
Aber:
4 Tasks auf einem ATMega328p, da dürfte dann irgendwo die Grenze sein.
Das ist nicht viel.
Zudem sind die Unmengen Push und Pop nicht gerade ein Beschleuniger.
Auch war die Eingangsfrage:
Niklas G. schrieb im Beitrag #7718652:
aber eben kein präemptives Scheduling haben möchte,
Dann zeig' doch mal Deine for-Schleife, die nicht Deine Protothreads
blockiert.
Erstens: Du kennst die Protothreads nicht.
Sonst wüsstest du das, wie das geht.
Zweitens: Das interessiert dich überhaupt nicht!
Denn sonst würdest du dir die Abhandlungen des Herren Dunkels mal durchgelesen haben, bevor du so ein dummes Zeugs blubberst.
Offensichtlich glaubst du mir nicht.
Das ist eigentlich ok.
Aber schade, dass du das nicht selber gegenprüfen möchtest.
Beispiel:
For Schleife mit Adruino delay() Drop in Ersatz und dazu mit einer Endlosschleife garniert.
1
// Grundsaetzliche Annahme (-: es "mag" Ausnahmen geben ;-)
2
constexprboolstromausfall{false};
3
4
classPiepser:publicTask
5
{
6
protected:
7
inti;
8
bool&piepflag;
9
10
public:
11
Piepser(bool&piepflag):i(0),piepflag(piepflag){}
12
13
virtualvoidrun()override// 5 mal piepsen, wenn Flag gesetzt
14
{
15
16
TaskBlock
17
{
18
while(notstromausfall)
19
{
20
taskWaitFor(piepflag);
21
for(i=0;i<5;i++)
22
{
23
Serial.println(F("Piep"));
24
//taskSwitch();
25
taskPause(200);/ms
26
}
27
piepflag=false;// fertig mit piepsen (Flag konsumieren)
28
}
29
}
30
}
31
};
1 bis 2 Dutzend Tasks auf einem Uno durchaus machbar.
ca 100000 Durchläufe pro Sekunde bei 4 bis 5 Tasks
Erstens: Du kennst die Protothreads nicht.
Sonst wüsstest du das, wie das geht.
Zweitens: Das interessiert dich überhaupt nicht!
Du bist irgendwo ganz, ganz falsch abgebogen. Und wirfst jetzt krampfhaft mit Beleidigungen und haltlosen Unterstellungen um Dich.
Was Du da zeigst, ist halt keine simple for-Schleife mehr, sondern eine, die nach jedem Durchlauf eine zusätzliche Funktion ("taskPause") aufruft, um eben anderen Threads Rechenleistung zukommen zu lassen.
Wenn Du das bei Deiner Programmierung berücksichtigst, ist ja alles gut, nur widersprichst Du Deinen Pauschalaussagen hier:
Wenn irgendwas X mal gemacht werden soll, dann will ich da eine zählende
for Schleife sehen.
Ohne wenn und aber!
Ebenso eine Endlosschleife, wenn irgendwas dauerhaft getan werden soll.
z.B. so: while(not stromausfall) tuwas();
Deine Endlosschleife funktioniert nur dann, wenn entweder zusätzlich zu "tuwas" eine Funktion analog zu "taskPause" aufgerufen wird, oder aber "tuwas" das macht.
/Das/ ist der essentielle Unterschied, auf den man eben achten muss.
Beleidigungen und haltlosen Unterstellungen um Dich.
Wie?
Du hast doch gezeigt, dass du die Protothreads nicht kennst und dich nicht kundig gemacht hast.
Wie kann das beleidigend sein, wenn man das klar so benennt?
Ja, ich bin enttäuscht von dir, da hätte ich mehr erwartet.
Diese Anforderung bedingt, dass für jede Task/Thread ein Stack Bereich
reserviert werden muss.
Damit ist der Speicher die begrenzende Ressource.
Wenn da kein Mange herrscht, dann gut.
Ja, richtig, jede Task läuft auf ihrem eigenen Taskstack und dafür braucht man genügend Speicher. Die Größe des Taskstacks hängt von dem Code in der Task ab. Der Taskstack muss z.B. größer sein, wenn mehr lokale Variablen und Unterprogrammaufrufe genutzt werden.
Wir haben Kunden, die embOS auf einem 8051 mit 2 kByte RAM einsetzen...da wundert man sich schon ein bisschen ;-).
Zudem sind die Unmengen Push und Pop nicht gerade ein Beschleuniger.
Du meinst wahrscheinlich den Taskwechsel. Dazu kommt dann auch noch die Laufzeit des Schedulers.
Man muss das wahrscheinlich ein bisschen differenzieren. Nicht jede Applikation braucht ein RTOS und nicht jeder Mikrocontroller hat dafür genug Leistung und Speicher. Aber Mikrocontroller werden immer leistungsfähiger und haben mehr Speicher. Daher werden komplexere Applikationen ausgeführt, die mehr Echtzeitanforderungen haben. Der Overhead des RTOS ist dann im Vergleich zu den Vorteilen vernachlässigbar.
Allerdings haben heutige RTOSe (z.B. Zephyr, RT-Thread usw) ja eine
große Anzahl an zusätzlichen Komponenten und Middlewares wie z.B.
Networking, Dateisysteme, Power Management, Treiber für externe interne
& externe Peripherie, Kryptographie, OTA-Updates usw.
Da würde ich allerdings auch nicht auf einen präemptiven Scheduler verzichten wollen. Ein RTOS zeichnet sich nicht nur durch garantierte Antwortzeiten aus, die Tasks/Threads haben auch verschiedene Prioritäten die eine Programmstruktur vereinfachen.
Dann zeig' doch mal Deine for-Schleife, die nicht Deine Protothreads
blockiert.
Erstens: Du kennst die Protothreads nicht.
Sonst wüsstest du das, wie das geht.
"taskPause", "taskWaitFor" sind nichts weiteres als in Deiner Applikation explizit gesetzte Unterbrechungspunkte an denen Du die Kontrolle zurück an den "Protothread Scheduler" übergibst. (Im Endeffekt steht da ein "return") Und das ist genau das, was Harald mit seiner Aussage meinte: Wenn man ein deartig implementiertes kooperatives Multitasking einsetzt, dann muss die Applikation dafür geschrieben sein, sonst funktioniert das nicht. Wenn du nämlich "taskPause" und "taskWaitFor" weg lässt, naja, den Rest weist Du sicher selbst. Und hier entsteht das Problem wenn man fertige Bibliotheken einsetzen will, z.b. fürs Dateisystem. Würde man einen Aufruf von "open(...)" in Deine Schleife einsetzen, dann würde er an der Stelle gemütlich alle I/O Operationen (z.B SPI) abwarten und durcharbeiten bevor er aus der "open" Funktion überhaupt zurückkommt. Und das würde mit read/write so weitergehen. Erst dann wenn die Applikation explizit die Kontrolle an den Protothread Scheduler zurückgibt würde überhaupt erst eine andere "Task" dran kommen können, die sogenannte Parallelität geht dann ganz schnell flöten (Kommt drauf an wie zeitkritisch die einzelnen Aufgaben sind)
Im Gegensatz dazu kann ein echtes Multitasking OS eine Task zu jedem beliebigen Zeitpunkt unterbrechen und was anderes laufen lassen, dafür werden keine Unterbrechungspunkte gebraucht. Somit kann dann (im Prinzip beliebiger) Code dem System zugefügt werden ohne den Rest des Systems zu stören oder das Zeitverhalten zu beeinflussen.
Ich würde den Unterschied zwischen kooperativem und präemptiven Multitasking nicht verwenden, um zwischen "echtem" und "unechtem" Multitasking zu unterscheiden. Auch kooperativ ist sehr wohl echtes Multitasking möglich (entsprechende Disziplin und Sorgfalt seitens des Programmierers vorausgesetzt).
Ja, ein präemptives Multitasking macht das ganze sehr viel leichter, wiederum vorausgesetzt, der Programmierer schafft es, bei der Synchronisation seiner Threads keine Verknotungen (Deadlock, Race Condition etc.) zu basteln.
Wenn ich also diese zusätzlichen Komponenten/Libraries nutzen möchte,
aber eben kein präemptives Scheduling haben möchte, hat man kaum eine
Option, richtig?
Irgendwie ist die Frageform hier kacke. Aktuelle Forschungen gehen da wohl eher in Richtung Stromsparen?
"In spite of this large application domain, most of the current real-time systems are still designed and implemented using low-level programming and empirical techniques, without the support of a scientific methodology. This approach results in a lack of reliability, which in critical applications may cause serious environmental damage or even loss of life."
Würdest du sagen, dass diese Thematik mit den oben angesprochen Problemen eine passende in einem Lämpchen-Blinken-lassen-Forum ist?
Mit solchen Fragen geht man an die Uni, fragt viele Leute, macht sich eine Leseliste zum Abarbeiten und macht sich selber ein paar Notizen und Gedanken - bis man merkt, dass man keine Ansprechpartner mehr hat, und ein Kommunikationsproblem.
Falls man selber an der Uni lehrt, hätte man natürlich auch ein supergutes Thema zum Veröffentlichen.
Früher hätte man sogar nach Pisa pilgern können, um die Vorlesungen von diesem Buttazzo zu besuchen.
(Wenn man ein paar Wiki-Seiten zur Jupitersonde Juno durchliest, weiß man immer noch nicht, wer die Sonde wie und womit programmiert hat.)
"In spite of this large application domain, most of the current
real-time systems are still designed and implemented using low-level
programming and empirical techniques, without the support of a
scientific methodology. This approach results in a lack of reliability,
which in critical applications may cause serious environmental damage or
even loss of life."
Welche Quelle hast Du da zitiert? Klingt ja gar nicht voreingenommen, das.
"In spite of this large application domain, most of the current
real-time systems are still designed and implemented using low-level
programming and empirical techniques, without the support of a
scientific methodology. This approach results in a lack of reliability,
which in critical applications may cause serious environmental damage or
even loss of life."
Das klingt mir sehr subjektiv und schlecht informiert/recherchiert vom ursprünglichen Autor dieser Zeilen. Wenn Menschenleben betroffen sind, gibt es sehr strenge Vorgaben für die Software in kritischen Applikationen wenigstens im Maschinenbau, Luft- & Raumfahrt. Ich vermute in der Autoindustrie oder gar Medizin ist es nicht anders. Da wird nichts empirisch programmiert. Das ist schlicht Unsinn.
Wenn Menschenleben betroffen sind,
gibt es sehr strenge Vorgaben für die Software in kritischen
Applikationen wenigstens im Maschinenbau, Luft- & Raumfahrt. Ich vermute
in der Autoindustrie oder gar Medizin ist es nicht anders.
Ja, ist bei Automotive und Medizin nicht anders. In der ISO 26262 bzw. IEC 62304 sind die Anforderungen an die Software genau beschrieben.
Ein RTOS wie z.B. embOS-Safe oder SafeRTOS müssen nach diesen Normen zertifiziert werden, um im Fahrzeug oder im Medizinprodukt genutzt werden zu können.
Diese Zertifizierung muss aber der Entwickler nicht selber machen, sondern das machen oft bereits die RTOS Hersteller, so dass man ein "pre-certified" RTOS nutzen kann.
Wann und wofür benutzt ihr eigentlich ein RTOS? In 10 Jahren Arbeitswelt und auch privater Bastelleien hatte ich noch nie das Bedürfnis nach einem RTOS.
Aber ich programmiere vermutlich auch keine HF Echtzeit Anwendungen.
In den letzten knapp 17 Jahren benutzen eher weniger...mehr das RTOS entwickeln ;-).
Ein RTOS macht immer da Sinn, wo die Applikation komplexer ist, und mehrere Aufgaben quasi parallel mit unterschiedlichen Echtzeitanforderungen abgearbeitet werden sollen.
Sagen wir, eine fiktive Anwendung soll irgendwelche Daten per TCP/IP austauschen und per GUI/Touch bedienbar sein. Der TCP/IP Stack und der Datenaustausch können in Tasks mit niedriger Priorität laufen, weil sie keine hohen Echtzeitanforderungen haben. Ob die Daten ein paar Millisekunden später ankommen, ist in dieser fiktiven Anwendung egal.
Die GUI Task hat aber hohe Echtzeitanforderungen und sollte eine hohe Taskpriorität bekommen. Wenn der Benutzer das Touch bedient und auf dem Display passiert nichts, weil gerade Code des TCP/IP Stacks abgearbeitet wird, ist das suboptimal.
Das RTOS hilft einem ungemein bei dem Timing und den Echtzeitanforderungen.
Natürlich geht das auch irgendwie ohne RTOS, aber ab einer gewissen Komplexität der Anwendung nur mit sehr viel mehr Aufwand.
Dazu kommen noch andere Aspekte wie z.B. Energie sparen aber das führt hier zu weit.
Wer schon für eine ausreichende Schwuppdizität eines Guis ein Rtos benötigt, macht irgend etwas sehr grundlegend verkehrt.
Multithreading und Multitasking haben erstmal gar nichts mit "real time" zu tun. Selbst das selige Windows 3.1 konnte TCP/IP und Gui "gleichzeitig", obwohl das nun wirklich gar nichts von sich aus gleichzeitig konnte.
obwohl das nun wirklich gar nichts von sich aus
gleichzeitig konnte.
Das konnte kooperatives Multitasking, damit hat es seine GUI verwaltet. TCP lief irgendwo im schmutzigen Hintergrund, mit Interrupts oder wie auch immer.
Das klingt mir sehr subjektiv und schlecht informiert/recherchiert vom
ursprünglichen Autor dieser Zeilen.
Fass dich an deine eigene Nase, bevor du hier auf andere zeigst. Ein paar Beispiele hat der Autor auch, die dann aber eher in Richtung Bugs aufgrund der Komplexität des schlecht wartbaren Codes gehen.
Bei Windows 3.1 ist die Aussage aber doch eher ein Euphemismus.
Nein, ganz und gar nicht. Das ist kein Euphemismus, sondern echtes kooperatives Multitasking.
Wenn man das (auf 386ern verfügbare) Multitasking von DOS-Prozessen parallel zur Windows-GUI meint - das ist kein kooperatives Multitasking, das ist präemptives Multitasking.
Kooperatives Multitasking über die Windows-Message-API haben schon viel ältere Windows-Versionen betrieben.
Wenn es gehakelt hat, dann lag das an schlecht geschriebenen Programmen - und nichts gibt es in der Windows-Welt mehr als schlecht geschriebene Programme. Das war zu 16-Bit-Zeiten so (wo es den kompletten Betrieb lahmlegen konnte), das ist aber auch heute noch so, nur wird heute viel, viel mehr Aufwand betrieben, die Auswirkungen abzufangen.
Kooperativ war übrigens auch das Multitasking der alten MacOS-Varianten (alles vor OS X).
Fass dich an deine eigene Nase, bevor du hier auf andere zeigst
Ich habe bzw. arbeite in zwei von den von mir genannten Bereichen und habe deshalb "etwas" Wissen. Deshalb fällt es mir schwer die Aussage des Autors als glaubhaft anzuerkennen. Selbst wenn mal etwas "durchrutscht" trotz aller Regelarien, ist das noch länger nicht zu verallgemeinern, so wie in den Buch geschehen. Trotz möglicher Beispiele...
Und immer freundlich bleiben gelle :)
Nase und so....
Aber egal, es ändert nichts daran, dass selbst preemtives Multitasking
erst einmal nichts mit Real time zu tun hat.
Tatsächlich kommen hier erst die Problem ins Spiel. Ein verlässliches Timing wie beim Atari ST oder wie bei DOS gab es jetzt nicht mehr - wie auch die einfache Hardwarezugänglichkeit/Schnittstelle nicht mehr. Und ohne richtiges DOS ist die Hardwarezugänglichkeit teilweise noch schlimmer.
Teilweise deswegen, weil die DOS-Emulation in Vista doch recht gut ging und bei alten Programmen weniger Probleme machte als die alten Kisten. Damals gab es aber noch andere potentielle Sorgenkinder wie z.B. DPMI - und ähnlich wie bei der Frage "welches Linux nehme ich denn?" drehten sich die Fragen damals um VGA oder FPU oder was immer -
Und aktuell steht ja auch so ein wenig Directx in Frage oder die Windowsversion selber.
Toll, wenn dann die hochqualititative Audiokarte keinen Direktx-Treiber oder Directx-Funktionalität mitbringt.
->
Da kam dann damals Ubuntu-Studio - und auf die RTOS brauchte man dann auch nicht mehr lange warten.
Ein Cubase für FreeDOS wäre eigentlich auch ganz nett gewesen.
https://help.ubuntu.com/community/UbuntuStudio/RealTimeKernel
Nein, ganz und gar nicht. Das ist kein Euphemismus, sondern echtes
kooperatives Multitasking.
So ist es und das gab es sogar noch sehr viel länger als Windows3.x in Form der diversen Varianten von "embedded Windows", die ich mal (vereinfachend) als "WindowsCE" zusammen fassen würde.
Da hat das auch einen Sinn ergeben, denn das lief auf teils wirklich recht mickrigen Architekturen und in vielen der damaligen Anwendungen braucht es obendrein tatsächlich RT-Eigenschaften.
Noch heute sind weltweit mindestens zehntausende, wenn nicht gar hunderttausende kleine Werkzeugmaschinen mit WindowsCE-Steuerung im Einsatz.
Tatsächlich kommen hier erst die Problem ins Spiel. Ein verlässliches
Timing wie beim Atari ST oder wie bei DOS gab es jetzt nicht mehr - wie
auch die einfache Hardwarezugänglichkeit/Schnittstelle nicht mehr. Und
ohne richtiges DOS ist die Hardwarezugänglichkeit teilweise noch
schlimmer.
DOS hatte gar kein Timing, und "Hardwarezugänglichkeit" scheiterte sehr oft schon am technischen Verständnis der Programmierer. Was ich an vergurkten Interpretationen der Ansteuerung einer seriellen Schnittstelle gesehen habe, geht auf keine Kuhhaut.
Dein Begriff von RTOS wird meist mit "hart" qualifiziert. Das nutzen
relativ wenige.
Genau. Ein RTOS im embedded Bereich ist Regel erstmal "nur" ein OS. Ob dessen realtime Fähigkeiten wirklich ausgenutzt /gebraucht werden hängt halt vom Anwendungsfall ab.
Interrupts sind die Emulation von MT und RT. Der Ticker für zyklische
Tasks, Scheduler über SW-Interrupts, HW-Interrupts als Semaphoren etc.
So ein vollendeten Quatsch habe ich je selten zuvor jemals gehört.
Nein, es ist natürlich genau anders herum: Interrupts sind das, was REAL existiert.
Zu was MT-OS die dann verwursten, hängt vom OS ab. Recht typisch für alle Ernstzunehmenden ist allerdings, dass sie Anwendungen nicht mehr direkt an die Interrupts ranlassen. Weil: wäre es anders, könnte sowas wie etwa RT-Anforderungen nur schwerlich garantiert werden.
Nein, es ist natürlich genau anders herum: Interrupts sind das, was
REAL existiert.
Ich kenne Deine Embedded Erfahrung nicht. Wenn Du Dir ein paar Deiner Projekte ohne MT ansiehst und Dir anschaust, wie Du es mit machen würdest, siehst Du oft die 1-1 Relation.
Was mich noch mehr stört als regelmäßiges Geplenke, sind dauernde Hinweise auf regelmäßiges Geplenke.
Ersteres überlese ich einfach, letzteres würde ich gern überlesen, erkenne es aber erst, nachdem ich es gelesen habe.
Hast Du auch noch was anderes beizutragen als Kritik an meiner Umgangsformenkritik? Ich habe die nur als Anmerkdung angebracht, davor aber was anderes geschrieben.
War das für Dich zu kompliziert, konntest Du das nicht verstehen?
Wenn irgendwas X mal gemacht werden soll, dann will ich da eine zählende
for Schleife sehen.
Ohne wenn und aber!
Wenn Deine Schleife auf einem System mit kooperativen Multitasking
laufen soll und nicht das ganze System während der Ausführungszeit der
Schleife blockiert sein soll, dann hast Du mit der Einstellung ein
Problem.
Nein mit meiner Einstellung habe ich kein Problem.
Die Problemvermeidung habe ich vorher schon genannt!
Siehe:
Arduino F. schrieb im Beitrag #7718678:
Adam Dunkels seine Protothreads
Ist dir das evtl. durch die Lappen gegangen?
Klar, kann man darüber streiten, wie geil oder scheiße diese Protothreads sind. Sicherlich wird die Ressourcenersparnis teuer erkauft, z.B. durch den quasi Verlust lokaler Variablen auf dem Stack.
Immerhin, kann man damit Schleifen so hinschreiben, wie man es auch in anderen Multitasking Systemen kann. Man muss sie nicht "ausrollen".
Bis zur Unkenntlichkeit zerreißen/verstümmeln.
Wenn irgendwas X mal gemacht werden soll, dann will ich da eine zählende
for Schleife sehen.
Das entspricht dem Prinzip der geringsten Verwunderung!
Und ist für kein ernsthaftes Multitaskingsystem ein Problem.
Angefangen hasts hier damit, dass du mich attackierst.
Ich habe Dich nicht "attackiert", das bildest Du Dir ein. Ich habe nur auf Deine fehlerhafte/stark vereinfachende und irreführende Darstellung reagiert.
Vielleicht sind dem Adam Dunkels seine Protothreads was für dich.
Die sind sehr beschränkt, keine Funktionsaufrufe und keine lokalen Variablen - das passt nicht mit existierenden zu benutzenden Komponenten wie z.B. Dateisystemen zusammen.
nicht immer, bei Mbed wurde das teilweise getrennt.
Danke, das ist schonmal interessant, ich habe jetzt auch gesehen dass Zephyr das auch kann. Das wäre grundsätzliche ein Möglichkeit sich die Komplexität des präemptiven Multithreading vom Leib zu halten, aber:
Asynchrone Architekturen
sind aber nicht jedermanns Sache, da muss man oft um die Ecke denken.
Ich finde asynchrone eventbasierte Architekturen wesentlich einfacher zu beherrschen als Multithreading. Es ist zwar mehr Code nötig, aber dadurch wird es auch besser verständlich.
Ich hatte durchaus das Gefühl dass es auch für Nicht-Echtzeit-Kritische Anwendungen benutzt wird, z.B. Smart Home- oder Multimedia-Anwendungen. Das muss ich wohl halluziniert haben.
Ungeteilt. Also, die Ethernet
Schnittstelle ist ein Thread.
Und ich dachte die Ethernet-Schnittstelle wäre eine Hardwarekomponente. z.B. bei Verwendung von lwIP gibt es einen IP-Thread, welcher aber mehrere Ethernet-Schnittstellen bearbeiten kann. Es gibt nicht pro Schnittstelle einen Thread.
Schlimmer noch: es muss noch nicht mal echte Asynchronität und die damit
verbundenen Probleme sein.
Ich würde lieber asynchron programmieren, aber das passt nicht zum Großteil der vorhandenen Frameworks und Bibliotheken. Und alles selbst implementieren ist einfach vom Zeitaufwand her nicht realistisch.
Habe ich schon. Ich habe viele Multithreading-Anwendungen geschrieben (auch verteilt auf Clustern) und auch ein eigenes RTOS implementiert und finde immer noch, das präemptives Multithreading schwer zu beherrschen ist.
Bei meinem ersten FreeRTOS-Projekt bin ich auf einen tückischen Bug im Scheduler gestoßen, welcher die Anwendung in unregelmäßigen Abständen abstürzen ließ. Nach einigen Wochen debugging habe ich den Fehler gefunden und den Fix bei FreeRTOS eingereicht (wurde akzeptiert). So etwas steigert nicht mein Vertrauen in die ganze RTOS-Thematik.
Ansonsten würden RTOS ja nicht in sicherheitskritischen Produkten
eingesetzt werden.
Guter Einwand, aber werden bei so etwas klassische Patterns wie Mutexe und Shared Memory benutzt? Werden hier nicht viel eher die Threads stark voneinander abgeschottet und Nachrichten ausgetauscht? Das sagt mir mehr zu, aber passt wiederum nicht (gut) zu gängigen RTOSen und deren Paradigmen (viele Mutexe).
Mit solchen Fragen geht man an die Uni, fragt viele Leute
Wie genau macht man das? Man spaziert die Gänge lang und macht ne Umfrage? Rein zufällig habe ich mich im Studium genau damit befasst und Arbeiten dazu geschrieben, aber eine erhellende Diskussion kam nie dabei heraus. Allerdings bin ich über Paper dieser Art gestolpert:
Welche dafür plädieren, dass klassisches präemptives Multithreading gar nicht so gut für die Zuverlässigkeit ist. Das berühmte THERAC-25 -Desaster ging auch auf fehlerhaftes Multitasking (allerdings nicht der präemptiven Art) zurück.
Das RTOS hilft einem ungemein bei dem Timing und den
Echtzeitanforderungen.
Natürlich geht das auch irgendwie ohne RTOS, aber ab einer gewissen
Komplexität der Anwendung nur mit sehr viel mehr Aufwand.
Ich finde das ist genau der Knackpunkt. Bei asynchroner Programmierung kann ich die Echtzeitanforderung über die Interrupt-Prioritäten erreichen. Der höchstprioritäre Interrupt hat eine fixe Latenz, der zweithöchste wird maximal um die Dauer des höchstprioritären verzögert usw. Wie geht das beim RTOS einfacher?
Dazu kommen noch andere Aspekte wie z.B. Energie sparen aber das führt
hier zu weit.
Das ist für mich auch sehr wichtig - Zephyr und andere haben ein Power Management welches an das runtime PM von Android erinnert. Dieses ins RTOS integrierte PM ist erforderlich damit man das RTOS stromsparend einsetzen kann, zusätzlich zum "tickless" -Betrieb. Ohne RTOS kann man das aber auch relativ gut selbst implementieren.
Dein Begriff von RTOS wird meist mit "hart" qualifiziert. Das nutzen
relativ wenige.
Genau. Ein RTOS im embedded Bereich ist Regel erstmal "nur" ein OS. Ob
dessen realtime Fähigkeiten wirklich ausgenutzt /gebraucht werden hängt
halt vom Anwendungsfall ab.
Die Programmierung über Events gefällt mir auch, z.B. in JavaScript bzw NodeJS ist das ja systemisch drin. Als Alternative zu vielen Threads die die CPU zyklisch nerven.
Ich habe viele Jahre mit einem proprietären RTOS gearbeitet das nur zyklische Tasks kannte. Hohe Prio hatten Messwertverarbeitung und Steuerung, dann kamen Schnittstellen und weiteres, zuletzt Grafikinterfaces und Druckeransteuerung. So liefen einige zig Tasks parallel und störungsfrei. Wenn es Probleme gab, dann war es Anwendungscode... Das kostet natürlich einen gewissen Overhead, aber auch Eventbasiert hat seine Tücken und Programmteile dürfen die CPU nicht zu lange beanspruchen. Letztendlich braucht man einfach genug Rechenpower.
So liefen einige zig Tasks
parallel und störungsfrei.
Ein ganz typisches Problem ist das Abbrechen von Operationen. z.B. könnte ein Messwert-Thread eine adc_read Funktion aufrufen die erst dann zurückkehrt, wenn die Konvertierung fertig ist. Währenddessen könnte per USB der Befehl reinkommen, die Messung abzubrechen. Die USB-Implementation läuft im Interrupt-Kontext, muss also sofort zurückkehren. Aber adc_read kann man nicht einfach so von außen abbrechen.
Ja, man kann es workarounden, aber es ist umständlich und eben schwer zu beherrschen. Besonders wenn dann die Messung sofort wieder aktiviert werden soll... Bei asynchroner Programmierung deaktiviert man einfach den ADC per Register und löscht zur Sicherheit noch das Interrupt-Flag, wodurch man die Messung mit 2 Zeilen problemlos abgewürgt hat.
Ja, ganz typisch für Embedded ist es ja, das jederzeit alle möglichen Ereignisse eintreten können. Bei asynchroner Programmierung kann man bei jedem Schritt sehr einfach auf jedes Ereignis reagieren und den aktuellen Zustand auswerten.
Beim RTOS hingegen habe ich Aufrufe wie adc_read, die nur auf genau ein Ereignis reagieren können. Andere Ereignisse muss ich in anderen Threads abfangen, die dann kompliziert mit ersten Thread (der adc_read aufruft) synchronisiert werden müssen. Ja, manche RTOSe können so etwas wie eine ADC-Konvertierung asynchron laufen lassen und einen Callback aufrufen - aber wozu benutze ich dann ein RTOS, wenn ich dann doch wieder asynchron arbeite?
aber wozu benutze ich dann ein RTOS, wenn ich dann doch wieder asynchron
arbeite?
Manchmal hat mal halt beides. Irgendwelche synchron arbeitenden Programmbibliotheken und selbst implementierten, asynchronen Code. Wir haben bei uns z.B. das Dateisystem auch zugekauft. Der asynchrone Code läuft halt in den höherprioren Task Kontexten und der synchrone Kram niederprior. Man kann aber auch im Asynchronen Code mehrere Prioritätsebenen haben: Möglicherweise will man das bestimmter Code eben mit möglichst wenig Latenz ausgeführt wird und dann braucht man auch bei asynchroner Architektur mehrere Prioritätsebenen wo die höheren die niedrigen einfach unterbrechen können. Und schon braucht man ein preemptives OS. Hier kann ich nur ein Beispiel aus meiner Arbeit bringen wo wir typischer z.B. drei Kontexte haben, einer mit Latenz < 200µs, einer mit Latenz < 4ms und einer, da kanns auch schon mal ne Sekunde dauern bis der Event verarbeitet wird. Teilweise liegt hier sogar der Code in unterschiedlich schnellen Speicherbereichen ab.
RTOS wird im embedded-Bereich als Synonym für Multitasking verwendet.
Egal ob preemtiv, kooperativ, mit und ohne Prioritäten oder Round Robin.
Nun ja, das „RT“ in RTOS steht nunmal für Real Time, und was das bedeutet, ist klar definiert.
Das mancher den Begriff falsch verwendet, ändert nichts daran.
und dann braucht man auch bei
asynchroner Architektur mehrere Prioritätsebenen wo die höheren die
niedrigen einfach unterbrechen können. Und schon braucht man ein
preemptives OS.
Mit verschachtelbaren Interrupts geht das auch, wie sie z.B. der Cortex-M hat. Das geht dann auch komplett asynchron, ohne präemptives Multithreading.