Mit Timer-Mechanismen können Sie den Betriebssystem-Kernel so planen, dass er eine Anwendung benachrichtigt, wenn eine vorgegebene Zeit verstrichen ist. Sie verwenden sie normalerweise, indem Sie zwei Informationen angeben. Zuerst müssen Sie angeben, wie lange der Timer dauern soll, bevor er benachrichtigt wird. Zweitens müssen Sie eine Rückruffunktion vorbereiten, die reagiert, wenn diese Benachrichtigung auftritt.

Traditioneller Ansatz für Timer

Timer-Mechanismen in Linux- und Unix-basierten Systemen wurden entwickelt, um verschiedenen Anforderungen gerecht zu werden. Verschiedene Ansätze können Ihnen helfen, verschiedene Arten von Problemen zu lösen. Allerdings sehen Sie oft die erste Version der Alarm() Mechanismus noch in Gebrauch.

Die Weckfunktion ist die einfachste Art, einen Timer zu verwenden; hier ist sein prototyp:

ohne VorzeichenintAlarm(ohne Vorzeichenint Sekunden);

Bei dieser Methode können Sie die Zeit nur in ganzen Sekunden angeben. Wenn die Zeit abgelaufen ist, sendet das Betriebssystem die

instagram viewer
SIGALRM Signal für Ihre Anwendung. Um den Ablauf des Timers in Ihrer Anwendung zu verarbeiten, sollten Sie zusätzlich eine Callback-Funktion definieren.

Hier ist ein Beispiel für eine Signal-Handler-Funktion:

#enthalten
#enthalten
#enthalten
#enthalten

Leeretimer_callback(int Zeichen)
{
Zeit_t jetzt = Zeit (NULL);
Druckf("Signal %d auf %li abgefangen", signum, now);
}

inthauptsächlich()
{
signal (SIGALRM, timer_callback);
Alarm(1);
schlafen(3);
Rückkehr0;
}

Dieser Code löst a aus SIGALRM Signal nach 1 zweite. Wenn Sie die Timer-Verzögerung auf fünf Sekunden erhöhen möchten, rufen Sie einfach an Wecker (5) stattdessen. Um den Timer zu stoppen, übergeben Sie den Wert 0: Wecker (0).

Wenn die Zeit abgelaufen ist, wird der von Ihnen verwendete Timer nicht regelmäßig neu gestartet. Wenn Sie beispielsweise eine weitere Sekunde verzögern möchten, sollten Sie den Mechanismus mit einem weiteren Aufruf von neu starten Alarm().

Trotz der einfachen Handhabung hat diese Methode einige Nachteile:

  • Nur ein Timer auf einmal.
  • Keine periodische Timer-Unterstützung.
  • Sie können den Zeitraum nur in Vielfachen ganzer Sekunden angeben.
  • Keine Möglichkeit zu wissen, wie viel Zeit auf einem Timer verbleibt.

Speichern Sie den oben angegebenen Beispielcode unter alarm.c. Wann Sie kompilieren und ausführen es, das Programm wird die aufrufen timer_callback Funktion nach einer Sekunde. Es wird dann aufgrund der verbleibenden zwei Sekunden gewartet schlafen (3) Linie, dann beenden.

$ gcc -o alarm alarm.c
$ Zeit ./Alarm
Signal 14 auf 1653490465 abgefangen
echte 0m1.004s
Benutzer 0m0.000s
sys 0m0.003s

Der Grund für die Verwendung des Zeitbefehls besteht darin, die Zeiten sehen zu können. Schaut man sich aber das Ergebnis an, beträgt die Gesamtlaufzeit keine drei Sekunden. Dies liegt an der SIGALRM Signal von Wecker (1) wenn die erste Sekunde abgelaufen ist, während die Systemaufruf verursacht durch die Schlaffunktion (3) läuft. Wenn dieses Signal ankommt, unterbricht es den für initiierten Syscall schlafen (3).

Verwenden eines Intervall-Timers

Der Intervall-Timer-Mechanismus war erstmals in Version 4.2 BSD verfügbar. Es war später von POSIX standardisiert. Seine wichtigsten Vorteile gegenüber dem traditionellen Alarm() basierende Timer-Methode sind:

  • Bietet Mikrosekundenauflösung.
  • Es ermöglicht eine detailliertere Steuerung der Zeitmessung über drei verschiedene Modi.
  • Es ist möglich, es einmal einzustellen und es regelmäßig arbeiten zu lassen.
  • Es ist möglich herauszufinden, wie lange es zu einem bestimmten Zeitpunkt vorhanden ist.

Funktionsprototypen, die für Intervall-Timer-Operationen verwendet werden, lauten wie folgt:

#enthalten

intSetitimer(int die, konst struct itimerval *neuerWert, struct itimerval *alterWert);
intgetitimer(int was, struct iterval *value);

Strukturtimerval
{
StrukturZeititIntervall;// nächster Wert
StrukturZeitesWert;// aktueller Wert
};

StrukturZeit
{
lang tv_sec;
lang tv_usec;
};

Wenn Sie einen Intervall-Timer einrichten möchten, müssen Sie die verwenden timerval Struktur. Sie müssen einen Wert mit dieser Struktur als zweites Argument an die übergeben Settimer Funktion.

Beispielsweise kann ein Intervalltimer, der Ihre Anwendung 1 Sekunde lang und dann alle 300 Millisekunden benachrichtigt, wie folgt eingerichtet werden:

StrukturtimervalneuerTimer;
StrukturtimervalOldtimer;

newTimer.itValue.tv_sec = 1;
newTimer.itValue.tv_usec = 0;

newTimer.itInterval.tv_sec = 0;
newTimer.itInterval.tv_usec = 300 * 1000;

setitimer (ITIMER_REAL, &newTimer, &oldTimer);

Wenn vor dem Setzen der neuen Werte ein Intervalltimer aktiv ist, werden dessen Werte an die Variablenadresse des übertragen timerval Typ, der dem dritten Parameter der Funktion gegeben wird.

Mit dem Intervall-Timer-Mechanismus können Sie drei verschiedene Arten von Timern einrichten. Geben Sie den Timer-Typ im ersten Parameter von an setitimer():

Timer-Typ Signal Erläuterung
ITIMER_REAL SIGALRM Unabhängig von der für die Anwendung aufgewendeten Zeit, berechnet über die gesamte verstrichene Zeit.
ITIMER_VIRTUAL SIGVTALRM Berechnet über die Zeit, in der die Anwendung nur im Benutzermodus ausgeführt wird.
ITIMER_PROF SIGPROF Berechnet über die Summe der Zeit, die die Anwendung sowohl im Benutzer- als auch im Systemmodus verbracht hat.

Sie können dieser Tabelle entnehmen, dass die ITIMER_REAL Typ sendet a SIGALRM Signal, genau wie die Alarm() Funktion.

Verwenden eines Intervalltimers und Alarm() in der gleichen Anwendung wird verwirrend sein. Sie können zwar eine zweite Überprüfung der verbleibenden Zeit mit vornehmen gettimer(), ist es nicht sinnvoll, sie gleichzeitig zu verwenden.

Hier ist ein Beispiel für die Definition der Signal-Handler-Funktion mit dem Debug-Header:

#enthalten
#enthalten
#enthalten
#enthalten
#enthalten
#enthalten
#enthalten
#enthalten "./debug.h"

Leeretimer_callback(int Zeichen)
{
StrukturZeitjetzt;
gettimeofday(&jetzt, NULL);
Druckf("Signal %d auf %li empfangen.%03li ", signum, jetzt.tv_sec, jetzt.tv_usec / 1000);
}

inthauptsächlich()
{
ohne Vorzeichenint übrig = 3;

Strukturtimervalnew_timer;
StrukturtimervalOldtimer;

new_timer.it_value.tv_sec = 1;
new_timer.it_value.tv_usec = 0;
new_timer.it_interval.tv_sec = 0;
new_timer.it_interval.tv_usec = 300 * 1000;

setitimer (ITIMER_REAL, &new_timer, &old_timer);
signal (SIGALRM, timer_callback);

während (schlafen (verbleibend) != 0)
{
wenn (Fehlernummer == EINTR)
debugf("Schlaf durch Signal unterbrochen");
anders
errorf("sleep error %s", strerror (errno));
}

Rückkehr0;
}

Der obige Code verwendet die schlafen() Funktion, um drei Sekunden zu warten. Während dieser Zeit läuft ein Intervalltimer, zunächst für eine Sekunde, dann im Intervall von 300 Millisekunden.

Speichern und kompilieren Sie zum besseren Verständnis den Beispielcode mit dem Namen Intervall.c:

$ gcc -o Intervall Intervall.c
$ Zeit ./Intervall
Signal 14 auf 1653493614.325 abgefangen
debug: Schlaf durch Signal unterbrochen (Hauptintervall.c: 36)
Signal 14 auf 1653493614.625 abgefangen
debug: Schlaf durch Signal unterbrochen (Hauptintervall.c: 36)
Signal 14 auf 1653493614.925 abgefangen
debug: Schlaf durch Signal unterbrochen (Hauptintervall.c: 36)
Signal 14 auf 1653493615.225 abgefangen
debug: Schlaf durch Signal unterbrochen (Hauptintervall.c: 36)
Signal 14 auf 1653493615.525 abgefangen
...

Wie Sie der Ausgabe entnehmen können, nachdem der Timer ausgeführt wurde, ruft er die Callback-Funktion alle 300 Millisekunden auf.

Nachdem Sie jedoch etwas länger gewartet haben, werden Sie feststellen, dass die Anwendung nicht beendet wird. Die Callback-Funktion wird weiterhin alle 300 Millisekunden ausgeführt. Wenn Sie den Intervallwert in Millisekunden erhöhen, sehen Sie, dass die Anwendung beendet wird. Dies liegt am Einsatzgebiet der schlafen() Funktion.

Bedeutung der Verwendung von Timern in Linux

Besonders für Echtzeitanwendungen ist der Timer-Mechanismus von großer Bedeutung. Dies ist auch eine Lösung, die für Leistungsoptimierungen verwendet wird. Sie können es sogar verwenden, um die Betriebszeit oder Latenz in Ihrer Anwendung zu messen. Es ist wichtig, Zeitgebermechanismen zu verwenden, um die verstrichene Zeit und Zeitübergangsereignisse zu verfolgen.

So kompilieren und installieren Sie Software aus der Quelle unter Linux

Lesen Sie weiter

TeilenTwitternTeilenEmail

Verwandte Themen

  • Programmierung
  • Programmierung
  • Linux-Tipps

Über den Autor

Fatih Küçükkarakurt (10 veröffentlichte Artikel)

Ein Ingenieur und Softwareentwickler, der ein Fan von Mathematik und Technik ist. Schon immer mochte er Computer, Mathematik und Physik. Er hat Spiele-Engine-Projekte sowie maschinelles Lernen, künstliche neuronale Netze und lineare Algebra-Bibliotheken entwickelt. Darüber hinaus arbeitet er weiter an maschinellem Lernen und linearen Matrizen.

Mehr von Fatih Küçükkarakurt

Abonnieren Sie unseren Newsletter

Abonnieren Sie unseren Newsletter für technische Tipps, Rezensionen, kostenlose E-Books und exklusive Angebote!

Klicken Sie hier, um sich anzumelden