Mécanismes de minuterie avec C et Linux
Obtenez un contrôle précis de vos fonctions de chronométrage en utilisant Linux et C.
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 le temps que le minuteur doit prendre avant de notifier. Deuxièmement, vous devrez préparer une fonction de rappel pour agir lorsque cette notification se produit.
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 dualarme()mécanisme encore en usage.
La fonction d'alarme est la manière la plus simple d'utiliser une minuterie ; voici son prototype :
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 leSIGALRM 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 :
Ce code soulève unSIGALRMsignal après1 deuxième. Si vous souhaitez augmenter le délai de la minuterie à cinq secondes, appelez simplementalarme(5) plutôt. 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 :
Enregistrez l'exemple de code ci-dessus sousalarme.c . Lorsque vous le compilez et l'exécutez, le programme appellera leminuterie_rappel fonction après une seconde. Il attendra ensuite les deux secondes restantes en raison dudormir(3)ligne, puis terminez.
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û à laSIGALRMsignal dealarme(1)lorsque la première seconde est écoulée, tandis que leappel système causé par l'exécution de la fonction sleep(3). Lorsque ce signal arrive, il interrompt l'appel système initié pourdormir (3).
Le mécanisme de minuterie d'intervalle a été disponible pour la première fois dans la version 4.2 BSD. Il a ensuite été standardisé par POSIX. Ses principaux avantages par rapport au traditionnelalarme()méthode basée sur la minuterie sont :
Les prototypes de fonction utilisés pour les opérations de minuterie d'intervalle sont les suivants :
Si vous souhaitez configurer un minuteur d'intervalle, vous devrez utiliser leitimerval structure. Vous devrez transmettre une valeur en utilisant cette structure comme deuxième argument ausemainefonction.
Par exemple, un minuteur d'intervalle qui avertira votre application pendant 1 seconde puis toutes les 300 millisecondes peut être configuré comme suit :
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 duitimervaltype 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 desettimer():
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 leITIMER_REALle type envoie unSIGALRMsignal, tout comme lealarme()fonction.
À l'aide d'un minuteur d'intervalle etalarme() dans la même application sera source de confusion. Bien que vous puissiez effectuer une deuxième vérification du temps restant avecgettimer(), 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 l'en-tête de débogage :
Le code ci-dessus utilise ledormir() 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 nomintervalle.c:
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 dudormir()fonction.
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.
Fatih est chercheur indépendant en sécurité, testeur d'intrusion et analyste de logiciels malveillants. Depuis 2017, il travaille activement avec de nombreux langages et technologies logiciels différents, en particulier C, C++, Python et x86 Assembly. Il a signalé les vulnérabilités de plus de 100 grandes entreprises. Il poursuit ses recherches en tant qu'ingénieur traitant des systèmes d'exploitation et de l'architecture cloud.
alarm() UTILISEZ LA VIDÉO DU JOUR FAITES DÉFILER POUR CONTINUER AVEC LE CONTENU SIGALRM SIGALRM 1 alarm(5) alarm(0) alarm() alarm.c timer_callback sleep(3) SIGALRM alarm(1) syscall sleep(3 alarm() itimerval settimer itimerval setitimer() ITIMER_REAL SIGALRM alarm() alarm() gettimer() sleep() interval.c sleep()