I meccanismi del timer consentono di pianificare il kernel del sistema operativo per notificare a un'applicazione quando è trascorso un tempo predeterminato. In genere li utilizzerai fornendo due informazioni. Innanzitutto, dovrai specificare quanto tempo dovrebbe impiegare il timer prima di notificare. In secondo luogo, dovrai preparare una funzione di callback che agisca quando si verifica quella notifica.

Approccio tradizionale ai timer

I meccanismi del timer nei sistemi basati su Linux e Unix si sono evoluti per soddisfare varie esigenze. Approcci diversi possono aiutarti a risolvere diversi tipi di problemi. Tuttavia, vedrai spesso la prima versione di allarme() meccanismo ancora in uso.

La funzione sveglia è il modo più semplice per utilizzare un timer; ecco il suo prototipo:

non firmatointallarme(non firmatoint secondi);

Usando questo metodo, puoi solo specificare il tempo in secondi interi. Quando il tempo è scaduto, il sistema operativo invia il file SIGALRM segnale alla tua applicazione. Per elaborare la scadenza del timer nella tua applicazione, dovresti anche definire una funzione di callback.

instagram viewer

Ecco un esempio di una funzione di gestione del segnale:

#includere
#includere
#includere
#includere

vuototimer_richiamata(int segno)
{
tempo_t ora = ora(NULLO);
stampa f("Segnale %d catturato su %li", signum, ora);
}

intprincipale()
{
segnale (SIGALRM, timer_callback);
allarme(1);
dormire(3);
Restituzione0;
}

Questo codice genera a SIGALRM segnale dopo 1 secondo. Se vuoi aumentare il ritardo del timer a cinque secondi, chiama allarme (5) invece. Per fermare il timer, passare un valore di 0: allarme (0).

Allo scadere del tempo, il timer utilizzato non si riavvierà periodicamente. Ad esempio, se si desidera ritardare di un altro secondo, è necessario riavviare il meccanismo con un'altra chiamata a allarme().

Nonostante la sua facilità d'uso, questo metodo presenta alcuni svantaggi:

  • Solo un timer alla volta.
  • Nessun supporto periodico del timer.
  • Puoi fornire il periodo di tempo solo in multipli di secondi interi.
  • Non c'è modo di sapere quanto tempo rimane su un timer.

Salva il codice di esempio fornito sopra come allarme.c. quando tu compili ed esegui it, il programma chiamerà il timer_richiamata funzione dopo un secondo. Aspetterà quindi i restanti due secondi a causa del dormire (3) riga, quindi termina.

$ gcc -o allarme allarme.c
$ ora ./allarme
Segnale 14 catturato su 1653490465
0m1.004 reali
utente 0m0.000s
sistema 0m0.003s

Il motivo per utilizzare il comando time è di poter vedere gli orari. Ma se guardi il risultato, il tempo di esecuzione totale non è di tre secondi. Ciò è dovuto al SIGALRM segnale da allarme (1) quando il primo secondo è scaduto, mentre il syscall causato dalla funzione sleep (3) è in esecuzione. Quando questo segnale arriva, interrompe la syscall iniziata per dormire (3).

Utilizzo di un timer a intervalli

Il meccanismo del timer di intervallo era disponibile per la prima volta nella versione 4.2 BSD. Fu più tardi standardizzato da POSIX. I suoi principali vantaggi rispetto al tradizionale allarme() metodo timer basato sono:

  • Fornisce una risoluzione di microsecondi.
  • Consente di controllare la misurazione del tempo in modo più dettagliato in tre diverse modalità.
  • È possibile impostarlo una volta e farlo funzionare periodicamente.
  • È possibile scoprire quanto tempo è presente in un dato momento.

I prototipi di funzione utilizzati per le operazioni con timer a intervalli sono i seguenti:

#includere

intsettimer(int quale, cost struct itimerval *newValue, struct itimerval *oldValue);
intgettimer(int quale, struct timerval *valore);

strutturatempo
{
strutturatemporaleitIntervallo;// valore successivo
strutturatemporaleitValore;// valore corrente
};

strutturatemporale
{
lungo tv_sec;
lungo tv_usec;
};

Se desideri impostare un intervallometro, dovrai utilizzare il tempo struttura Dovrai passare un valore usando questa struttura come secondo argomento a settatore funzione.

Ad esempio, un timer intervallo che avviserà la tua applicazione per 1 secondo e poi ogni 300 millisecondi può essere impostato come segue:

strutturatemponuovoTimer;
strutturatempovecchi tempi;

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

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

settimer (ITIMER_REAL, &newTimer, &oldTimer);

Se è attivo un timer di intervallo prima dell'impostazione dei nuovi valori, i suoi valori vengono trasferiti all'indirizzo variabile del tempo tipo dato al terzo parametro della funzione.

È possibile impostare tre diversi tipi di timer con il meccanismo del timer a intervalli. Specificare il tipo di timer nel primo parametro di settimer():

Tipo di timer Segnale Spiegazione
ITIMER_REALE SIGALRM Indipendente dal tempo impiegato dall'applicazione, calcolato sul tempo totale trascorso.
ITIMER_VIRTUALE SIGVTALRM Calcolato nel tempo in cui l'applicazione è in esecuzione solo in modalità utente.
ITIMER_PROF SIGPROF Calcolato sulla somma del tempo trascorso dall'applicazione sia in modalità utente che in modalità sistema.

Puoi vedere da questa tabella che il ITIMER_REALE tipo invia a SIGALRM segnale, proprio come il allarme() funzione.

Utilizzando un timer intervallo e allarme() nella stessa applicazione sarà fonte di confusione. Anche se puoi fare un secondo controllo sul tempo rimanente con gettimer(), non ha senso usarli contemporaneamente.

Ecco un esempio di definizione della funzione di gestione del segnale con il intestazione di debug:

#includere
#includere
#includere
#includere
#includere
#includere
#includere
#includere "./debug.h"

vuototimer_richiamata(int segno)
{
strutturatemporaleadesso;
gettimeofday(&ora, NULLO);
stampa f("Segnale %d intercettato su %li.%03li ", signum, now.tv_sec, now.tv_usec / 1000);
}

intprincipale()
{
non firmatoint restante = 3;

strutturatemponuovo_timer;
strutturatempovecchi tempi;

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;

settimer (ITIMER_REAL, &new_timer, &old_timer);
segnale (SIGALRM, timer_callback);

mentre (sonno (rimanente) != 0)
{
Se (errno == EINTR)
debugf("sonno interrotto da segnale");
altro
errorf("errore di sonno %s", strerror (errno));
}

Restituzione0;
}

Il codice sopra usa il dormire() funzione per attendere tre secondi. Durante questo periodo, viene eseguito un timer di intervallo, prima per un secondo, quindi con un intervallo di 300 millisecondi.

Per una migliore comprensione, salvare e compilare il codice di esempio con il nome intervallo.c:

$ gcc -o intervallo intervallo.c
$ tempo ./intervallo
Segnale 14 catturato su 1653493614.325
debug: sonno interrotto dal segnale (main interval.c: 36)
Segnale 14 catturato su 1653493614.625
debug: sonno interrotto dal segnale (main interval.c: 36)
Segnale 14 catturato su 1653493614.925
debug: sonno interrotto dal segnale (main interval.c: 36)
Segnale 14 catturato su 1653493615.225
debug: sonno interrotto dal segnale (main interval.c: 36)
Segnale 14 catturato su 1653493615.525
...

Come puoi vedere dall'output dopo l'esecuzione del timer, chiama la funzione di callback ogni 300 millisecondi.

Tuttavia, dopo aver atteso un po' di più, noterai che l'applicazione non si chiude. Continua a eseguire la funzione di callback ogni 300 millisecondi. Se aumenti il ​​valore dell'intervallo in millisecondi, vedrai che l'applicazione termina. Ciò è dovuto all'area di utilizzo del dormire() funzione.

Importanza dell'uso dei timer in Linux

Soprattutto per le applicazioni in tempo reale, il meccanismo del timer è di grande importanza. Questa è anche una soluzione utilizzata per l'ottimizzazione delle prestazioni. Puoi persino usarlo per misurare il tempo di attività o la latenza nella tua applicazione. È importante utilizzare i meccanismi del timer per tenere traccia del tempo trascorso e degli eventi di transizione temporale.

Come compilare e installare software dal sorgente in Linux

Leggi Avanti

CondividereTwittaCondividereE-mail

Argomenti correlati

  • Programmazione
  • Programmazione
  • Suggerimenti per Linux

Circa l'autore

Fatih Kuçükkarakurt (10 articoli pubblicati)

Un ingegnere e sviluppatore di software che è un fan della matematica e della tecnologia. Gli sono sempre piaciuti i computer, la matematica e la fisica. Ha sviluppato progetti di motori di gioco, machine learning, reti neurali artificiali e librerie di algebra lineare. Inoltre continua a lavorare su machine learning e matrici lineari.

Altro da Fatih Küçükkarakurt

Iscriviti alla nostra Newsletter

Iscriviti alla nostra newsletter per suggerimenti tecnici, recensioni, ebook gratuiti e offerte esclusive!

Clicca qui per iscriverti