Les mécanismes de minuterie vous permettent de programmer le noyau du système d'exploitation pour notifier une application lorsqu'un temps prédéterminé s'est écoulé. Vous les utiliserez généralement en fournissant deux informations. Tout d'abord, vous devrez spécifier combien de temps le minuteur doit prendre avant de notifier. Deuxièmement, vous devrez préparer une fonction de rappel pour agir lorsque cette notification se produit.

Approche traditionnelle des minuteries

Les mécanismes de minuterie dans les systèmes basés sur Linux et Unix ont évolué pour répondre à divers besoins. Différentes approches peuvent vous aider à résoudre différents types de problèmes. Cependant, vous verrez souvent la première version du alarme() mécanisme encore en usage.

La fonction d'alarme est la manière la plus simple d'utiliser une minuterie; voici son prototype :

non signéentieralarme(non signéentier secondes);

En utilisant cette méthode, vous ne pouvez spécifier le temps qu'en secondes entières. Lorsque le temps est écoulé, le système d'exploitation envoie le

instagram viewer
SIGALRM signal à votre application. Pour traiter l'expiration du temporisateur dans votre application, vous devez également définir une fonction de rappel.

Voici un exemple de fonction de gestionnaire de signal :

#comprendre
#comprendre
#comprendre
#comprendre

annulerminuterie_rappel(entier signe)
{
temps_t maintenant = temps(NUL);
printf("Signal %d intercepté sur %li", signum, maintenant );
}

entierprincipale()
{
signal (SIGALRM, timer_callback);
alarme(1);
dormir(3);
revenir0;
}

Ce code soulève un SIGALRM signal après 1 deuxième. Si vous souhaitez augmenter le délai de la minuterie à cinq secondes, appelez simplement alarme (5) Au lieu. Pour arrêter le timer, passez la valeur 0: alarme (0).

Lorsque le temps est écoulé, la minuterie que vous utilisez ne redémarrera pas périodiquement. Par exemple, si vous souhaitez retarder une autre seconde, vous devez redémarrer le mécanisme avec un autre appel à alarme().

Malgré sa facilité d'utilisation, cette méthode présente quelques inconvénients :

  • Une seule minuterie à la fois.
  • Pas de prise en charge de la minuterie périodique.
  • Vous ne pouvez donner la période de temps qu'en multiples de secondes entières.
  • Aucun moyen de savoir combien de temps il reste sur une minuterie.

Enregistrez l'exemple de code ci-dessus sous alarme.c. Lorsque vous compilez et exécutez celui-ci, le programme appellera le minuterie_rappel fonction après une seconde. Il attendra ensuite les deux secondes restantes en raison du dormir (3) ligne, puis terminez.

$ gcc -o alarme alarme.c
$ temps ./alarme
Signal 14 pris sur 1653490465
réel 0m1.004s
utilisateur 0m0.000s
système 0m0.003s

La raison d'utiliser la commande time est de pouvoir voir les heures. Mais si vous regardez le résultat, le temps de fonctionnement total n'est pas de trois secondes. Cela est dû à la SIGALRM signal de alarme (1) lorsque la première seconde est écoulée, tandis que le appel système causé par la fonction veille (3) est en cours d'exécution. Lorsque ce signal arrive, il interrompt l'appel système initié pour dormir (3).

Utilisation d'un minuteur d'intervalle

Le mécanisme de minuterie d'intervalle a été disponible pour la première fois dans la version 4.2 BSD. C'était plus tard normalisé par POSIX. Ses principaux avantages par rapport au traditionnel alarme() méthode basée sur la minuterie sont :

  • Fournit une résolution en microsecondes.
  • Il permet de contrôler plus en détail la mesure du temps sur trois modes différents.
  • Il est possible de le régler une fois et de le faire fonctionner périodiquement.
  • Il est possible de savoir combien de temps il est présent à un moment donné.

Les prototypes de fonction utilisés pour les opérations de minuterie d'intervalle sont les suivants :

#comprendre

entierminuteur(entier qui, constante struct itimerval *newValue, struct itimerval *oldValue);
entierobtenir(entier lequel, struct itimerval *valeur);

structureitimerval
{
structuretimevalitInterval;// valeur suivante
structuretimevalitValue;// valeur actuelle
};

structuretimeval
{
long tv_sec ;
long tv_usec ;
};

Si vous souhaitez configurer un minuteur d'intervalle, vous devrez utiliser le itimerval structure. Vous devrez transmettre une valeur en utilisant cette structure comme deuxième argument à la Régler la minuterie fonction.

Par exemple, un temporisateur d'intervalle qui avertira votre application pendant 1 seconde puis toutes les 300 millisecondes peut être configuré comme suit :

structureitimervalnouveauTimer;
structureitimervaloldTimer;

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

Si un temporisateur d'intervalle est actif avant que les nouvelles valeurs ne soient définies, ses valeurs sont transférées à l'adresse de variable du itimerval type donné au troisième paramètre de la fonction.

Vous pouvez configurer trois types différents de minuteries avec le mécanisme de minuterie d'intervalle. Spécifiez le type de temporisateur dans le premier paramètre de settimer():

Type de minuterie Signal Explication
ITIMER_REAL SIGALRM Indépendamment du temps passé par l'application, calculé sur le temps total écoulé.
ITIMER_VIRTUAL SIGVTALRM Calculé sur la durée d'exécution de l'application en mode utilisateur uniquement.
ITIMER_PROF SIGPROF Calculé sur la somme du temps passé par l'application en mode utilisateur et système.

Vous pouvez voir sur ce tableau que le ITIMER_REAL le type envoie un SIGALRM signal, tout comme le alarme() fonction.

À l'aide d'un minuteur d'intervalle et alarme() dans la même application sera source de confusion. Bien que vous puissiez effectuer une deuxième vérification du temps restant avec gettimer(), cela n'a pas de sens de les utiliser simultanément.

Voici un exemple de définition de la fonction de gestionnaire de signal avec la en-tête de débogage:

#comprendre
#comprendre
#comprendre
#comprendre
#comprendre
#comprendre
#comprendre
#comprendre "./debug.h"

annulerminuterie_rappel(entier signe)
{
structuretimevalà présent;
gettimeofday(&maintenant, NUL);
printf("Signal %d capté sur %li.%03lje ", signum, now.tv_sec, now.tv_usec / 1000);
}

entierprincipale()
{
non signéentier restant = 3;

structureitimervalnew_timer;
structureitimervalancien;

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, &new_timer, &old_timer);
signal (SIGALRM, timer_callback);

tandis que (dormir (restant) != 0)
{
si (errno == EINTR)
debugf("sommeil interrompu par signal");
autre
errorf("erreur de veille %s", strerror (errno));
}

revenir0;
}

Le code ci-dessus utilise le dormir() fonction d'attendre trois secondes. Pendant ce temps, un temporisateur d'intervalle fonctionne, d'abord pendant une seconde, puis sur un intervalle de 300 millisecondes.

Pour une meilleure compréhension, enregistrez et compilez l'exemple de code avec le nom intervalle.c:

$ gcc -o intervalle intervalle.c
$ temps ./intervalle
Signal 14 pris sur 1653493614.325
débogage: veille interrompue par le signal (intervalle principal.c: 36)
Signal 14 pris sur 1653493614.625
débogage: veille interrompue par le signal (intervalle principal.c: 36)
Signal 14 pris sur 1653493614.925
débogage: veille interrompue par le signal (intervalle principal.c: 36)
Signal 14 pris sur 1653493615.225
débogage: veille interrompue par le signal (intervalle principal.c: 36)
Signal 14 pris sur 1653493615.525
...

Comme vous pouvez le voir sur la sortie après l'exécution du minuteur, il appelle la fonction de rappel toutes les 300 millisecondes.

Cependant, après avoir attendu un peu plus longtemps, vous remarquerez que l'application ne se termine pas. Il continue d'exécuter la fonction de rappel toutes les 300 millisecondes. Si vous augmentez la valeur de l'intervalle en millisecondes, vous verrez que l'application se termine. Ceci est dû à la zone d'utilisation du dormir() fonction.

Importance de l'utilisation des minuteries sous Linux

Surtout pour les applications en temps réel, le mécanisme de minuterie est d'une grande importance. C'est aussi une solution utilisée pour les optimisations de performances. Vous pouvez même l'utiliser pour mesurer la disponibilité ou la latence de votre application. Il est important d'utiliser des mécanismes de minuterie pour suivre le temps écoulé et les événements de transition temporelle.

Comment compiler et installer un logiciel à partir de la source sous Linux

Lire la suite

PartagerTweeterPartagerE-mail

Rubriques connexes

  • Programmation
  • Programmation
  • Conseils Linux

A propos de l'auteur

Fatih Küçükkarakurt (10 articles publiés)

Un ingénieur et développeur de logiciels passionné de mathématiques et de technologie. Il a toujours aimé les ordinateurs, les mathématiques et la physique. Il a développé des projets de moteurs de jeux ainsi que des bibliothèques d'apprentissage automatique, de réseaux de neurones artificiels et d'algèbre linéaire. De plus continue à travailler sur l'apprentissage automatique et les matrices linéaires.

Plus de Fatih Küçükkarakurt

Abonnez-vous à notre newsletter

Rejoignez notre newsletter pour des conseils techniques, des critiques, des ebooks gratuits et des offres exclusives !

Cliquez ici pour vous abonner