LINUX Timer für zyklisches Aufrufen von Funktionen
-
Hallo SeppJ,
danke für das Umleiten und deine Antwort.
Leider bin ich totaler Anfänger und bräuchte ein bisschen mehr Hilfe.
Könntest du mir das ausführlicher aufzeigen ?
-
#include <stdio.h> #include <pthread.h> #include <unistd.h> void *funktion( void* data) { printf("hallo\n"); } int main ( int argc , char ** argv ) { int pause = 100000; pthread_t thread ; while(1) { pthread_create ( &thread , 0 , funktion , 0 ); usleep(pause); } }
mit -lpthread linken
-
Hallo,
danke, jetzt versteh ich es jetzt besser
Eine Frage: Mir wurde beigebracht, dass while(1) nicht verwendet werden solle, weil es zu hohe Auslastung hat ..... stimmt das ?
Wenn ja, wie kann man das verhindern ?
-
Wer hat dir das denn beigebracht?
while(1) ist eine Endlosschleife und die Auslastung hängt davon ab was in der Schleife steht.
Rate mal was usleep() macht - oder lies die manpage dazu.
-
Da wir faule Programmierer sind, machen wir es natürlich gleich so, dass wir unsere Lösung wiederverwenden können. Letztlich brauche ich sogar überhaupt keine Mittel der Linux-Systemprogrammierung (von daher war das Verschieben wohl etwas voreilig), da die nötigen Mittel längst in den C++-Standard eingeflossen sind:
#include <thread> #include <atomic> #include <chrono> #include <functional> class RepeatingTask { private: std::atomic_int running; std::function<void()> task; std::chrono::nanoseconds interval; void execute_task() { while(running) { std::thread t(task); t.detach(); std::this_thread::sleep_for(interval); } } public: RepeatingTask(std::function<void()> task, std::chrono::nanoseconds interval): running(0), task(task), interval(interval) {} // Ob und wie man diese Klasse kopieren kann, sei dem geneigten Leser überlassen: RepeatingTask(const RepeatingTask&) = delete; RepeatingTask &operator=(const RepeatingTask&) = delete; void run() { running = 1; std::thread t(std::bind(&RepeatingTask::execute_task, this)); t.detach(); } void stop() {running = 0;} }; // Beispiel #include <iostream> void ausgabe() { std::cout << "Buh!\n"; } int main() { using namespace std::chrono_literals; RepeatingTask task(ausgabe, 2s); task.run(); std::this_thread::sleep_for(5s); task.stop(); std::this_thread::sleep_for(5s); }
Die Task-Klasse benötigt C++11 (sollte jeder gängige Compiler unter Linux beherrschen). Das Beispiel benötigt C++14, weil ich demonstrieren wollte, wie schön man die Zeitintervalle damit schreiben kann. Braucht etwas aktuellere Compiler, wenn man das so machen möchte; ansonsten muss man eben die alten Methoden aus chrono benutzen.
-
Danke für die ausführliche Erklärung.
Damit versteht man es wirklich super.
Eine Frage noch:
Ich habe nanoseconds in milliseconds geändert.
Ich habe das using namespace std::chrono_literals wegmachen müssen, da er es nicht kannte.aber er meckert noch bei:
std::this_thread::sleep_for(5s);
Genauer Output:
error: unable to find numeric literal operator 'operator"" ms'
liegt das am C++14 standard ??
ich hab aber in meinem Makefile std=c++0x verlinkt, seitdem kann er auch c++11
-
Ergänzung:
Hatte die Zeile von oben kopiert...
bei mir steht statt 5s 5000ms da
-
Okay, es lag wirklich an c++14, was mein Compiler nicht mochte
Hab es einfach so umgeschrieben und es geht (ungetestet, nur fehlerfrei kompiliert)
int main() { RepeatingTask task(ausgabe, std::chrono::milliseconds(1000)); task.run(); std::this_thread::sleep_for(std::chrono::milliseconds(5000)); task.stop(); std::this_thread::sleep_for(std::chrono::milliseconds(5000)); }
Danke an SeppJ
-
Deine Vermutungen sind allesamt korrekt (wobei ich nicht verstehe, was du dir davon erhoffst, Millisekunden statt Nanosekunden zu speichern. Schließlich hat die Art der Speicherung nichts damit zu tun, wie die Angabe auszusehen hat).
Falls du den GCC benutzt, der kennt die Chronoliterale ab ungefähr Version 4.9.3. Ich musste selber auch erst eine neue Version installieren
-
Hallo SeppJ,
ja, das weiß ich auch nicht, was ich mir davon erhofft habe
Ich habe es inzwischen getestet und es läuft schonmal.
-
EDIT:
Ich nutze ptxdist