Hallo zusammen,
ich möchte in einem Programm alle paar ms eine Aktion ausführen.
Dazu polle ich in einer Funktion gettimeofday und warte dann bis die
entsprechende Zeit vergangen ist. Das geht auch alles soweit.
Jedoch funktioniert nach einiger Zeit nichts mehr, da das System
offensichtlich überlastet ist. Offensichtlich zu viele Aufrufe von
gettimeofday.
Nun meine Frage, wie kann ich dafür sorgen das ich das System nicht
überlaste und dennoch in der Lage bin die ms zu zählen?
Das Ganze läuft auf Linux, hier ein Beispiel:
Sonst belegt dein Programm einen ganzen CPU Kern mit 100%.
Ich fürchte allerdings, dass dadurch das Problem noch nicht gelöst wird.
> Jedoch funktioniert nach einiger Zeit nichts mehr
Wie lange ist "einige Zeit"? Ich habs's ein paar Minuten laufen lassen -
klappt.
Ja, das ist schon klar. Allerdings möchte ich jede Millisekunde etwas
tun und das da oben war nur ein Beispiel.
Zu lange kann ich auch nicht warten, da andere Programmteile noch etwas
arbeiten müssen.
Also ist die Lösung hier eher soviel wie möglich und so wenig wie nötig.
Gruß
Michael
Michael schrieb:> Ja, das ist schon klar. Allerdings möchte ich jede Millisekunde etwas> tun und das da oben war nur ein Beispiel.
Dann verwende clock_nanosleep. Dem kannst du auch absolute Zeiten
vorgeben. Du ermittelst einmal am Anfang die Zeit, dann addierst du in
jedem Zyklus eine Millisekunde dazu und wartest bis zu dem Zeitpunkt,
der sich daraus ergibt. Damit ist die Zykluszeit immer genau 1 ms, egal
wie viel Rechenzeit deine Funktion zwischendrin braucht (solange das
nicht mehr als 1 ms ist, natürlich).
> Zu lange kann ich auch nicht warten, da andere Programmteile noch etwas> arbeiten müssen.
Dann musst du die Struktur des Programms überdenken. Entweder du hast
eine Hauptschleife, in der (blockierend) gewartet wird, bis es irgendwas
zu tun gibt (egal ob nun durch einen Timer oder ankommende Daten oder
Eingaben des Benutzer), nur dann aufwacht, seine Aufgaben abarbeitet und
sich wieder schlafen legt. Oder du machst getrennte Threads, um diese
Dinge zu entkoppeln.
Aber alle 10 µs aufzuwachen, um zu zählen, ob schon eine ms abgelaufen
ist, ist schlechtes Design. Abgesehen davon gibt es mindest-Dauern für
die Zeit, die nanosleep schläft und auch eine begrenzte Auflösung, je
nach Zielsystem.
> Also ist die Lösung hier eher soviel wie möglich und so wenig wie nötig.
Nein, das ist keine sinnvolle Lösung.
Übrigens: Wenn man ein präzises Timing will, ist zu bedenken, dass
nanosleep wie jeder Syscall durch Signale unterbrochen werden und damit
vorzeitig zurückkehren kann. Sofern du also mit Signalen arbeitest,
musst du das berücksichtigen.
Gibt es in dem "Framework" soetwas wie Timer? Ich mach solche Dinge eig.
immer mit Qt (QTimer, wenn ich mich richtig erinnere) es müsste doch
auch "direkt" so gehen, oder?
Bitte bedenkt, dass der Task Scheduler jedes laufende Programm aktiv
unterbricht und irgendwann wieder fortsetzt. Ich meine, dass das
Umschalt-Intervall ist standardmäßig weit mehr als eine Millisekunde
lang ist.
Auffallen wird das, sobald man mehr gleichzeitig aktive Programme als
CPU Kerne hat.
Wenn man in einem Linux jede Millisekunde was machen will, dann kommt
man mit sleep, gettimeofday usw. nicht weit. Der Scheduler vom Kernel
kann den Prozess zu jedem beliebigen Zeitpunkt für jede beliebe Zeit
anhalten, z.b. beim Speicherauslagern, anderen Prozessen mit höherer
Priorität sind aktiv, hohe Peripherielast.... Auch ist der
Scheduler-Zeitschlitz üblicherweise im Bereich von 10-100ms
Für sowas braucht man einen RT Kernel und dazu gibt es dann passende RT
Bibliotheken und Funktionen.
Ansonsten: Anständige Timings macht man mittels "poll". Dabei gibt man
eine absolute Zeit an und übergibt eine leere Liste von
File-Deskriptoren. Dann weis man auch gleich wieviel Zeit man zu spät
ist, und der Prozess schläft bis zum definierten Zeitpunkt.
Mit File-Descriptoren kann man dann natürlich auch auf "events"
reagieren.
Andreas M. schrieb:> Wenn man in einem Linux jede Millisekunde was machen will, dann kommt> man mit sleep, gettimeofday usw. nicht weit. Der Scheduler vom Kernel> kann den Prozess zu jedem beliebigen Zeitpunkt für jede beliebe Zeit> anhalten, z.b. beim Speicherauslagern, anderen Prozessen mit höherer> Priorität sind aktiv, hohe Peripherielast.... Auch ist der> Scheduler-Zeitschlitz üblicherweise im Bereich von 10-100ms>> Für sowas braucht man einen RT Kernel und dazu gibt es dann passende RT> Bibliotheken und Funktionen.
Die oben von mir erwähnte Funktion clock_nanosleep gehört da übrigens
dazu. Sie gehört zur librt (real time) und lässt ein sehr genaues
Einhalten der Millisekunde zu, sofern man den Thread auf
Realtime-Priorität stellt und den Prozess gegen Auslagerung sperrt.