LINUX Timer für zyklisches Aufrufen von Funktionen



  • Hallo Leute,

    ich finde einfach nichts zu meinem Problem im Web.
    Entweder sind alle Lösungen in anderen Programmiersprachen oder es bezieht sich auf Windows. 😞

    Ich hoffe sehr, dass ihr mir hier helfen könnt.

    Ich brauche eine Art Timer, mit dem ich zyklisch aller z.B. 1s eine bestimmte Funktion aufrufen kann unter Linux.
    Dies soll auch multithreading unterstützen, da ich mehrere Timer benötige mit unterschiedlichen Intervallen.

    Ich hoffe, ich konnte es gut verständlich erklären 😕

    und ihr könnt mir helfen



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


  • Mod

    Thread erstellen, Intervall warten, Funktion aufrufen, Repeat?



  • Qt hat so etwas. Wenn du dir dafür eine fette Bibliothek ans Beim binden willst ...



  • 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.


  • Mod

    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 👍 👍


  • Mod

    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 😉


Anmelden zum Antworten