Timermekanismer lar deg planlegge at OS-kjernen skal varsle en applikasjon når en forhåndsbestemt tid har gått. Du vil vanligvis bruke dem ved å oppgi to opplysninger. Først må du spesifisere hvor lang tid tidtakeren skal ta før du varsler. For det andre må du forberede en tilbakeringingsfunksjon for å handle når det varselet inntreffer.

Tradisjonell tilnærming til timere

Timermekanismer i Linux- og Unix-baserte systemer har utviklet seg for å dekke ulike behov. Ulike tilnærminger kan hjelpe deg med å løse ulike typer problemer. Imidlertid vil du ofte se den første versjonen av alarm() mekanismen som fortsatt er i bruk.

Alarmfunksjonen er den enkleste måten å bruke en timer på; her er prototypen:

usignertintalarm(usignertint sekunder);

Ved å bruke denne metoden kan du bare spesifisere tiden i hele sekunder. Når tiden er ute, sender operativsystemet SIGALRM signal til søknaden din. For å behandle tidtakerens utløp i applikasjonen din, bør du også definere en tilbakeringingsfunksjon.

Her er et eksempel på en signalbehandlingsfunksjon:

instagram viewer
#inkludere
#inkludere
#inkludere
#inkludere

tomromtimer_callback(int signum)
{
tid_t nå = tid(NULL);
printf("Signal %d fanget på %li", signum, nå);
}

inthoved-()
{
signal (SIGALRM, timer_callback);
alarm(1);
sove(3);
komme tilbake0;
}

Denne koden reiser en SIGALRM signal etter 1 sekund. Hvis du vil øke tidsforsinkelsen til fem sekunder, er det bare å ringe alarm (5) i stedet. For å stoppe tidtakeren, send en verdi på 0: alarm (0).

Når tiden er ute, starter ikke timeren du bruker på nytt med jevne mellomrom. For eksempel, hvis du ønsker å utsette et sekund til, bør du starte mekanismen på nytt med et nytt anrop til alarm().

Til tross for dens brukervennlighet har denne metoden noen ulemper:

  • Bare én timer om gangen.
  • Ingen periodisk timerstøtte.
  • Du kan bare angi tidsperioden i multipler av hele sekunder.
  • Ingen måte å vite hvor mye tid som gjenstår på en tidtaker.

Lagre eksempelkoden gitt ovenfor som alarm.c. Når du kompilerer og kjører det vil programmet kalle timer_callback funksjon etter ett sekund. Den vil da vente i de resterende to sekundene på grunn av sove (3) linje, og deretter avslutte.

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

Grunnen til å bruke tidskommandoen er å kunne se tidene. Men hvis du ser på resultatet, er ikke den totale kjøretiden tre sekunder. Dette er på grunn av SIGALRM signal fra alarm (1) når første sekund er oppe, mens syscall forårsaket av at dvalefunksjonen (3) kjører. Når dette signalet ankommer, avbryter det syscallen som er initiert for sove (3).

Bruke en intervalltimer

Intervalltimermekanismen var først tilgjengelig i versjon 4.2 BSD. Det var senere standardisert av POSIX. Dens viktigste fordeler fremfor den tradisjonelle alarm() basert timermetode er:

  • Gir mikrosekund oppløsning.
  • Den lar deg kontrollere tidsmålingen mer detaljert over tre forskjellige moduser.
  • Det er mulig å sette den en gang og få den til å fungere med jevne mellomrom.
  • Det er mulig å finne ut hvor lenge den er tilstede til enhver tid.

Funksjonsprototyper som brukes for intervalltimeroperasjoner er som følger:

#inkludere

intsetitimer(int hvilken, konst struct itimerval *newValue, struct itimerval *oldValue);
intgetitimer(int som, struct itimerval *verdi);

strukturitimerval
{
strukturtidsperiodeitInterval;// neste verdi
strukturtidsperiodeitValue;// nåværende verdi
};

strukturtidsperiode
{
lang tv_sek;
lang tv_usec;
};

Hvis du vil sette opp en intervalltimer, må du bruke itimerval struktur. Du må sende en verdi ved å bruke denne strukturen som det andre argumentet til setttimer funksjon.

For eksempel kan en intervalltimer som vil varsle applikasjonen din i 1 sekund og deretter hvert 300. millisekund settes opp som følger:

strukturitimervalnewTimer;
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 det er en intervalltimer aktiv før de nye verdiene settes, blir verdiene overført til den variable adressen til itimerval type gitt til den tredje parameteren til funksjonen.

Du kan sette opp tre forskjellige typer timere med intervalltimermekanismen. Spesifiser timertypen i den første parameteren til setitimer():

Timer Type Signal Forklaring
ITIMER_REAL SIGALRM Uavhengig av tiden applikasjonen har brukt, beregnet over totalt medgått tid.
ITIMER_VIRTUAL SIGVTALRM Beregnet over tiden applikasjonen kjører kun i brukermodus.
ITIMER_PROF SIGPROF Beregnet over summen av tiden applikasjonen bruker i både bruker- og systemmodus.

Du kan se fra denne tabellen at ITIMER_REAL type sender en SIGALRM signal, akkurat som alarm() funksjon.

Ved hjelp av en intervalltimer og alarm() i samme applikasjon vil være forvirrende. Selv om du kan foreta en ny sjekk på gjenværende tid med gettimer(), er det ikke fornuftig å bruke dem samtidig.

Her er et eksempel på å definere signalbehandlerfunksjonen med debug header:

#inkludere
#inkludere
#inkludere
#inkludere
#inkludere
#inkludere
#inkludere
#inkludere "./debug.h"

tomromtimer_callback(int signum)
{
strukturtidsperiode;
gettimeofday(&nå, NULL);
printf("Signal %d fanget på %li.%03li ", signum, now.tv_sec, now.tv_usec / 1000);
}

inthoved-()
{
usignertint gjenværende = 3;

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

samtidig som (søvn (gjenstår) != 0)
{
hvis (feil == EINTR)
debugf("søvn avbrutt av signal");
ellers
errorf("søvnfeil %s", strerror (feilno));
}

komme tilbake0;
}

Koden ovenfor bruker sove() funksjon for å vente i tre sekunder. I løpet av denne tiden kjører en intervalltimer, først i ett sekund, deretter med et intervall på 300 millisekunder.

For bedre forståelse, lagre og kompiler eksempelkoden med navnet intervall.c:

$ gcc -o intervall interval.c
$ tid ./intervall
Signal 14 fanget på 1653493614.325
feilsøking: søvn avbrutt av signal (hovedintervall.c: 36)
Signal 14 fanget på 1653493614.625
feilsøking: søvn avbrutt av signal (hovedintervall.c: 36)
Signal 14 fanget på 1653493614.925
feilsøking: søvn avbrutt av signal (hovedintervall.c: 36)
Signal 14 fanget på 1653493615.225
feilsøking: søvn avbrutt av signal (hovedintervall.c: 36)
Signal 14 fanget på 1653493615.525
...

Som du kan se fra utgangen etter at timeren har kjørt, kaller den tilbakeringingsfunksjonen hvert 300. millisekund.

Etter å ha ventet litt lenger, vil du imidlertid legge merke til at programmet ikke avsluttes. Den fortsetter å kjøre tilbakeringingsfunksjonen hvert 300. millisekund. Hvis du øker intervallverdien i millisekunder, vil du se at applikasjonen avsluttes. Dette er på grunn av bruksområdet til sove() funksjon.

Viktigheten av å bruke timere i Linux

Spesielt for sanntidsapplikasjoner er timermekanismen av stor betydning. Dette er også en løsning som brukes for ytelsesoptimalisering. Du kan til og med bruke den til å måle oppetid eller ventetid i applikasjonen din. Det er viktig å bruke tidtakermekanismer for å holde styr på medgått tid og tidsovergangshendelser.

Hvordan kompilere og installere programvare fra kilde i Linux

Les Neste

DelekvitringDeleE-post

Relaterte temaer

  • Programmering
  • Programmering
  • Linux-tips

Om forfatteren

Fatih Küçükkarakurt (10 artikler publisert)

En ingeniør og programvareutvikler som er en fan av matematikk og teknologi. Han har alltid likt datamaskiner, matematikk og fysikk. Han har utviklet spillmotorprosjekter samt maskinlæring, kunstige nevrale nettverk og lineære algebrabiblioteker. Videre fortsetter arbeidet med maskinlæring og lineære matriser.

Mer fra Fatih Küçükkarakurt

Abonner på vårt nyhetsbrev

Bli med i vårt nyhetsbrev for tekniske tips, anmeldelser, gratis e-bøker og eksklusive tilbud!

Klikk her for å abonnere