Maison  >  Article  >  Tutoriel système  >  Introduction pertinente et analyse du cadre de fonctionnement des minuteries de haute précision

Introduction pertinente et analyse du cadre de fonctionnement des minuteries de haute précision

WBOY
WBOYoriginal
2024-07-20 08:36:00373parcourir

Introduction pertinente et analyse du cadre de fonctionnement des minuteries de haute précision

La mention soudaine de minuteries de haute précision me laisse perplexe. Au moins, les débutants seront frustrés. Et si vous le comprenez littéralement, c'est très simple. Si la minuterie est moins précise, alors il n'y en aura plus. Bien que ce soit à peu près tout, cela implique simplement quelques autres détails.

Si un travailleur veut bien faire son travail, il doit d’abord affûter ses outils. Avant de commencer à parler, affûtons d’abord ses outils :

.

2 Plusieurs fichiers de code source associés et leurs chemins sont les suivants :

Hrtimers.txt(linux-3.2.12documentationtimers)

Hrtimer.c(noyau Linux-3.2.12)

Hrtimer.h(linux-3.2.12includelinux)

2 Faites simplement fonctionner la minuterie de haute précision en mode minuterie de haute précision. L'ensemble du cadre de fonctionnement est le suivant :

.

Initialisez hrtimer_init, définissez les données pertinentes via la structure hetimer, telles que la durée de synchronisation, etc.-> Activez la minuterie hrtimer_start-> Exécutez la minuterie de grande précision hrtimer_run_queues-> hrtimer_interrupt-> Supprimer la minuterie de haute précision remove_hrtimer.

Les lecteurs ont désormais un cadre en tête, et les détails spécifiques du pilote seront discutés un par un ci-dessous.

Donnons d'abord un aperçu. Il peut y avoir des choses gênantes qui sont difficiles à comprendre. Cela n'a pas d'importance. Il y aura des codes et des exemples pertinents pour l'expliquer.

 ? Un minuteur de haute précision trie un arbre rouge noir en fonction du temps.

 ? Ils sont indépendants de l'horloge de période minuterie d'application Linux, utilisant des horodatages de largeur d'impulsion au lieu de dimensions temporelles en jiffies.

Prenez d'abord la documentation relative aux timers de haute précision dans le code Linux et jetez un œil à son introduction, je l'expliquerai plus tard, le chemin du document : Hrtimers.txt (linux-3.2.12documentationtimers)

.

Le contenu du document... Pour être honnête, le document est un peu long, mais la maintenance des documents Linux n'est pas très élevée. J'ai trouvé quelques phrases de ce qui précède et les ai traduites, puis je les ai expliquées :

.

 ? Ce patch introduit un nouveau sous-système pour les minuteries de noyau haute résolution. L'expression patch dans cette phrase est un peu intéressante. Cela signifie que les minuteries de haute précision sont installées dans le système en tant que package de correctifs.

 ? Le deuxième point, l'anglais est trop long donc je ne le publierai pas. C'est pourquoi nous devons utiliser une minuterie de haute précision. Puisque chaque système a une minuterie, la précision n'est en fait pas élevée. appelé une minuterie de faible précision. Pour parler franchement, une grande précision est requise.

?Troisième point, une autre caractéristique du minuteur de haute précision est que son cadre est dans le noyau lors de la compilation, et si le minuteur de haute précision n'est pas configuré, un tel minuteur de haute précision est basé sur une exécution de minuteur ordinaire.

?Dernier point, la minuterie de haute précision est implémentée à l'aide de l'algorithme de la mangrove noire, tandis que la minuterie ordinaire est implémentée à l'aide de l'algorithme de round robin temporel.

?De plus, le document explique également de nombreux problèmes tels que la source d'horloge, la structure des données, l'arborescence rouge-noir, etc. Ces problèmes sont abordés séparément ci-dessous.

应用定时器程序-1PLC_linux 应用定时器_应用定时器2

1. Structures de données associées

La structure de données impliquée dans le timer à fréquence d'images élevée, nous la considérons sous les aspects suivants :

A propos de la source : D'où vient cette horloge ? Une structure est définie dans hrtimer.h, le code est le suivant :

structhrtimer_clock_base{

structhrtimer_cpu_base*cpu_base;

intindex; //Attributs utilisés pour distinguer les horloges (il existe deux types au total, qui seront mentionnés ci-dessous)

clockid_tclockid;//L'ID de l'horloge supportée par chaque CPU

structtimerqueue_headactive;//Le nœud de branche noir et rouge du timer en cours d'activation

ktime_tresolution;//Fréquence d'image de l'horloge, millisecondes

ktime_t(*get_time)(void);//Utilisé pour restaurer l'horloge actuelle

ktime_tsoftirq_time;//Le temps d'exécution de la file d'attente de minuterie de grande précision en interruption douce

ktime_toffset ;//Modifier la quantité de décalage de l'horloge de la minuterie

};

Concernant les éléments précédents, merci d'expliquer certaines choses.

La minuterie à fréquence d'images élevée peut être basée sur deux horloges (clockbase) : l'une est une horloge monotone (CLOCK_MONOTONIC), qui démarre à 0 lorsque le système démarre ; l'autre horloge (CLOCK_REALTIME) représente le temps réel du système. Dans la structure structhrtimer_clock_base ci-dessus, l'élément index est utilisé pour distinguer s'il s'agit d'une horloge CLOCK_MONOTONIC ou CLOCK_REALTIME. Pour chaque CPU du système, une structure de données contenant ces deux bases d'horloge est fournie. Chaque base d'horloge totale a un arbre rouge noir pour trier tous les minuteurs de haute précision en attenteminuterie d'application Linux, et chaque CPU fournit deux bases d'horloge (monotones). horloge et temps réel), et tous les minuteurs sont triés sur l'arbre rouge noir par heure d'expiration. Si le minuteur a expiré mais que la fonction de rebond de son gestionnaire n'a pas encore été exécutée, migrez de la mangrove noire vers un tableau. Lors du réglage de l'horloge en temps réel, il y aura une erreur entre la valeur du délai d'expiration de la minuterie stockée dans l'horloge CLOCK_REALTIME et l'heure réelle actuelle. Le tableau de décalage aide à corriger ces situations. Il représente la quantité de décalage dont le minuteur a besoin pour se calibrer. Parce que ce n’est qu’un effet temporaire et qu’il se produit rarement.

Avant de comprendre la source de l'horloge, nous aurons peut-être aussi besoin de connaître une structure structhrtimer, le code est le suivant :

structhrtimer{

structtimerqueue_nodenode;//Le nœud de file d'attente du timer gère également node.expires. Le temps d'expiration absolu du timer de haute précision est dans son algorithme interne. Ce temps est lié à l'horloge sur laquelle le timer est basé (les deux bases de temps mentionnées ci-dessus. ) ).

应用定时器2_linux 应用定时器_应用定时器程序-1PLC

ktime_t_softexpires ;//Le délai d'expiration absolu le plus tôt

enumhrtimer_restart(*)(structhrtimer*);//Fonction de rebond d'expiration du minuteur

structhrtimer_clock_base*base;//Main pointant vers la base de temps (par CPU, par horloge)

unsignedlongstate ;//Informations d'état, utilisées pour voir la valeur du bit

#ifdefCONFIG_TIMER_STATS

intstart_pid; //Le pid de la tâche qui démarre le chronométrage stocké dans la zone des statistiques du minuteur

void*start_site;//La minuterie stocke la valeur de démarrage actuelle de la minuterie

charstart_comm[16];//Le nom de la zone de statistiques du minuteur démarre le processus de stockage du timing

#endif

};

Pour la structure ci-dessus, les utilisateurs ne doivent se soucier que de trois points. Le premier est le tableau, qui est la fonction de rebond après l'expiration du minuteur, le deuxième est l'expiration, qui représente le délai d'expiration. L'utilisation de la structure de minuterie de haute précision doit être initialisée par la fonction hrtimer_init(). La fonction hrtimer_init() appartient au socket d'application, elle est donc mentionnée ci-dessus. Il y a un autre problème ici, qui est également le problème central des minuteries de haute précision, à savoir l'application des mangroves noires dans les minuteries de haute précision. En fait, il est un peu tôt pour en parler maintenant et laisser les lecteurs avoir une idée. idée de base d'abord. Synchronisation traditionnelle de Linux La minuterie est implémentée via l'algorithme de la roue temporelle (timer.c), mais la minuterie hr est implémentée via l'algorithme de la mangrove noire. Il y a un champ de nœud sur structhrtimer, le type est structtimerqueue_node. Ce champ représente la position de hrtimer dans l'arborescence rouge noir. Notez que le code source auquel je fais référence est la version 3.2.12. le champ est structrb_node. Permettez-moi d'abord de saluer les lecteurs. Une telle chose existe. Lorsque nous l'utiliserons en détail, nous parlerons de la manière dont elle est mise en œuvre.

Les deux structures importantes sont terminées. Parce qu'elles doivent être compatibles avec les processeurs multicœurs, elles impliqueront la base de temps de chaque CPU. La structure structhrtimer_cpu_base est utilisée pour définir l'horloge de chaque CPU. Actuellement, chaque CPU correspond uniquement à. Horloge monotone et horloge temps réel, la structure est la suivante :

structhrtimer_cpu_base{//Structure de base de temps CPU unique

raw_spinlock_tlock ;//Base de temps et minuterie liées au verrouillage, verrouillage du transporteur

unsignedlongactive_bases ;//Marquer le tableau de bits de base avec une minuterie active

#ifdefCONFIG_HIGH_RES_TIMERS

ktime_texpires_next;//L'heure absolue de la prochaine fois qui est sur le point d'expirer

inthres_active ; //Statut du mode fréquence d'images élevée, variable booléenne

应用定时器2_linux 应用定时器_应用定时器程序-1PLC

inthang_detected;//La dernière interruption détectée en attente de minuterie de haute précision

unsignedlongnr_events ;//Nombre total d'interruptions de minuterie de haute précision

unsignedlongnr_retries ;//Nombre total de tentatives d'interruption de minuterie de haute précision

unsignedlongnr_hangs ;//Nombre total de blocages d'interruption de minuterie de haute précision

ktime_tmax_hang_time;//Le temps maximum nécessaire au déclenchement de l'interruption de la minuterie de haute précision

#endif

structhrtimer_clock_baseclock_base[HRTIMER_MAX_CLOCK_BASES];//Cette aiguille de base de temps CPU

};

Les trois structures à l'intérieur doivent être les fonctions et les éléments les plus basiques, définissant les minuteries de haute précision, et chaque processeur dispose d'un ensemble complet de structures définies, puis initialise les minuteries.

Maintenant que nous avons fini de parler de la structure de base, commençons à parler du socket API.

La première consiste à configurer et initialiser l'API des hrtimers. Lorsque nous avons parlé de structhrtimer au début, nous avons mentionné que pour utiliser structhrtimer, nous devons d'abord l'initialiser. Le code de déclaration de la fonction est le suivant :

.

voidhrtimer_init(structhrtimer*timer,clockid_tclock_id,

enumhrtimer_modemode)//Minuterie d'initialisation de l'horloge donnée

debug_init(timer,clock_id,mode);

__hrtimer_init(timer,clock_id,mode);

La fonction ci-dessus implémente l'initialisation d'une minuterie de haute précision. Voici une explication des éléments pertinents :

/**

*hrtimer_init – Initialiser la minuterie avec l'horloge donnée

应用定时器2_应用定时器程序-1PLC_linux 应用定时器

*@timer : la minuterie qui est sur le point d'être initialisée

*@clock_id : L'horloge qui sera utilisée

*@mode : mode minuterie abs/rel

*/

mode peut utiliser cinq constantes, comme suit :

enumhrtimer_mode{

HRTIMER_MODE_ABS=0x0,/*Le temps est absolu*/

HRTIMER_MODE_REL=0x1,/*Le temps est relatif*/

HRTIMER_MODE_PINNED=0x02,/*Le timer est lié au CPU*/

HRTIMER_MODE_ABS_PINNED=0x02,

HRTIMER_MODE_REL_PINNED=0x03,

};

La fonction hrtimer_init() appelle la fonction __hrtimer_init() Voici le prototype de cette fonction :

staticvoid__hrtimer_init(structhrtimer*timer,clockid_tclock_id,enumhrtimer_modemode)

structhrtimer_cpu_base*cpu_base;

intbase;

memsettimer,0,sizeof(structhrtimer));

cpu_base=&__raw_get_cpu_var(hrtimer_bases);

应用定时器程序-1PLC_应用定时器2_linux 应用定时器

if(clock_id==CLOCK_REALTIME&&mode!=HRTIMER_MODE_ABS)

clock_id=CLOCK_MONOTONIC;

base=hrtimer_clockid_to_base(clock_id);

timer->base=&cpu_base->clock_base[base];

timerqueue_init(&timer->node);

#ifdefCONFIG_TIMER_STATS

pemasa->start_site=NULL;

pemasa->start_pid=-1;

memset(pemasa->start_comm,0,TASK_COMM_LEN);

#endif

Fungsi

__hrtimer_init() memanggil struktur structhrtimer_cpu_base untuk memulakan CPU dan menggunakan fungsi memset() Prototaip adalah seperti berikut:

void*memset(void*s,intc,size_tn)

inti;

char*ss=s;

untuk(i=0;i

ss[i]=c;

kembali;

Fungsi ini mengosongkan kandungan memori dan melengkapkan permulaan, memset(pemasa,0,sizeof(structhrtimer)).

Sila ambil perhatian di sini, ia masih menjadi masalah yang dinyatakan di atas Kod sumber yang saya gunakan ialah 3.2.12, dan kod sumber yang disediakan dalam 2.6.X hanya mempunyai dua pemalar

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn