Partager via


Utiliser un minuteur système en tant qu’agent de surveillance

Une application de haut niveau peut utiliser un minuteur système en tant qu’agent de surveillance pour provoquer l’arrêt et le redémarrage du système d’exploitation s’il ne répond plus. Lorsque l’agent de surveillance expire, il déclenche un signal que l’application ne gère pas, ce qui entraîne l’arrêt de l’application par le système d’exploitation. Après l’arrêt, le système d’exploitation redémarre automatiquement l’application.

Pour utiliser un minuteur de surveillance :

  • Définir le minuteur
  • Créer et armer le minuteur
  • Réinitialisez régulièrement le minuteur avant son expiration

Pour définir le minuteur, créez une structure itimerspec et définissez l’intervalle et l’expiration initiale sur une valeur fixe, par exemple une seconde.

#include <time.h>

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

Définissez un événement de notification, un signal et une valeur de signal pour l’agent de surveillance, appelez timer_create pour le créer et appelez timer_settime pour l’armer. Dans cet exemple, watchdogTimer déclenche l’événement SIGALRM. Comme l’application ne gère pas l’événement, le système d’exploitation met fin à l’application.

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

Ailleurs dans le code de l’application, réinitialisez régulièrement l’agent de surveillance. Une technique consiste à utiliser un deuxième minuteur, dont la période est inférieure à , watchdogIntervalpour vérifier que l’application fonctionne comme prévu et, si c’est le cas, réinitialiser le minuteur de surveillance.

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