Ordonnancement

Transcription

Ordonnancement
Ordonnancement
1- Notions liées à l'ordonnancement de processus
1.1- Qu'est-ce que l'ordonnancement de processus ?
La figure 1 schématise le fonctionnement d'une machine multiprocessus. Plusieurs processus
sont présents en mémoire centrale. P1 est élu et s'exécute sur le processeur. P2 et P4 sont dans
l'état bloqué car ils attentent tous les deux une fin d'entrée/sortie avec le disque. Les processus
P3, P5 et P6 quant à eux sont dans l'état prêt : ils pourraient s'exécuter (ils ont à leur
disposition toutes les ressources nécessaires) mais ils ne le peuvent pas car le processeur est
occupé par P1. Lorsque P1 quittera le processeur parce qu'il a terminé son exécution, les trois
processus P3, P5 et P6 auront tous les trois le droit d'obtenir le processeur. Mais le processeur
ne peut être alloué qu'à un seul processus à la fois : il faudra donc choisir entre P3, P5 et P6 :
c'est le rôle de l'ordonnancement qui élira un des trois processus.
Système multiprocessus
Mémoire Centrale
P1
elu
P2
attente E/S
P3
attente cpu
P4
attente E/S
P51
attente cpu
P6
attente cpu
P4
P2
Processeur
UE
P1
Bus
Fig 1 : qu'est-ce l'ordonnancement ?
1.2- Définition de l’ordonnancement
La fonction d'ordonnancement gère le partage du processeur entre les différents processus en
attente pour s'exécuter, c'est-à-dire entre les différents processus qui sont dans l'état prêt.
L'opération d'élection consiste à allouer le processeur à un processus.
1.3- Ordonnancement préemptif ou non préemptif
La figure 2 reprend le graphe d'états tel qu'il a été vu à la leçon précédente concernant les
processus. Une transition a été cependant ajoutée entre l'état élu et l'état prêt : c'est la
transition de préemption. La préemption correspond à une opération de réquisition du
processeur, c'est-à-dire que le processeur est retiré au processus élu alors que celui-ci dispose
de toutes les ressources nécessaires à la poursuite de son exécution. Cette réquisition porte le
nom de préemption.
Système multiprocessus
Etats des processus
Fin
Election
Réveil
Elu
En exécution
Prêt
En attente
du processeur
Préemption
(réquisition)
Blocage
Déblocage
Bloqué
En attente de ressources
Fig 2 : Ordonnancement préemptif
1.3.1- Définition de la préemption.
Selon si l'opération de réquisition du processeur est autorisée ou non, l'ordonnancement sera
qualifié d'ordonnancement préemptif ou non préemptif :
- si l'ordonnancement est non préemptif, la transition de l'état élu vers l'état prêt est
interdite : un processus quitte le processeur si il a terminé son exécution ou si il se
bloque.
- si l'ordonnancement est préemptif, la transition de l'état élu vers l'état prêt est
autorisée : un processus quitte le processeur si il a terminé son exécution , si il se
bloque ou si le processeur est réquisitionné.
2- Les entités système responsables de la fonction d'ordonnancement
Le système d'ordonnancement gère une file des processus (bloc de contrôle) prêts et une file
des processus bloqués. La file des processus prêts est classée selon une politique
d'ordonnancement qui assure que le processus en tête de file est le prochain processus à élire
au regard de la politique mise en oeuvre. Ce classement est effectué par l'ordonnanceur et
est réactualisé à chaque fois qu'un processus est préempté ou qu'un processus est débloqué
(ajout d'un nouvel élément prêt).
C'est le répartiteur qui élit le processus en tête de file, c'est-à-dire qui lui alloue un processeur
libre. La figure montre le cas d'un système multiprocesseur ; le répartiteur doit alors choisir
quel processeur allouer. Dans un système monoprocesseur, cette question ne se pose
évidemment pas et souvent alors, ordonnanceur et répartiteur sont confondus. Une fois élu par
le répartiteur, le processus s'exécute. S'il quitte le processeur, sur préemption, il réintègre la
file des processus prêts ; au contraire, s'il quitte le processeur sur un blocage, il intègre la file
des processus bloqués. Dans les deux cas, un nouveau processus est élu (la tête de file des
processus prêts).
Plus précisément, la file d'attente des processus bloqués est souvent organisée en files
multinivaux, chaque niveau correspondant à une attente d'un événement/ressource particulier
auquel peut être éventuellement associé une priorité. Dans le cas où des événements se
produisent simultanément, cette priorité sert alors à déterminer quel événement doit être traité
en premier.
Système multiprocessus
Ordonnanceur et répartiteur
Préemption
Cpu
Ordonnanceur
Répartiteur
Prêts
Classement selon une
Cpu
Politique d'ordonnancement
Blocage
Déblocage
PCB
PCB
PCB
PCB
PCB
PCB
Cpu
PCB
PCB
PCB
PCB
PCB
PCB
Election
Bloqués
Fig 3 : Ordonnanceur et répartiteur
2.1- Ordonnanceur
L'ordonnanceur est un programme système dont le rôle est d'allouer le processeur à un
processus prêt.
3- Les politiques d'ordonnancement
3.1- Définition : Politique d'ordonnancement
La politique d'ordonnancement détermine le choix d'un processus à élire parmi tous ceux qui
sont prêts.
3.2- Objectifs des politiques d'ordonnancement
Les buts de l'ordonnancement diffèrent en fonction du type de systèmes.
- Systèmes de traitements par lots. Le but est de maximiser le débit du processeur ;
c'est-à-dire le nombre moyen de processus traités par unité de temps.
- Systèmes interactifs. Les buts principaux de l'ordonnancement sont premièrement
de maximiser le taux d’occupation du processeur, c’est-à-dire le rapport entre le
temps où le processeur est actif et le temps total. En théorie, ce taux peut varier
entre 0% et 100 % ; dans la pratique, on peut observer un taux d’occupation
variant entre 40 % et 95 %. Deuxièmement, on va chercher à minimiser le temps
de réponse des processus, c’est-à-dire la durée séparant l’instant de soumission du
processus au système de la fin d’exécution du processus. Au mieux, le temps de
réponse peut être exactement égal au temps d’exécution du processus, lorsque le
processus a immédiatement été élu et s’est exécuté sans être préempté.
- Systèmes temps réel. Le but principal est d'assurer le respect des contraintes de
temps liées aux processus.
3.3- Les principales politiques d'ordonnancement
Nous décrivons ci-dessous les politiques mises en oeuvre dans des systèmes interactifs ou à
traitements par lots. Les politiques spécifiques aux systèmes temps réel sont abordées dans la
leçon suivante.
3.3.1- Politique d’ordonnancement “premier arrivé, premier servi” (FIFO).
C’est une politique à l’ancienneté, sans réquisition ; l’unité centrale est allouée selon l’ordre
de soumission des processus. Dans cette politique, des processus de faible temps d’exécution
peuvent être pénalisés parce qu’un processus de longue durée les précède dans la file.
Algorithme : Premier Arrivé Premier Servi
• FIFO, sans réquisition
Prêt
P1
24
Prêt
P2
P3
3
3
Actif
Bloqué
Temps de cycle
P3
Temps moyen d'attente
P2
17 millisecondes
(0 + 24 + 27)/3
P1
24
27
30
Fig 4 : Politique "Premier Arrivé, Premier Servi"
3.3.2- Politique d’ordonnancement “plus court d’abord”
Cette politique tente de remédier à l’inconvénient mentionné pour la politique précédente.
Maintenant, l’unité centrale est allouée au processus de plus petit temps d’exécution. Cette
politique est également une politique sans réquisition. Elle a la propriété de minimiser le
temps de réponse moyen pour l’ensemble des algorithmes d’ordonnancement sans réquisition.
Elle pénalise les travaux longs. Elle impose également d’estimer la durée des processus ce
qu’on ne connaît pas habituellement.
Il existe une version avec réquisition de cette politique appelée “temps restant le plus court
d’abord” : dans ce cas, le processus en exécution restitue le processeur lorsqu’un nouveau
processus de temps d’exécution inférieur à son temps d’exécution restant devient prêt.
3.3.3- Politique d’ordonnancement par tourniquet (Round Robin)
On définit une tranche de temps appelée quantum qui peut varier de 10 ms à 100 ms. Chaque
processus présent dans la file des processus prêts acquiert le processeur à tour de rôle, et ce
pour au maximum un temps égal au quantum de temps. Si le processus a terminé son
exécution avant la fin du quantum, il libère le processeur et le processus suivant dans la file
des processus prêts est élu. Si le processus n’a pas terminé son exécution avant la fin du
quantum, il perd le processeur et est réinséré en fin de file des processus prêts. Cette politique
du tourniquet est usuellement utilisée dans les systèmes en temps partagé. Sa performance
dépend largement de la taille du quantum. Un quantum trop grand augmente les temps de
réponse alors qu’un quantum trop petit multiplie les commutations de contexte jusqu’à les
rendre non négligeables.
Algorithme : tourniquet
Prêt
P1
20
P2
P3
7
3
Quantum = 4
Temps de cycle
P3
P2
P1
4
8
11
15
18
22
26
30
Fig 6 : Politique par tourniquet
3.3.4- Politique d’ordonnancement par priorités constantes
Un niveau de priorité constant est affecté à chaque processus et à un instant donné, le
processus élu est toujours celui de plus forte priorité. Cet algorithme présente une version sans
réquisition et une version avec réquisition. Le défaut de cette politique est le risque de famine
$popbw (compl_famine)
encouru par le processus de faible priorité. Une solution à ce problème est de faire “vieillir” la
priorité des processus en attente, c’est-à-dire d’augmenter celle-ci en fonction du temps
d’attente. La priorité des processus devient ainsi variable.
$popd (compl_famine)
La famine est la situation où un processus ne peut disposer d'une ressource qu'il demande (ici
le processeur)
Algorithme : avec priorités
Prêt
3
1
3
2
prio
10
1
2
5
P1
P2
P3
Tps exec
P4
P4
P3
Temps moyen d'attente
P2
8,2 millisecondes
P1
Fig 7 : Politique par priorités constantes
3.3.5- Politique d’ordonnancement par files de priorités constantes multiniveaux avec ou sans
extinction de priorité
Les politiques présentées jusqu’à présent utilisent une seule file d’attente des processus prêts.
On choisit ici de définir plusieurs files de processus prêts, chaque file correspondant à un
niveau de priorité ; on peut alors avoir n files de priorités différentes variant de 0 à n-1. Dans
une file donnée, tous les processus ont la même priorité et sont servis soit selon une politique
à l’ancienneté sans préemption, soit selon une politique de tourniquet. Le quantum peut être
différent selon le niveau de priorité de la file. L’ordonnanceur sert d’abord tous les processus
de la file de priorité n, puis ceux de priorité n-1 dès que la file de niveau n est vide et ainsi de
suite...
On peut définir deux variantes de l’algorithme, fonction de l’évolution de la priorité des
processus :
• les priorités des processus sont constantes tout au long de leur exécution. A ce
moment-là, un processus en fin de quantum est toujours réinséré dans la même file
d’attente, celle correspondant à son niveau de priorité.
• les priorités des processus évoluent dynamiquement en fonction du temps de
service dont a bénéficié le processus. Ainsi un processus de priorité n, à la fin du
quantum de la file n, si il n’a pas terminé son exécution, n’est pas réinséré dans la
file de priorité n, mais dans la file de priorité n-1. Et ainsi de suite... On cherche ici
à minimiser les risques de famine pour les processus de faible priorité en faisant
petit à petit baisser la priorité des processus de plus forte priorité.
Algorithme : multifiles sans extinction
Prêt
Prêt
Arrivée
F1
q1
F2
q2
Priorité
Arrivée
F1
q1
F2
q2
Election
Election
F3
q3
Fn
qn
F3
q3
Fn
FIFO
--
Fig 8 : Politique par priorités multiniveaux avec ou sans extinction de priorité
3.3.6- Les politiques d'ordonnancement sous le système Linux
Il existe trois politiques (classes) d’ordonnancement dans Linux qui correspondent aux
politiques définies dans la norme pour les systèmes d'exploitation ouverts, POSIX.: deux sont
dites temps réel, SCHED_FIFO et SCHED_RR, la troisième est classique SCHED_OTHER.
On peut attribuer un processus à l’une de ces trois classes grâce à l’appel système :
sched_setscheduler().
Comme dans les systèmes Unix, la politique d’ordonnancement SCHED_OTHER de Linux a
plusieurs objectifs : avoir de bons temps de réponses, assurer une bonne capacité de traitement
et essayer de répartir équitablement le temps CPU entre les différents processus. Elle
correspond à ce qu’on appelle la politique « en temps partagé ».
Chaque processus Linux a une priorité variable qui dépend de nombreux facteurs parmi
lesquels nous pouvons citer le taux d’utilisation de la CPU et l’intensité des entrées / sorties.
$p
Il existe deux autres classes d’ordonnancement dites temps réel : SCHED_FIFO et
SCHED_RR.Les rubriques « policy » et « rt_priority » stockées dans la structure des
processus Linux permettent de leur attribuer une classe d’ordonnancement et une priorité
temps réel. SCHED_FIFO et SCHED_RR ne sont pas des classes temps réel strictes, mais
relatives. Quand un processus temps réel est prêt, tous les processus de priorité inférieure sont
mis de côté.
Un processus de la classe SCHED_FIFO peut s’exécuter jusqu’à la fin de son traitement ou
jusqu’à ce qu’un processus de la classe SCHED_FIFO de priorité temps réel plus forte soit
prêt.
Un processus de la classe SCHED_RR est interrompu à la fin de son quantum de temps ou
dès qu’un processus de priorité temps réel (SCHED_FIFO ou SCHED_RR) supérieure est
prêt. Il existe dans cette classe un principe de tourniquet parmi les processus de même
priorité.
4- Ordonnancement sous le système Unix
Les opérations relatives à l'ordonnancement sont réalisées par le système Unix à chaque fois
qu'un processus s'apprête à passer du mode système au mode utilisateur, donc à la suite de
l'occurrence soit d'une interruption, d'un appel système ou d'une trappe.
La politique d'ordonnancement du système Unix est une politique à multiples niveaux de
priorité avec quantum de temps. Le noyau recalcule la priorité d'un processus quand il passe
du mode noyau au mode utilisateur. Dans une première approche, ce calcul permet une
extinction de priorité des processus qui s'exécutent de manière à permettre l'exécution de tous
les processus et à éviter les problèmes de famine
4.1- Structures de données liées à l'ordonnancement
La priorité de chaque processus est codée dans l'entrée de la table des processus qui lui
correspond. La plage des priorités des processus est partitionnée en deux sous-ensembles.
Chaque ensemble contient plusieurs niveaux de priorités et à chaque niveau de priorité est
associé une file d'attente (fig 9) :
Ordonnancement dans le système Unix
Priorités
du
mode noyau
(sleep)
Non interruptible
Interruptible
Swapper
Attente E/S disque
Attente tampon
Attente sortie tty
Attente entrée tty
Attente exit du fils
Priorités
du
mode user
(préempté)
Niveau utilisateur 0
Niveau utilisateur 1
Niveau utilisateur n
Fig 9 : Files de priorités pour l’ordonnancement sous Unix
-
les priorités utilisateurs : ce sont les processus préemptés par l'ordonnanceur au
moment de leur retour en mode utilisateur. Un processus qui se réveille quitte la
priorité noyau pour réintégrer les priorités utilisateur. La procédure de traitement
de l'interruption horloge ajuste les priorités des processus en mode utilisateur
toutes les secondes et fait entrer le noyau dans son algorithme d'ordonnancement
pour éviter qu'un processus monopolise l'unité centrale
-
les priorités noyau : ce sont des processus endormis en attente d'un événement. La
file où le processus s'endort est fonction de l'événement attendu et la priorité
correspond à une "préférence" sur les réveils suite à un événement. Un processus
endormi en priorité noyau demeure toujours dans la file où il s'est endormi
4.2- Algorithmes d'ordonnancement mis en oeuvre
L’algorithme mis en œuvre s’appuie sur la routine d’interruption horloge qui fait
régulièrement passer le processus en mode noyau. Plus précisément :
- A chaque interruption horloge, le système incrémente de une unité la valeur du
champ "utilisation du processeur" pour le processus élu.
- Toutes les secondes c'est-à-dire toutes les 50 à 100 interruptions horloge, la valeur
du champ "utilisation du processeur" pour tous les processus est divisée par deux.
Puis la priorité des processus est recalculée selon la formule suivante :
priorité du processus = Utilisation du processeur /2 + (priorité de base du
niveau utilisateur)
Du fait de ce recalcul des priorités; les processus se déplacent dans les files de priorité
4.3- Un exemple de mise en œuvre
On considère trois processus A, B et C qui ont chacun une priorité initiale de 60. La priorité
de base du niveau utilisateur est également la priorité 60. L'interruption horloge se déclenche
60 fois par seconde.
A l'instant 0, le processus A est élu. Chaque seconde, l'interruption horloge survient et le
champ "utilisation du processeur " (compte UC sur la figure 10) est incrémenté de une unité.
Au bout de 60 secondes (instant t = 1), la priorité des processus est recalculée. Du fait que les
processus B et C ne se sont pas encore exécutés leur priorité est inchangée (le compte UC est
nul pour ces processus). La priorité du processus A par contre baisse et devient égale à 75 (60
+ 30/2). C'est donc le processus B qui est à présent élu.
A l'instant 2, de nouveau les priorités sont recalculées. Le compte UC du processus C étant
toujours nul , la priorité de ce processus n'est pas modifiée. Les priorités du processus A et B
par contre évoluent et deviennent respectivement égales à 67 pour le processus A (60 + 15/2)
et à 75 pour le processus B. On voit à présent que le processus A a une priorité qui remonte du
fait qu'il n'a pas pu utiliser l'unité centrale.
Proc A
Priorité
0
A
Proc B
Compte UC
60
0
1
Priorité
Proc C
Compte UC Priorité
Compte UC
60
0
60
0
60
0
1
60
0
60
0
1
60
1
B
75
(60+30/2)
30
(60/2)
60
2
67
(60 + 15/2)
C
15
(30/2)
75
30
60
3
A
4
B
63
(60 +7/2)
7 (15/2)
8
67
76
33
(60 + 33/2) (67/2)
67
63
15
7
8
75
67
30
15
67
5
Fig 10 : Exemple de mise en œuvre de l’ordonnancement sous Unix
5- Ordonnancement temps réel
5.1- Caractéristiques de l'ordonnancement temps réel
Dans un système temps réel, le but principal de l'ordonnancement est de permettre le respect
des contraintes temporelles associées à l'application et aux tâches. Chaque tâche possède un
délai critique qui est le temps maximal dont elle dispose pour s'exécuter depuis sa date de
réveil. La date butoir résultante est appelée échéance. Le dépassement d'une échéance est
appelé faute temporelle. Beaucoup d'applications temps réel sont des applications
embarquées et critiques et il est nécessaire de certifier l'ordonnancement réalisé, c'est-à-dire
de vérifier avant le lancement de l'application (hors ligne) le respect des contraintes
temporelles. Cette certification s'effectue à l'aide de tests d'acceptabilité qui prennent en
compte les paramètres temporels des tâches et notamment les temps d'exécutions des tâches.
Il faut donc pouvoir connaître ces temps d'exécutions et surtout pouvoir les borner. Pour cela
l'exécutif doit être déterministe. Les tests d'acceptabilité sont rarement des conditions
nécessaires et suffisantes. On établit donc soit des conditions nécessaires, soit des conditions
suffisantes. Les tests d'acceptabilité utilisent les temps d'exécution maximum des tâches pour
pouvoir certifier les exécutions. Il faut donc être capable de calculer ces temps d'exécutions
maximums. Pour cela, le support d'exécution, l'exécutif temps réel, doit être déterministe.
Un exécutif temps réel déterministe est un exécutif pour lequel les temps de certaines
opérations système et matérielles élémentaires peuvent être bornés : temps de commutation,
temps de prise en compte des interruptions, etc…
5.2- Les algorithmes d'ordonnancement temps réel
5.2.1- Classification des algorithmes d'ordonnancement temps réel
L'ordonnancement peut être en ligne ou hors ligne. Un ordonnancement hors ligne établit
avant le lancement de l'application une séquence fixe d'exécution des tâches à partir de tous
les paramètres de celles-ci. Cette séquence est rangée dans une table et exécutée en ligne par
un automate. Avec un ordonnancement en ligne, la séquence d'exécution des tâches est établie
dynamiquement par l'ordonnanceur au cours de la vie de l'application en fonction des
événements qui surviennent (réveils des tâches, blocage, etc…). Dans ce dernier cas,
l'ordonnanceur choisit le prochaine tâche à élire en fonction d'un critère de priorité.
5.3- Modélisation de l'application temps réel pour la certification
On distingue deux types de tâches pour la modélisation de l'application :
- les tâches périodiques : Elles correspondent aux mesures sur le procédé ; elles se
réveillent régulièrement (toutes les P unités de temps)
- les tâches apériodiques : Elles correspondent aux événements ; elles se réveillent
de manière aléatoire
5.3.1- Les tâches périodiques
On distingue :
- périodiques strictes : contraintes temporelles dures à respecter absolument
- périodiques relatives : contraintes temporelles molles qui peuvent être non
respectées de temps à autre (sans échéance)
- périodiques à échéance sur requête (délai critique = période)
Une tâche périodique Tp (r0, C, R, P) est caractérisée par les paramètres temporels suivants
avec 0 <= C <= R <= P :
- r0, sa date de premier réveil
- P, sa période
- rk, la date de réveil de la kème requête, rk = r0 + kP
- C, son temps d'exécution maximum
- R, son délai critique et dk, sa date d'échéance qui est telle que échéance d = rk + R
- C(t) : le temps d'exécution restant à t
- R(t) : le délai critique dynamique c'est-à dire le temps restant à t jusqu'à d.
Une tâche périodique relative n'a pas de paramètre R défini.
Une tâche périodique à échéance sur requête est une tâche pour laquelle R = P.
Modèle de tâches Périodique stricte
Tp (r0, C, R, P)
0£C£R£P
Tp (t, C(t), R(t))
R = P, à échéance sur requête
dk = r k+1
R
• r0, date de premier réveil
• P, période
• rk, date de réveil de la kème requête
rk = r0 + kP
• C, temps d'exécution
• R, délai critique
• dk, échéance = rk + R
• C(t) : temps d'exécution restant à t
• R(t) : délai critique dynamique
(temps restant à t jusqu'à d)
kème requête
C max
r0
t
d0
C(t)
r0 + kP
t
R(t)
P
Fig 11 : Modèle de tâche périodique
5.3.2- Les tâches apériodiques
On distingue :
- apériodiques strictes : contraintes temporelles dures à respecter absolument
- apériodiques relatives : contraintes temporelles molles qui peuvent être non
respectées de temps à autre (sans échéance)
Une tâche apériodique Tap (r0, C, R) est caractérisée par les paramètres temporels suivants
avec 0 <= C <= R :
- r, sa date de réveil
- C, son temps d'exécution maximum
- R, son délai critique et dk, sa date d'échéance qui est telle que échéance d = rk + R
- C(t) : le temps d'exécution restant à t
- R(t) : le délai critique dynamique c'est-à dire le temps restant à t jusqu'à d.
Une tâche apériodique relative n'a pas de paramètre R défini.
Modèle de tâches Apériodique stricte
Tap (r, C, R)
Tap (t, C(t), R(t))
R
• r, date aléatoire de réveil
• C, temps d'exécution
• R, délai critique
• dk, échéance = rk + R
• C(t) : temps d'exécution restant à t
• R(t) : délai critique dynamique
(temps restant à t jusqu'à d)
kème requête
C max
r
t
d
r'
t
C(t)
R(t)
Fig 12 : Modèle de tâche apériodique
5.3.3- Ordonnancement en ligne préemptifs pour des tâches périodiques indépendantes.
Nous ordonnançons un ensemble de tâches périodiques (configuration). Les priorités affectées
aux tâches sont soit constantes (évaluées hors ligne et fixes par la suite), soit dynamiques
(elles changent dans la vie de la tâche)
L'ordonnancement d'un ensemble de tâches périodiques est cyclique et la séquence se répète
de manière similaire sur ce que l'on appelle la période d'étude. Pour un ensemble de tâches à
départ simultanée (t = 0), la période d'étude est : [0, PPCM(Pi)]
5.4- L'ordonnancement Rate Monotonic (RM)
Avec cet algorithme, la priorité d’une tâche est fonction de sa période, de telle sorte que la
tâche de plus petite période est la tâche la plus prioritaire. Pour un ensemble de tâches à
échéance sur requête, le test d'acceptabilité d’une configuration de n tâches est (condition
suffisante) donné sur la figure qui suit.
La figure ci-dessous donne un exemple pour trois tâches périodiques à échéance sur requête,
Tp1(r0=0, C=3, P=20), Tp2(r0=0, C=2, P=5) et Tp3(r0=0, C=2, P=10). La tâche
la plus prioritaire est la tâche Tp2 et la tâche la moins prioritaire est la tâche Tp1. La séquence
est décrite sur la période d’étude, soit l’intervalle [0, 20]. Les trois tâches respectent leurs
contraintes temporelles. La condition suffisante est vérifiée ; on a :
3/20 + 2/5 + 2/10 = 0.75 < 0.77
Algorithmes d'ordonnancement pour les tâches périodiques indépendantes
Test d ’acceptabilité
Rate Monotonic
n
Ci
ÂP
i =1
£ n (21/ n - 1)
i
Tp1 (r0 = 0, C = 3,P = 20)Tp2 (r0 = 0, C = 2, P = 5)020020510Réveil Echéance sur requêteTp3 (r0 = 0, C = 2, P=10)15020107122172412149754ttt
Fig 13 : Ordonnancement Rate Monotonic
5.5- Ordonnancement Inverse Deadline (ID)
Avec cet algorithme, la priorité d’une tâche est fonction de son délai critique. La tâche la plus
prioritaire est la tâche de plus petit délai critique. Cet algorithme constitue une généralisation
de l'algorithme Rate Monotonic à des tâches quelconques. Une condition suffisante
d’acceptabilité de tâches est donné sur la figure qui suit :
La figure ci-dessous donne un exemple pour trois tâches périodiques Tp1(r0=0, C=3,
R=7, P=20), Tp2(r0=0, C=2, R=4, P=5) et Tp3(r0=0, C=2, R=9, P=10). La tâche
la plus prioritaire est la tâche Tp2 et la tâche la moins prioritaire est la tâche Tp3. La condition
suffisante n’est pas vérifiée ; en effet on a : 3/7 + 2/4 + 2/9 = 1.14 > 1. Mais le
chronogramme construit sur la période d’étude de la configuration prouve que
l’ordonnancement des trois tâches s’effectue sans faute temporelle.
Algorithmes d'ordonnancement pour les tâches périodiques indépendantes
Test d ’acceptabilité
Inverse Deadline
n
i =1
Tp1(r0 =
0, C = 3, R = 7, P =
20)Tp2(r0 =
0, C = 2, R = 4, P = 5)020020510Réveil Échéance
Ci
ÂR
Tp3(r0 =
£ n (21/ n - 1)
i
0, C = 2, R = 9, P = 10)150201071221741214975291919714ttt
Fig 14 : Ordonnancement Inverse Deadline
5.6- Ordonnancement Earliest Deadline (EDF)
La priorité maximale à l’instant t est accordée à la tâche dont l’échéance est la plus proche.
La priorité des tâches est maintenant dynamique.
La figure ci-dessous donne un exemple pour trois tâches périodiques Tp1(r0=0, C=3,
R=7, P=20), Tp2(r0=1, C=2, R=4, P=5) et T p3(r0=0, C=1, R=8, P=10). À
l’instant t=0, les trois tâches sont réveillées et la tâche pour laquelle l’échéance est la plus
proche est la tâche Tp2, qui donc s’exécute. À l’instant t=2, la tâche Tp2 a terminé son
exécution et c’est maintenant la tâche Tp1 qui est la plus prioritaire. À l’instant t=5, la tâche
Tp1 se termine et la tâche Tp2 se réveille de nouveau. Mais, c’est maintenant la tâche Tp3
pour laquelle la date d’échéance est à t=8 qui est devenue la plus prioritaire. C’est donc elle
qui s’exécute. On voit donc que contrairement à ce qui se passe avec les algorithmes à priorité
fixe où les priorités des tâches sont calculées une fois pour toutes à l’initialisation du système,
ici les priorités des tâches évoluent les unes par rapport aux autres en fonction de leur
urgence. Ainsi, à l’instant t=0, la tâche Tp2 est plus prioritaire que la tâche Tp3, mais le
rapport d’urgence est inversé à l’instant t=5.
Algorithmes d'ordonnancement pour les tâches périodiques indépendantes
Earliest Deadline
Tp1 (r0 = 0, C = 3, R = 7, P = 20)Tp2 (r0 = 0, C = 2, R = 4, P = 5)020020510Réveil Echéance Tp3 (r0 = 0, C = 1, R = 8, P = 10)15020108122174121497528181961356ttt
Fig 15 : Ordonnancement Earliest Deadline
6- Une application temps réel sous RT-Linux
Le système RT-Linux est une extension du système Linux classique vers le temps réel. Il est
constitué par un noyau temps réel Rt-Linux qui partage le processeur avec le noyau de base
Linux et exécute des tâches temps réel.
6.1- Les tâches RT-Linux.
6.1.1- Mise en œuvre.
Les tâches RT-Linux s’exécutent dans l’espace adresse du noyau Linux au même titre que
l’ordonnanceur temps réel. Il existe dans les versions récentes de Linux la possibilité de
charger dynamiquement des modules dans l’espace adresse du noyau et de les « lier » au code
du noyau. On parle de « modules chargeables ». En effet, pour limiter la taille du noyau Linux
et libérer ainsi plus de place mémoire pour l’utilisateur, on évite de compiler le noyau avec
des composants qui ne sont pas nécessaires à tout moment. Ces composants sont par exemple
des gestionnaires de périphériques. Lorsqu’on a besoin d’ajouter ou de supprimer l’un de ces
composants, on n’a plus besoin de recompiler tout le noyau comme cela était le cas
auparavant: le composant est chargé ou déchargé dynamiquement à l’aide d’un module. Il faut
simplement configurer le noyau avant sa compilation pour qu’il accepte de gérer les
modules chargeables:
Ainsi, les tâches RT-Linux sont créées à l’aide d’un « module chargeable ».
Il y a plusieurs avantages à mettre les tâches dans l’espace adresse du noyau:
-
Elles partagent le même espace adresse.
Comme elles sont dans l’espace adresse du noyau, on élimine la charge
occasionnée par tout changement de niveau de protection.
Un avantage plus pratique que performant. Dans l’espace adresse du noyau, il est
permis de faire référence aux objets et aux fonctions par leur nom plutôt que par
leur descripteur. C’est l’édition de lien dynamique des « modules chargeables »
qui résoudra les symboles en adresse.
En conclusion cette solution, qui consiste à mettre les tâches temps réel dans l’espace adresse
du noyau permet d’optimiser les performances de RT-Linux.
En contrepartie, cette solution comporte un risque : Un « Bug » dans une tâche temps réel
peut mettre en danger tout le système. Ce risque est renforcé avec l’utilisation du langage C,
notamment les pointeurs. La seule garantie à ce niveau est la rigueur du programmeur.
Le mode opératoire consiste en général à créer toutes les tâches lors du chargement du module
(fonction init_module()) et à les supprimer uniquement au déchargement (fonction
cleanup_module).
La structure « rt_task_struct » (ou RT_TASK par « typedef struct rt_task_struct
RT_TASK ;») des tâches temps réel dans RT-Linux est la suivante :
-
int *stack ; /* hardcoded */
int uses_fp ;
/* this one is too*/
int magic ;
int state;
Etat de la tâche : RT_TASK_READY,…
int *stack_bottom ;
Pointeur de pile.
int priority ; Politique d’ordonnancement basée sur la priorité seule.
RTIME period; P : Période si la tâche est périodique.
RTIME resume_time;
r : Prochaine heure de réveil .
struct rt_task_struct *next;
Chaînage simple de l’ensemble des tâches créées
dans l’application.
RTL_FPU_CONTEXT fpu_regs ;
Les fonctions de gestion des tâches temps réel dans RT-Linux sont listées ci-dessous. Les
états évoqués sont présentés dans les figures qui suivent.
- int rt_task_init (RT_TASK *task, void (fn)(int data), int data, int stack_size,
int priority) :
Création d’une tâche RT_Linux pointée par « task ». Il y a réservation d’espace
mémoire dans le noyau (kmalloc) à hauteur de stack_size. « fn » est le code
exécuté par la tâche. « data » est le paramètre passé à « fn » au démarrage.
« priority » est la priorité de la tâche dont la valeur peut aller de 1, la plus forte
priorité, à « RT_LOWEST_PRIORITY » (1000000), la plus faible.
- int rt_task_delete (RT_TASK *task) :
Suppression logique d’une tâche : Pas de libération de l’espace mémoire « kfree »
à ce niveau. Son état passe à RT_TASK_ZOMBIE.
- int rtl_delete_zombies (void) :
Suppression réelle de l’ensemble des tâches logiquement supprimées par
« rt_task_delete ». « kfree » est effectué ici.
-
-
-
int rt_task_make_periodic (RT_TASK *task, RTIME start_time, RTIME
period) :
Rend la tâche « *task » périodique avec une période « period » à partir de la
première date de réveil « start_time ».
int rt_task_wait (void) :
Suspension de la tâche périodique jusqu’à sa prochaine date de réveil. Elle met la
tâche qui l’a appelée dans l’état RT_TASK_DELAYED. En général toute tâche
périodique indique par cette fonction qu’elle a terminé son traitement : ce doit
donc être la dernière instruction du code de la tâche. Les tâches apériodiques ne
s’en servent pas car l’état RT_TASK_DELAYED ne leur correspond pas.
int rt_task_wakeup (RT_TASK *task) :
Déclenche la tâche « task », c’est-à-dire la met dans l’état prêt
RT_TASK_READY.
int rt_task_suspend (RT_TASK *task) :
Inactive la tâche « task », c’est-à-dire la met dans l’état RT_TASK_DORMANT.
En général, cette routine est utilisée par les tâches apériodiques à la place de
rt_task_wait pour signaler la fin de leur traitement. Une tâche périodique ou
apériodique peut être suspendue par une autre tâche ou par l’ordonnanceur.
Les figures jointes donnent les graphes d'état des tâches périodiques et apériodiques pour RtLinux
6.1.2- Format d'une application.
La déclaration des tâches périodiques et apériodiques dans RT-Linux se fait à l’aide d’un
module noyau dont nous présentons le squelette ci-dessous :
On suppose que ce module s’appelle RT_PROCESS.C et qu’il va créer deux tâches : T1 et
T2. T1 est une tâche périodique et T2 apériodique.
Le module s’installe dans le noyau par :
insmod RT_PROCESS.O
On le décharge du noyau par :
rmmod RT_PROCESS
$tfig
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <rtl_sched.h >
#include <linux/arch/i386/kernel/irq.h>
#define NTASKS 2
RT_TASK tasks[NTASKS]
$e Fonction 1
/*-- Fonction 1 = traitement de la tâche périodique 1 --*/
Code de la fonction exécutée par la tâche périodique 1; l’affectation de cette fonction à la
tâche 1 est faite par rt_task_init (Cf. plus bas). Toute tâche périodique doit terminer son
traitement par l’appel à la fonction rt_task_wait(). Cette routine met la tâche dans l’état
RT_TASK_DELAYED, réinitialise la prochaine date de réveil et fait appel à l’ordonnanceur
rtl_schedule().
$tfig
void f_tache_1(int par1)
{
rt_task_wait() ;
}
Fonction 2
/*-- Fonction 2 = traitement de la tâche apériodique 2 --*/
Code de la fonction exécutée par la tâche apériodique 2. Toute tâche apériodique doit
terminer son traitement par l’appel à la fonction rt_task_suspend() sur elle-même. Cette
routine met la tâche dans l’état RT_TASK_DORMANT et fait appel à l’ordonnanceur
rtl_schedule().
void f_tache_2(int par2)
{
rt_task_suspend(&(tasks[2])) ;
}
Interruption Tache 2
/*-- Gestionnaire de l’interruption associée à la tâche 2 --*/
La tâche apériodique 2 est associée à un niveau d’interruption dont l’apparition active le
gestionnaire T2_Handler(). L’association entre le numéro d’interruption et le gestionnaire sera
vue plus bas. Ce gestionnaire a au moins pour rôle de réveiller la tâche apériodique concernée.
Cette fonction met la tâche dans l’état RT_TASK_READY et appelle l’ordonnanceur.
int T2_handler()
{
rt_task_wakeup(&(tasks[2])) ;
}
/*-- Ordres lancés à l’installation du module: RT_PROCESS --*/
Lorsqu’un module est chargé sous Linux (>insmmod RT_Process.o), il commence par
effectuer la fonction init_module(). Cette fonction doit donc figurer dans tous les modules
chargeables. Dans RT-Linux, on lui attribue le rôle de l’initialisation des tâches temps réel
(rt_task_init), de l’initialisation des périodes et des dates de réveil pour les tâches périodiques
(rt_task_make_periodic) et de l’association des niveaux d’interruptions aux gestionnaires
associés (request_RTirq).
int init_module(void)
{
rt_task_init(&(tasks[0]), f_tache_1, 0, 3000, 4) ;
rt_task_init(&(tasks[1]), f_tache_2, 1, 3000, 5) ;
rt_task_make_periodic(&(tasks[0]), 5, 10) ;
request_RTirq(2, &T2_handler) ;
return 0 ;
}
/*-- Ordres lancés à la suppression du module: RT_PROCESS --*/
void cleanup_module(void)
Lorsqu’un module est déchargé sous Linux, il exécute systématiquement la fonction
cleanup_module(). Cette fonction doit donc figurer dans tous les modules chargeables. Dans
RT-Linux, on lui attribue le rôle de suppression des tâches temps réel (rt_task_delete) ainsi
que celui de la libération des interruptions (free_Rtirq).
{
rt_task_delete(&(tasks[0])) ;
rt_task_delete(&(tasks[1])) ;
free_Rtirq(2) ;
}
6.1.3- L’ordonnancement.
Dans la version 1.2 de RT-Linux, présentée sur le site officiel du système, trois ordonnanceurs
préemptifs ont déjà été installés :
- Un ordonnanceur « à priorité fixe » : il s’appuie sur le paramètre « priority » défini au
niveau de chacune des tâches. Lorsque plusieurs tâches sont prêtes, celle qui a la priorité
la plus forte (la valeur la plus petite) est élue. Une tâche qui se réveille
(RT_TASK_READY) pourra préempter la tâche active si sa priorité est plus forte.
- Un ordonnanceur « Rate-Monotonic » : nous ne nous y intéresserons pas, compte-tenu
des limites de cette politique vis-à-vis des tâches apériodiques.
- Un ordonnanceur « EDF » (« Earliest Deadline First ») : Il utilise l’urgence comme
critère de sélection de la prochaine tâche à élire.

Documents pareils