Timermekanismer giver dig mulighed for at planlægge OS-kernen til at underrette en applikation, når en forudbestemt tid er gået. Du vil typisk bruge dem ved at give to stykker information. Først skal du angive, hvor lang tid timeren skal tage, før du giver besked. For det andet skal du forberede en tilbagekaldsfunktion for at handle, når denne meddelelse opstår.

Traditionel tilgang til timere

Timermekanismer i Linux- og Unix-baserede systemer har udviklet sig til at opfylde forskellige behov. Forskellige tilgange kan hjælpe dig med at løse forskellige typer problemer. Du vil dog ofte se den første version af alarm() mekanisme stadig i brug.

Alarmfunktionen er den enkleste måde at bruge en timer på; her er dens prototype:

usigneretintalarm(usigneretint sekunder);

Ved at bruge denne metode kan du kun angive tiden i hele sekunder. Når tiden er gået, sender operativsystemet SIGALRM signal til din ansøgning. For at behandle timerens udløb i din applikation, bør du også definere en tilbagekaldsfunktion.

instagram viewer

Her er et eksempel på en signalhåndteringsfunktion:

#omfatte
#omfatte
#omfatte
#omfatte

ugyldigtimer_tilbagekald(int signum)
{
tid_t nu = tid(NUL);
printf("Signal %d fanget på %li", signum, nu);
}

intvigtigste()
{
signal (SIGALRM, timer_tilbagekald);
alarm(1);
søvn(3);
Vend tilbage0;
}

Denne kode rejser en SIGALRM signal efter 1 sekund. Hvis du vil øge timerforsinkelsen til fem sekunder, skal du bare ringe alarm (5) i stedet. For at stoppe timeren skal du sende en værdi på 0: alarm (0).

Når tiden er gået, vil den timer, du bruger, ikke genstarte med jævne mellemrum. For eksempel, hvis du vil forsinke et sekund mere, bør du genstarte mekanismen med endnu et opkald til alarm().

På trods af dens brugervenlighed har denne metode nogle ulemper:

  • Kun én timer ad gangen.
  • Ingen periodisk timerunderstøttelse.
  • Du kan kun angive tidsperioden i multipla af hele sekunder.
  • Ingen måde at vide, hvor meget tid der er tilbage på en timer.

Gem prøvekoden angivet ovenfor som alarm.c. Hvornår du kompilerer og kører det, vil programmet kalde timer_tilbagekald funktion efter et sekund. Den vil så vente i de resterende to sekunder pga søvn (3) linje, og afslut derefter.

$ gcc -o alarmalarm.c
$ tid ./alarm
Signal 14 fanget på 1653490465
reelle 0m1.004s
bruger 0m0.000s
sys 0m0.003s

Grunden til at bruge tidskommandoen er at kunne se tiderne. Men hvis man ser på resultatet, er den samlede køretid ikke tre sekunder. Dette skyldes SIGALRM signal fra alarm (1) når det første sekund er gået, mens den syscall forårsaget af dvalefunktionen (3) kører. Når dette signal ankommer, afbryder det syscallet, der er startet for søvn (3).

Brug af en intervaltimer

Intervaltimermekanismen var først tilgængelig i version 4.2 BSD. Det var senere standardiseret af POSIX. Dens vigtigste fordele i forhold til den traditionelle alarm() baseret timer metode er:

  • Giver mikrosekund opløsning.
  • Det gør det muligt at kontrollere tidsmålingen mere detaljeret over tre forskellige tilstande.
  • Det er muligt at indstille det én gang og få det til at virke periodisk.
  • Det er muligt at finde ud af, hvor længe den er til stede på et givet tidspunkt.

Funktionsprototyper, der bruges til intervaltimeroperationer, er som følger:

#omfatte

intsetitimer(int hvilken, konst struct itimerval *newValue, struct itimerval *oldValue);
intgetitimer(int hvilken, struct itimerval *værdi);

strukturitimerval
{
strukturtidsrumitInterval;// næste værdi
strukturtidsrumitVærdi;// nuværende værdi
};

strukturtidsrum
{
lang tv_sek;
lang tv_usec;
};

Hvis du vil konfigurere en intervaltimer, skal du bruge itimerval struktur. Du skal sende en værdi ved at bruge denne struct som det andet argument til indstille timer fungere.

For eksempel kan en intervaltimer, der giver din applikation besked i 1 sekund og derefter hvert 300. millisekund, konfigureres som følger:

strukturitimervalny Timer;
strukturitimervaloldTimer;

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);

Hvis der er en intervaltimer aktiv, før de nye værdier indstilles, overføres dens værdier til den variable adresse på itimerval type givet til den tredje parameter i funktionen.

Du kan opsætte tre forskellige typer timere med intervaltimer-mekanismen. Angiv timertypen i den første parameter af setitimer():

Timer type Signal Forklaring
ITIMER_REAL SIGALRM Uafhængigt af den tid, applikationen har brugt, beregnet over den samlede forløbne tid.
ITIMER_VIRTUAL SIGVTALRM Beregnet over den tid, applikationen kun kører i brugertilstand.
ITIMER_PROF SIGPROF Beregnet over summen af ​​den tid, applikationen bruger i både bruger- og systemtilstand.

Du kan se fra denne tabel, at ITIMER_REAL type sender en SIGALRM signal, ligesom alarm() fungere.

Brug af en intervaltimer og alarm() i samme applikation vil være forvirrende. Selvom du kan foretage en anden kontrol af den resterende tid med gettimer(), giver det ikke mening at bruge dem samtidigt.

Her er et eksempel på at definere signalhåndteringsfunktionen med debug header:

#omfatte
#omfatte
#omfatte
#omfatte
#omfatte
#omfatte
#omfatte
#omfatte "./debug.h"

ugyldigtimer_tilbagekald(int signum)
{
strukturtidsrumnu;
gettimeofday(&nu, NUL);
printf("Signal %d fanget på %li.%03li ", signum, now.tv_sec, now.tv_usec / 1000);
}

intvigtigste()
{
usigneretint resterende = 3;

strukturitimervalny_timer;
strukturitimervalold_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, &ny_timer, &gammel_timer);
signal (SIGALRM, timer_tilbagekald);

mens (søvn (resterende) != 0)
{
hvis (fejl == EINTR)
debugf("søvn afbrudt af signal");
andet
errorf("søvnfejl %s", strerror (errno));
}

Vend tilbage0;
}

Ovenstående kode bruger søvn() funktion til at vente i tre sekunder. I løbet af denne tid kører en intervaltimer, først i et sekund, derefter med et interval på 300 millisekunder.

For bedre forståelse skal du gemme og kompilere eksempelkoden med navnet interval.c:

$ gcc -o interval interval.c
$ tid ./interval
Signal 14 fanget på 1653493614.325
debug: dvale afbrudt af signal (hovedinterval.c: 36)
Signal 14 fanget på 1653493614.625
debug: dvale afbrudt af signal (hovedinterval.c: 36)
Signal 14 fanget på 1653493614.925
debug: dvale afbrudt af signal (hovedinterval.c: 36)
Signal 14 fanget på 1653493615.225
debug: dvale afbrudt af signal (hovedinterval.c: 36)
Signal 14 fanget på 1653493615.525
...

Som du kan se på outputtet efter timeren kører, kalder den tilbagekaldsfunktionen hvert 300 millisekund.

Men efter at have ventet lidt længere, vil du bemærke, at applikationen ikke afsluttes. Den fortsætter med at køre tilbagekaldsfunktionen hvert 300 millisekund. Hvis du øger intervalværdien i millisekunder, vil du se, at applikationen afsluttes. Dette er på grund af brugsområdet for søvn() fungere.

Vigtigheden af ​​at bruge timere i Linux

Især til realtidsapplikationer er timermekanismen af ​​stor betydning. Dette er også en løsning, der bruges til ydelsesoptimeringer. Du kan endda bruge det til at måle oppetid eller latens i din applikation. Det er vigtigt at bruge timermekanismer til at holde styr på forløbet tid og tidsovergange.

Sådan kompileres og installeres software fra kilde i Linux

Læs Næste

DelTweetDelE-mail

Relaterede emner

  • Programmering
  • Programmering
  • Linux tips

Om forfatteren

Fatih Küçükkarakurt (10 artikler udgivet)

En ingeniør og softwareudvikler, der er fan af matematik og teknologi. Han har altid godt kunne lide computere, matematik og fysik. Han har udviklet spilmotorprojekter samt maskinlæring, kunstige neurale netværk og lineære algebrabiblioteker. Arbejder desuden med maskinlæring og lineære matricer.

Mere fra Fatih Küçükkarakurt

Abonner på vores nyhedsbrev

Tilmeld dig vores nyhedsbrev for tekniske tips, anmeldelser, gratis e-bøger og eksklusive tilbud!

Klik her for at abonnere