
Nous avons examiné le multitâche, la propriété du système d'exploitation d'exécuter plusieurs programmes quasi indépendants en même temps. Avant d'examiner de plus près les tâches, nous devons en traiter les termes.
Articles précédents de la série:
Article # 2. RTOS: Structure et mode temps réel
Article # 1. RTOS: introduction.
Nous utilisons le mot «tâche», bien qu'il n'ait pas de signification exacte. D'autres termes, «flux» et «processus», sont plus spécialisés et vous devez comprendre ce qu'ils signifient et en quoi ils diffèrent.
De nombreux RTOS utilisés dans les applications intégrées utilisent un modèle multithread. Plusieurs threads peuvent être exécutés simultanément, occupant le même espace d'adressage:

Cela signifie que la commutation de contexte consiste, tout d'abord, à passer d'un ensemble de registres de processeur à un autre. C'est simple et rapide. Le danger potentiel est que chaque thread a la capacité d'accéder à la mémoire qui appartient à d'autres threads ou au RTOS lui-même.
Une alternative est le modèle multi-processus. Si plusieurs processus sont en cours d'exécution, chaque processus a son propre espace d'adressage et vous ne pouvez pas accéder à la mémoire associée à d'autres processus ou RTOS:

Cela rend le changement de contexte plus difficile et plus long, car le système d'exploitation doit configurer correctement l'unité de gestion de la mémoire, le gestionnaire de mémoire (English Memory Management Unit, MMU). Bien entendu, une telle architecture n'est possible qu'avec un processeur prenant en charge MMU. Les processus sont pris en charge par RTOS "hautes performances" et la plupart des OS de bureau. De plus, chaque processus peut prendre en charge la division en plusieurs threads, mais cette propriété est rarement utilisée dans les applications embarquées ordinaires.
Si une MMU est disponible, un compromis peut être trouvé:

De nombreux RTOS «en streaming» prennent en charge les MMU pour protéger la mémoire contre les accès non autorisés. Ainsi, alors que la tâche est en contexte, seule une partie de son code / données et les sections nécessaires du RTOS sont «visibles»; les blocs de mémoire restants sont désactivés et une tentative d'accès entraînera une urgence (pour les gens ordinaires) / exception (pour les programmeurs). Cela rend le changement de contexte un peu plus difficile, mais l'application elle-même est plus sécurisée. Ce mode peut être appelé «Mode Thread Protected» ou «Lightweight Process Mode».
Planificateurs
Comme nous le savons, l'illusion de l'exécution simultanée de tâches est obtenue en allouant du temps processeur pour terminer chacune des tâches. Il s'agit de la fonction principale du noyau. La méthode de répartition du temps entre les tâches est appelée «planification». Scheduler - logiciel qui détermine à quelle prochaine tâche transférer le contrôle. La logique de l'ordonnanceur et le mécanisme qui détermine quand et ce qui doit être exécuté est l'algorithme de planification. Dans cette section, nous examinons plusieurs algorithmes de planification. La planification des tâches est un sujet vaste et de nombreux livres y sont consacrés. Nous fournirons le minimum nécessaire pour comprendre ce qu'un RTOS particulier peut offrir à cet égard.
Run to Completion Scheduler (RTC)
Le planificateur RTC (exécution complète) est très simple et consomme un minimum de ressources. Il s'agit d'un service idéal s'il répond aux exigences de l'application. Voici un graphique pour un système utilisant le planificateur RTC:

Le planificateur invoque à tour de rôle les fonctions de niveau supérieur de chaque tâche. La tâche contrôle le processeur (l'interrompt) jusqu'à ce que la fonction de niveau supérieur exécute l'instruction return return. Si le RTOS prend en charge la suspension des tâches, toutes les tâches actuellement suspendues ne sont pas exécutées. Ce sujet est abordé dans l'article ci-dessous, voir «Suspension d'une tâche».
Un grand avantage du planificateur RTC, en plus de la simplicité, est une pile unique et la portabilité du code (l'assemblage n'est pas requis). L'inconvénient est que la tâche peut "prendre" le processeur, donc un développement soigneux du programme est nécessaire. Malgré le fait que chaque fois que la tâche est exécutée depuis le début (contrairement à d'autres planificateurs qui vous permettent de démarrer le travail à partir de l'arrêt), vous pouvez obtenir plus de flexibilité à l'aide de variables "d'état" statiques qui déterminent la logique de chaque appel suivant.
Scheduler Round Robin (RR)
L'ordonnanceur RR ("carrousel") est similaire au RTC, mais plus flexible et donc plus complexe:

Cependant, dans le cas du planificateur RR, la tâche n'a pas besoin d'exécuter l'instruction return dans la fonction de niveau supérieur. Elle peut libérer le processeur à tout moment en effectuant un appel RTOS. Cet appel oblige le noyau à sauvegarder le contexte de la tâche en cours (tous les registres, y compris le pointeur de pile et le pointeur de commande) et à charger le contexte de la tâche suivante dans la file d'attente. Dans certains RTOS, le processeur peut être libéré (mettre la tâche en pause) en prévision de la disponibilité de la ressource du noyau. C'est plus compliqué, mais le principe est le même.
La flexibilité de l'ordonnanceur RR est déterminée par la possibilité de continuer à effectuer des tâches à partir du moment de la suspension, sans apporter de modifications au code d'application. Pour plus de flexibilité, vous devez payer moins de portabilité du code et une pile distincte pour chaque tâche.
Planificateur de tranche de temps (TS)
Scheduler TS (tranche de temps - "tranche de temps") à un niveau plus complexe que RR. Le temps est divisé en tranches (intervalles, tranches de temps), où chaque tâche peut être effectuée dans son intervalle assigné:

En plus de la possibilité de libérer volontairement le processeur, la tâche peut être interrompue par un appel au planificateur exécuté par le gestionnaire d'interruption du temporisateur système. L'idée d'attribuer une période de temps fixe à chaque tâche est très intéressante (si possible): elle est facile à comprendre et très prévisible.
L'inconvénient du planificateur TS est que le pourcentage de temps CPU alloué à chaque tâche peut différer, selon que d'autres tâches sont suspendues et que d'autres parties des emplacements sont libres:

Le planificateur TS peut devenir plus prévisible si des tâches en arrière-plan sont implémentées. La tâche d'arrière-plan peut être effectuée à la place de toute tâche suspendue et prendre l'intervalle de temps lorsque la tâche est libérée (ou s'interrompt).

De toute évidence, la tâche en arrière-plan ne doit pas effectuer de travail critique, car la part du temps processeur qui lui est allouée est absolument imprévisible: elle ne peut jamais être planifiée.
Une telle solution suppose que chaque tâche peut prédire quand elle sera à nouveau planifiée. Par exemple, si vous avez des emplacements pour 10 ms et 10 tâches, la tâche sait que si elle est libérée, elle continuera à s'exécuter après 100 ms. Avec cette solution, vous pouvez obtenir une configuration plus flexible des cycles de temps (temporisations) pour les tâches d'application.
Le RTOS peut fournir différents créneaux horaires pour chaque tâche. Cela offre plus de flexibilité, mais aussi aussi prévisible qu'avec une taille d'intervalle fixe. Une autre option consiste à allouer plus d'un intervalle pour la même tâche, si vous devez augmenter la proportion du temps processeur alloué.
Planificateur de priorités
La plupart des RTOS prennent en charge la planification basée sur les priorités. L'idée est simple: chaque tâche est prioritaire, et à tout moment la tâche qui a la priorité la plus élevée et est «prête» à être exécutée est transférée au processeur:

Le planificateur démarre lorsqu'un événement se produit (par exemple, une interruption ou un appel à un service de noyau spécifique) qui force une tâche avec une priorité élevée à devenir "prête". Il y a trois circonstances dans lesquelles le planificateur commence à fonctionner:
• La tâche est suspendue; le planificateur doit planifier la tâche suivante.
• Une tâche prépare une tâche de priorité plus élevée (à l'aide d'un appel API).
• Un gestionnaire d'interruption (Routine de service d'interruption, ISR) prépare une tâche de priorité plus élevée. Cela peut être un gestionnaire d'interruption pour un périphérique d'E / S ou le résultat d'une minuterie système.
Le nombre de niveaux de priorité varie (de 8 à plusieurs centaines), les valeurs de seuil varient également: certains RTOS perçoivent la priorité la plus élevée comme 0, tandis que dans d'autres 0 signifie la priorité la plus faible.
Certains RTOS n'autorisent qu'une seule tâche à chaque niveau de priorité; d'autres en autorisent quelques-uns, ce qui complique grandement les structures de données associées. De nombreux systèmes d'exploitation vous permettent de modifier les priorités des tâches au moment de l'exécution, ce qui complique encore les processus.
Planificateur composite
Nous avons examiné plusieurs planificateurs, cependant, de nombreux RTOS commerciaux offrent des solutions encore plus sophistiquées qui ont les caractéristiques de plusieurs algorithmes à la fois. Par exemple, un RTOS peut prendre en charge plusieurs tâches à chaque niveau de priorité, puis utiliser TS pour partager le temps entre plusieurs tâches prédéfinies au plus haut niveau.
États des tâches
À un moment donné, une seule tâche est exécutée. En plus du temps du processeur passé sur le gestionnaire d'interruption (plus à ce sujet dans l'article suivant) ou le planificateur, la tâche «en cours» est celle dont le code est en cours d'exécution et dont les données sont caractérisées par les valeurs de registre actuelles. Il peut y avoir d'autres tâches qui sont «prêtes» pour le lancement, et elles seront prises en compte par le planificateur. Dans un simple RTOS utilisant le planificateur RTC, RR ou TS, c'est tout. Mais le plus souvent, et toujours avec un ordonnanceur prioritaire, les tâches peuvent également être dans un état suspendu, ce qui signifie qu'elles ne sont pas prises en compte par l'ordonnanceur jusqu'à ce qu'elles soient reprises et passent dans un état de «préparation».
Suspendre une tâche
La suspension d'une tâche peut être assez simple: la tâche s'arrête d'elle-même (en appelant l'API) ou une autre tâche l'interrompt. Grâce à un autre appel d'API, une tâche suspendue peut être reprise par une autre tâche ou un gestionnaire d'interruption. Il s'agit d'une suspension «inconditionnelle» ou «pure». Certains systèmes d'exploitation appellent cette tâche "en veille".
Le RTOS peut fournir à la tâche la possibilité de faire une pause (s'endormir) pendant une certaine période de temps, après quoi elle reprend (selon l'horloge du système). Cela peut être appelé «s'endormir».
Si le RTOS prend en charge les appels d'API «bloquants», une suspension plus sophistiquée peut être utilisée. Un tel appel permet à la tâche de demander un service ou une ressource qu'il recevra immédiatement s'il est disponible. Sinon, il sera suspendu jusqu'à ce qu'il devienne disponible. Des délais d'expiration peuvent également être définis à partir desquels la tâche reprend si la ressource n'est pas disponible pendant une certaine période.
Autres états de tâche
De nombreux RTOS prennent en charge d'autres États, mais les concepts et définitions varient considérablement. Par exemple, l'état est «terminé», ce qui signifie simplement que la fonction externe de la tâche est sortie (soit en renvoyant le code, soit simplement en complétant le bloc de fonction externe). Pour que la tâche terminée puisse recommencer, elle devra probablement être réinitialisée d'une manière ou d'une autre.
Une autre option est l'état terminé. Ceci est similaire à une suspension complète (pure), sauf que la tâche doit être réinitialisée pour redémarrer.
Si le RTOS prend en charge la création et la suppression dynamiques de tâches (voir l'article suivant), cela implique un autre état possible de la tâche - «supprimé».
Lorsque nous avons travaillé sur notre propre système d'exploitation OSRV MAX en temps réel (articles déjà publiés à ce sujet), notre équipe a « découvert » le blog de Colin Walls, un expert en microélectronique et firmware de Mentor Graphics. Les articles semblaient intéressants, les traduisaient eux-mêmes, mais afin de ne pas "écrire sur la table", ils ont décidé de publier. J'espère qu'ils vous seront également utiles. Si c'est le cas, nous prévoyons de publier tous les articles traduits de la série.
À propos de l'auteur: Colin Walls travaille dans l'industrie électronique depuis plus de trente ans, consacrant la majeure partie de son temps au micrologiciel. Il est maintenant ingénieur firmware chez Mentor Embedded (une division de Mentor Graphics). Colin Walls intervient souvent lors de conférences et séminaires, auteur de nombreux articles techniques et de deux livres sur le firmware. Vit au Royaume-Uni. Blog professionnel de Colin: blogs.mentor.com/colinwalls , e-mail: colin_walls@mentor.comLes premier et deuxième articles du cycle sont affichés
ici.