Timermekanismer låter dig schemalägga OS-kärnan för att meddela ett program när en förutbestämd tid har förflutit. Du kommer vanligtvis att använda dem genom att tillhandahålla två delar av information. Först måste du ange hur lång tid timern ska ta innan du aviserar. För det andra måste du förbereda en återuppringningsfunktion för att agera när det meddelandet inträffar.
Traditionell metod för timers
Timermekanismer i Linux- och Unix-baserade system har utvecklats för att tillgodose olika behov. Olika tillvägagångssätt kan hjälpa dig att lösa olika typer av problem. Men du kommer ofta att se den första versionen av larm() mekanism som fortfarande används.
Larmfunktionen är det enklaste sättet att använda en timer; här är dess prototyp:
osigneradintlarm(osigneradint sekunder);
Med den här metoden kan du bara ange tiden i hela sekunder. När tiden är ute skickar operativsystemet SIGALRM signal till din ansökan. För att behandla timerns utgång i din applikation bör du också definiera en återuppringningsfunktion.
Här är ett exempel på en signalhanterarfunktion:
#omfatta
#omfatta
#omfatta
#omfattatomhettimer_återuppringning(int signum)
{
tid_t nu = tid(NULL);
printf("Signal %d fångad på %li", signum, nu);
}
inthuvud()
{
signal (SIGALRM, timer_callback);
larm(1);
sova(3);
lämna tillbaka0;
}
Denna kod väcker en SIGALRM signalera efter 1 andra. Om du vill öka timerns fördröjning till fem sekunder är det bara att ringa larm (5) istället. För att stoppa timern, skicka ett värde på 0: larm (0).
När tiden är ute kommer timern du använder inte att starta om med jämna mellanrum. Om du till exempel vill fördröja ytterligare en sekund bör du starta om mekanismen med ett annat samtal till larm().
Trots sin lätthet att använda har denna metod några nackdelar:
- Endast en timer åt gången.
- Inget periodiskt timerstöd.
- Du kan bara ange tidsperioden i multiplar av hela sekunder.
- Inget sätt att veta hur mycket tid som återstår på en timer.
Spara exempelkoden ovan som alarm.c. När du kompilerar och kör det kommer programmet att anropa timer_återuppringning fungerar efter en sekund. Den kommer sedan att vänta i de återstående två sekunderna på grund av sömn (3) linje och avsluta sedan.
$ gcc -o larm alarm.c
$ tid ./larm
Signal 14 fångade 1653490465
riktiga 0m1.004s
användare 0m0.000s
sys 0m0.003s
Anledningen till att man använder tidskommandot är för att kunna se tiderna. Men om man tittar på resultatet är den totala körtiden inte tre sekunder. Detta beror på SIGALRM signal från larm (1) när den första sekunden är uppe, medan den syscall orsakad av vilofunktionen (3) körs. När denna signal anländer avbryter den syscallet som initieras för sova (3).
Använda en intervalltimer
Intervalltimermekanismen var först tillgänglig i version 4.2 BSD. Det var senare standardiserad av POSIX. Dess främsta fördelar jämfört med den traditionella larm() baserad timermetod är:
- Ger mikrosekundsupplösning.
- Det gör det möjligt att kontrollera tidsmätningen mer detaljerat över tre olika lägen.
- Det är möjligt att ställa in den en gång och få den att fungera med jämna mellanrum.
- Det är möjligt att ta reda på hur länge den är närvarande vid ett givet tillfälle.
Funktionsprototyper som används för intervalltimeroperationer är följande:
#omfatta
intsetitimer(int som, konst struct itimerval *newValue, struct itimerval *oldValue);
intgetitimer(int vilket, struct itimerval *värde);strukturitimerval
{
strukturtidsperioditInterval;// nästa värde
strukturtidsperioditValue;// nuvarande värde
};
strukturtidsperiod
{
lång tv_sek;
lång tv_usec;
};
Om du vill ställa in en intervalltimer måste du använda itimerval struktur. Du måste skicka ett värde med denna struktur som det andra argumentet till inställningstimer fungera.
Till exempel kan en intervalltimer som meddelar din applikation i 1 sekund och sedan var 300:e millisekund ställas in enligt följande:
strukturitimervalny Timer;
strukturitimervalgammaldags;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);
Om det finns en aktiv intervalltimer innan de nya värdena ställs in, överförs dess värden till den variabla adressen för itimerval typ som ges till den tredje parametern i funktionen.
Du kan ställa in tre olika typer av timers med intervalltimermekanismen. Ange timertypen i den första parametern för setitimer():
Timertyp | Signal | Förklaring |
---|---|---|
ITIMER_REAL | SIGALRM | Oberoende av den tid applikationen spenderar, räknat över den totala förflutna tiden. |
ITIMER_VIRTUAL | SIGVTALRM | Beräknat över tiden som applikationen endast körs i användarläge. |
ITIMER_PROF | SIGPROF | Beräknat över summan av den tid som applikationen spenderar i både användar- och systemläge. |
Du kan se från den här tabellen att ITIMER_REAL typ skickar en SIGALRM signal, precis som larm() fungera.
Använda en intervalltimer och larm() i samma applikation kommer att vara förvirrande. Även om du kan göra en andra kontroll på den återstående tiden med gettimer(), det är inte meningsfullt att använda dem samtidigt.
Här är ett exempel på att definiera signalhanterarfunktionen med felsöka header:
#omfatta
#omfatta
#omfatta
#omfatta
#omfatta
#omfatta
#omfatta
#omfatta "./debug.h"tomhettimer_återuppringning(int signum)
{
strukturtidsperiodnu;
gettimeofday(&nu, NULL);
printf("Signal %d fångades på %li.%03li ", signum, now.tv_sec, now.tv_usec / 1000);
}inthuvud()
{
osigneradint återstående = 3;strukturitimervalny_timer;
strukturitimervalgammaldags;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);medan (sömn (återstående) != 0)
{
om (fel == EINTR)
debugf("sömn avbruten av signal");
annan
errorf("sömnfel %s", strerror (errno));
}
lämna tillbaka0;
}
Ovanstående kod använder sova() funktion för att vänta i tre sekunder. Under denna tid körs en intervalltimer, först i en sekund, sedan med ett intervall på 300 millisekunder.
För bättre förståelse, spara och kompilera exempelkoden med namnet intervall.c:
$ gcc -o intervall interval.c
$ tid ./intervall
Signal 14 fångade 1653493614.325
debug: sömn avbruten av signal (huvudintervall.c: 36)
Signal 14 fångade 1653493614.625
debug: sömn avbruten av signal (huvudintervall.c: 36)
Signal 14 fångade 1653493614.925
debug: sömn avbruten av signal (huvudintervall.c: 36)
Signal 14 fångade 1653493615.225
debug: sömn avbruten av signal (huvudintervall.c: 36)
Signal 14 fångade 1653493615.525
...
Som du kan se från utgången efter att timern har körts, anropar den återuppringningsfunktionen var 300:e millisekund.
Men efter att ha väntat lite längre kommer du att märka att programmet inte avslutas. Den fortsätter att köra återuppringningsfunktionen var 300:e millisekund. Om du ökar intervallvärdet i millisekunder ser du att applikationen avslutas. Detta beror på användningsområdet för sova() fungera.
Vikten av att använda timer i Linux
Speciellt för realtidsapplikationer är timermekanismen av stor betydelse. Detta är också en lösning som används för prestandaoptimering. Du kan till och med använda den för att mäta drifttid eller latens i din applikation. Det är viktigt att använda timermekanismer för att hålla reda på förfluten tid och tidsövergångshändelser.
Hur man kompilerar och installerar programvara från källan i Linux
Läs Nästa
Relaterade ämnen
- Programmering
- Programmering
- Linux tips
Om författaren

En ingenjör och mjukvaruutvecklare som är ett fan av matematik och teknik. Han har alltid gillat datorer, matematik och fysik. Han har utvecklat spelmotorprojekt samt maskininlärning, artificiella neurala nätverk och linjära algebrabibliotek. Fortsätter dessutom att arbeta med maskininlärning och linjära matriser.
Prenumerera på vårt nyhetsbrev
Gå med i vårt nyhetsbrev för tekniska tips, recensioner, gratis e-böcker och exklusiva erbjudanden!
Klicka här för att prenumerera