Condividi tramite


Usare un timer di sistema come cane da guardia

Un'applicazione di alto livello può utilizzare un timer di sistema come cane da guardia per causare l'interruzione del sistema operativo e riavviare l'applicazione se non risponde. Quando il cane da guardia scade, genera un segnale che l'applicazione non gestisce, il che a sua volta causa il sistema operativo per terminare l'applicazione. Dopo la chiusura, il sistema operativo riavvia automaticamente l'applicazione.

Per usare un timer del cane da guardia:

  • Definire il timer
  • Creare e armare il timer
  • Reimpostare regolarmente il timer prima della scadenza

Per definire il timer, creare una struttura itimerspec e impostare l'intervallo e la scadenza iniziale su un valore fisso, ad esempio un secondo.

#include <time.h>

const struct itimerspec watchdogInterval = { { 1, 0 },{ 1, 0 } };
timer_t watchdogTimer;

Imposta un evento di notifica, un segnale e un valore del segnale per il cane da guardia, chiama timer_create per crearlo e chiama timer_settime per armarlo. In questo esempio watchdogTimer genera l'evento SIGALRM. L'applicazione non gestisce l'evento, quindi il sistema operativo termina l'applicazione.

void SetupWatchdog(void)
{
    struct sigevent alarmEvent;
    alarmEvent.sigev_notify = SIGEV_SIGNAL;
    alarmEvent.sigev_signo = SIGALRM;
    alarmEvent.sigev_value.sival_ptr = &watchdogTimer;

    int result = timer_create(CLOCK_MONOTONIC, &alarmEvent, &watchdogTimer);
    result = timer_settime(watchdogTimer, 0, &watchdogInterval, NULL);
}

Altrove nel codice dell'applicazione, reimposta periodicamente il cane da guardia. Una tecnica consiste nell'usare un secondo timer, che ha un periodo più breve di watchdogInterval, per verificare che l'applicazione funzioni come previsto e, in tal caso, reimpostare il timer del cane da guardia.

// Must be called periodically
void ExtendWatchdogExpiry(void)
{
    //check that application is operating normally
    //if so, reset the watchdog
    timer_settime(watchdogTimer, 0, &watchdogInterval, NULL);
}