Met timermechanismen kunt u de OS-kernel plannen om een toepassing op de hoogte te stellen wanneer een vooraf bepaalde tijd is verstreken. U gebruikt ze meestal door twee gegevens op te geven. Eerst moet u specificeren hoeveel tijd de timer moet nemen voordat u hiervan op de hoogte stelt. Ten tweede moet u een callback-functie voorbereiden om te handelen wanneer die melding plaatsvindt.
Traditionele benadering van timers
Timermechanismen in op Linux en Unix gebaseerde systemen zijn geëvolueerd om aan verschillende behoeften te voldoen. Verschillende benaderingen kunnen u helpen bij het oplossen van verschillende soorten problemen. Vaak zie je echter de eerste versie van de alarm() mechanisme nog steeds in gebruik.
De alarmfunctie is de eenvoudigste manier om een timer te gebruiken; hier is het prototype:
niet ondertekendintalarm(niet ondertekendint seconden);
Met deze methode kunt u de tijd alleen in hele seconden opgeven. Als de tijd om is, stuurt het besturingssysteem de SIGALRM signaal naar uw toepassing. Om het verstrijken van de timer in uw toepassing te verwerken, moet u ook een terugbelfunctie definiëren.
Hier is een voorbeeld van een signaalverwerkingsfunctie:
#erbij betrekken
#erbij betrekken
#erbij betrekken
#erbij betrekkenleegtetimer_callback(int teken)
{
time_t nu = tijd(NUL);
printf("Signaal %d gevangen op %li", signum, nu);
}
inthoofd()
{
signaal (SIGALRM, timer_callback);
alarm(1);
slaap(3);
opbrengst0;
}
Deze code werpt een op SIGALRM signaal na 1 seconde. Als je de timervertraging wilt verhogen tot vijf seconden, bel dan gewoon alarm (5) in plaats van. Geef een waarde van 0 door om de timer te stoppen: alarm (0).
Als de tijd om is, wordt de timer die u gebruikt niet periodiek opnieuw gestart. Als u bijvoorbeeld nog een seconde wilt uitstellen, moet u het mechanisme opnieuw starten met een nieuwe oproep naar: alarm().
Ondanks het gebruiksgemak heeft deze methode enkele nadelen:
- Slechts één timer tegelijk.
- Geen periodieke timerondersteuning.
- U kunt de tijdsperiode alleen in veelvouden van hele seconden geven.
- Geen manier om te weten hoeveel tijd er nog op een timer staat.
Sla de bovenstaande voorbeeldcode op als alarm.c. Wanneer je compileert en voert uit het, het programma roept de timer_callback functie na een seconde. Het zal dan de resterende twee seconden wachten vanwege de slapen (3) lijn, en dan beëindigen.
$ gcc -o alarm alarm.c
$ tijd ./alarm
Sein 14 gevangen op 1653490465
echte 0m1.004s
gebruiker 0m0.000s
sys 0m0.003s
De reden voor het gebruik van het tijdcommando is om de tijden te kunnen zien. Maar als je naar het resultaat kijkt, is de totale looptijd geen drie seconden. Dit komt door de SIGALRM signaal van alarm (1) wanneer de eerste seconde voorbij is, terwijl de syscall veroorzaakt door de slaapfunctie (3) actief is. Wanneer dit signaal arriveert, onderbreekt het de syscall die is gestart voor slapen (3).
Een intervaltimer gebruiken
Het intervaltimermechanisme was voor het eerst beschikbaar in versie 4.2 BSD. Het was later gestandaardiseerd door POSIX. De belangrijkste voordelen ten opzichte van de traditionele: alarm() gebaseerde timermethode zijn:
- Biedt een resolutie van microseconden.
- Het maakt het mogelijk om de tijdmeting in meer detail te regelen over drie verschillende modi.
- Het is mogelijk om het eenmalig in te stellen en periodiek te laten werken.
- Op elk moment kan worden nagegaan hoe lang het aanwezig is.
Functie-prototypes die worden gebruikt voor intervaltimerbewerkingen zijn als volgt:
#erbij betrekken
intsetitimer(int welke, const struct iterval *newValue, struct iterval *oldValue);
intgetitimer(int welke, struct iterval *waarde);structurereniterval
{
structurerentijdswaardeitInterval;// volgende waarde
structurerentijdswaardeitValue;// huidige waarde
};
structurerentijdswaarde
{
lang tv_sec;
lang tv_usec;
};
Als u een intervaltimer wilt instellen, moet u de iterval structureren. U moet een waarde doorgeven met deze struct als het tweede argument aan de timer instellen functie.
Een intervaltimer die uw toepassing gedurende 1 seconde en vervolgens elke 300 milliseconden op de hoogte stelt, kan bijvoorbeeld als volgt worden ingesteld:
structurerenitervalnieuweTimer;
structurerenitervalOld Timer;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);
Als er een intervaltimer actief is voordat de nieuwe waarden worden ingesteld, worden de waarden ervan overgedragen naar het variabele adres van de iterval type gegeven aan de derde parameter van de functie.
Met het intervaltimermechanisme kun je drie verschillende soorten timers instellen. Specificeer het timertype in de eerste parameter van settimeter():
Timertype: | Signaal | Uitleg |
---|---|---|
ITIMER_REAL | SIGALRM | Onafhankelijk van de tijdsbesteding van de applicatie, berekend over de totaal verstreken tijd. |
ITIMER_VIRTUAL | SIGVTALRM | Berekend over de tijd dat de applicatie alleen in de gebruikersmodus draait. |
ITIMER_PROF | SIGPROF | Berekend over de som van de tijd besteed door de applicatie in zowel gebruikers- als systeemmodus. |
U kunt aan deze tabel zien dat de ITIMER_REAL typ stuurt een SIGALRM signaal, net als de alarm() functie.
Een intervaltimer gebruiken en alarm() in dezelfde toepassing zal verwarrend zijn. Hoewel u een tweede controle van de resterende tijd kunt uitvoeren met gettimer(), heeft het geen zin om ze tegelijkertijd te gebruiken.
Hier is een voorbeeld van het definiëren van de signaalverwerkingsfunctie met de debug koptekst:
#erbij betrekken
#erbij betrekken
#erbij betrekken
#erbij betrekken
#erbij betrekken
#erbij betrekken
#erbij betrekken
#erbij betrekken "./debug.h"leegtetimer_callback(int teken)
{
structurerentijdswaardenu;
gettimeofday(&nu, NUL);
printf("Signaal %d opgevangen op %li.%03li ", signum, nu.tv_sec, nu.tv_usec / 1000);
}inthoofd()
{
niet ondertekendint overblijvend = 3;structurerenitervalnieuwe_timer;
structurerenitervalOld Timer;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);
signaal (SIGALRM, timer_callback);terwijl (slaap (resterend) != 0)
{
als (errno == EINTR)
debugf("slaap onderbroken door signaal");
anders
errorf("slaapfout %s", strerror (errno));
}
opbrengst0;
}
De bovenstaande code gebruikt de slaap() functie om drie seconden te wachten. Gedurende deze tijd loopt een intervaltimer, eerst één seconde, daarna met een interval van 300 milliseconden.
Voor een beter begrip, bewaar en compileer de voorbeeldcode met de naam interval.c:
$ gcc -o interval interval.c
$ tijd ./interval
Signaal 14 gevangen op 1653493614.325
debug: slaap onderbroken door signaal (hoofdinterval.c: 36)
Signaal 14 gevangen op 1653493614.625
debug: slaap onderbroken door signaal (hoofdinterval.c: 36)
Signaal 14 gevangen op 1653493614,925
debug: slaap onderbroken door signaal (hoofdinterval.c: 36)
Signaal 14 gevangen op 1653493615.225
debug: slaap onderbroken door signaal (hoofdinterval.c: 36)
Signaal 14 gevangen op 1653493615.525
...
Zoals je kunt zien aan de output nadat de timer loopt, roept deze elke 300 milliseconden de callback-functie aan.
Na wat langer wachten zult u echter merken dat de toepassing niet wordt beëindigd. Het blijft de callback-functie elke 300 milliseconden uitvoeren. Als u de intervalwaarde in milliseconden verhoogt, ziet u dat de toepassing wordt beëindigd. Dit komt door het gebruiksgebied van de slaap() functie.
Belang van het gebruik van timers in Linux
Vooral voor realtime toepassingen is het timermechanisme van groot belang. Dit is ook een oplossing die wordt gebruikt voor prestatie-optimalisaties. U kunt het zelfs gebruiken om de uptime of latentie in uw applicatie te meten. Het is belangrijk om timermechanismen te gebruiken om de verstreken tijd en tijdovergangsgebeurtenissen bij te houden.
Software van de bron compileren en installeren in Linux
Lees volgende
Gerelateerde onderwerpen
- Programmeren
- Programmeren
- Linux-tips
Over de auteur
Een ingenieur en softwareontwikkelaar die een fan is van wiskunde en technologie. Hij heeft altijd van computers, wiskunde en natuurkunde gehouden. Hij heeft zowel game-engine-projecten als machine learning, kunstmatige neurale netwerken en lineaire algebra-bibliotheken ontwikkeld. Bovendien blijft men werken aan machine learning en lineaire matrices.
Abonneer op onze nieuwsbrief
Word lid van onze nieuwsbrief voor technische tips, recensies, gratis e-boeken en exclusieve deals!
Klik hier om je te abonneren