Vous êtes sur la page 1sur 165

Conception et Ralisation dun Excutif Temps Rel

Comment Concevoir et Raliser un Noyau Temps Rel ? Mmoire dun projet de fin dtudes. Universit Mouloud MAMMERI de Tizi-Ouzou. Prsent par M. Toufik SARNI. Dirig par Mme Samia Bouzefrane (CNAM Paris) & M. Lounes Djema (UMMTO)

Introduction gnrale

Le secteur industriel (militaire, aronautique, tlcommunications) manifeste, une demande de plus en plus accrue de systmes temps rel complexes et fiables. Ces derniers sefforcent, travers des thories mathmatiques avances, de solutions informatiques plus labores et, de contraintes temporelles rigoureuses, de subvenir aux besoins industriels. Pousss par la curiosit de connatre le fonctionnement de tels systmes et, par leur opportunit, nous essayerons de concevoir et de raliser un excutif temps rel simple, en illustrant et en mettant en relief tout au long de ce mmoire qui accompagnera ce travail, toutes les tapes ncessaires. La philosophie qui sera adopte, se basera, elle aussi sur la simplicit des mcanismes qui seront mis en uvre. Ceci afin de permettre, une meilleure comprhension de principes et politiques utiliss dune part, et dautre part, offrir un noyau, simple modliser, en vue de lui intgrer un certain aspect pdagogique. Justifiant ainsi, le choix de la cration au lieu dune modification ou amlioration dun systme dj existant. Ce mmoire prsente notre travail en deux chapitres, les deux autres, seront consacrs des rappels et prsentation des systmes existants. Le premier chapitre rappelle, les concepts utiliss dans les systmes temps rel. Pour cela, il introduit des dfinitions, et aborde la notion de multitche et les principes qui en dcoulent lis au problme de synchronisation et dordonnancement temps rel. Ce chapitre soulve, les principales diffrences entre les systmes classiques et les systmes temps rel. Le deuxime chapitre complte les concepts prsents au premier chapitre, en dcrivant des plates-formes et des systmes temps rel utiliss dans le milieu industriel, et ce, dune faon gnrale. Il aborde les diffrents lments les caractrisant, tout en rappelant brivement leurs diverses volutions. Les systmes comme RTAI (Linux temps rel), VxWorks (Unix temps rel), et les platesformes CLEOPATRE, BOSSA. Le troisime chapitre prsente, dune faon exhaustive la conception de notre travail. Il se propose alors de donner une vue dtaille de notre systme, et prsente entre autres, les diffrents modules dvelopper pour notre excutif temps rel, en se rfrant durant chaque passe lobjectif de notre travail. Le quatrime chapitre concrtise le prcdent, en saccentuant sur la ralisation, et dfinit nos motivations en matire dimplantations, notamment lenvironnement informatique choisi (architecture matrielle, environnement logiciel et de dveloppement). Comme il est tout aussi question dans ce chapitre, de reprendre quelques fragments de code, les analyser et dclaircir leurs fonctions.

Sommaire

Chapitre 1

Concepts temps rel

1 1 2 2 4 5 5 6 6 8 9 11 12 14 14 15 16 16 16 17

1.1 Historique 1.2 Quest-ce quun systme temps rel ? 1.3 Prsentation gnrale 1.4 Structure dun systme de contrle 1.5 Excutif temps rel 1.5.1 Principes de base du multitche 1.5.1.1 Notion de processus 1.5.1.2 Contexte dun processus 1.5.1.3 Zones mmoires dun processus 1.5.1.4 Les appels au systme 1.5.1.5 Section critique 1.5.1.6 Synchronisation par smaphores binaires 1.5.2 Ordonnancement des tches temps rel 1.5.2.1 Notion de tche temps rel 1.5.2.2 Problmatique 1.5.2.3 Algorithmes dordonnancement 1.5.2.3.1 Preemptif/non premptif 1.5.2.3.2 Hors ligne/en ligne 1.5.2.3.3 Conduit par la priorit 1.5.2.4 Algorithmes dordonnancement priorits fixes sans partage de ressources 1.5.2.4.1 Modlisation dune tche 1.5.2.4.2 Condition ncessaire de validation 1.5.2.4.3 Algorithme Rate Monotonic (RM) 1.5.2.4.4 Algorithme Deadline Monotonic (DM)

17 17 18 19 21 21 22 23 24 24 24 25 25 26 27 27 28 30 31 32 33

1.5.2.5 Ordonnancement des tches apriodiques 1.5.2.5.1 Serveur scrutation 1.5.2.5.2 Serveur ajournable 1.5.2.6 Algorithmes priorits variables sans partage de ressources 1.5.2.6.1 Algorithme Earliest Deadline (ED) 1.5.2.6.2 Algorithme Least Laxity (LL) 1.5.2.7 Problmes lis lexclusion 1.5.2.7.1 Interblocage 1.5.2.7.2 Inversion de priorits 1.5.2.8 Protocoles dallocation de ressources 1.5.2.8.1 Protocole priorit hrite (PPH) 1.5.2.8.2 Protocole priorits plafonds 1.5.2.8.3 Facteur de blocage 1.5.2.8.4 Algorithme RM avec partage de ressources Conclusion Bibliographie

Sommaire

Chapitre 2

Exemples de systmes et plates-formes temps rel

34 35 35 35 36 37 38 39 40 41 43 44 45 46 51 51 51 52 54 55 55 56 57 58 59 59 60 60 61 61 62 62 62 63 63 64 64 64 65 66 68 69

2.1 Real-Time Application Interface(RTAI) 2.1.1 Historique 2.1.2 Linux comme systme temps rel 2.1.3 Prsentation gnrale 2.1.4 Les services RTAI 2.1.4.1 Les schedulers 2.1.4.2 Inter-Process communications (IPCs) 2.1.4.3 FIFOs temps rel 2.1.4.3.1 Le partage de mmoire 2.1.4.3.2 Mailboxes (Boite aux lettres) 2.1.4.3.3 Messages RTAI et RPCs 2.1.5 Les modules sous Linux 2.1.6 Exemple 2.2 VxWorks 2.2.1 Historique 2.2.2 Prsentation gnrale 2.2.3 Caractristiques temps rel 2.2.4 Linterface avec Unix 2.2.5 Lenvironnement de compilation et dexcution 2.2.5.1 Chargeur 2.2.5.2 Compilation croise 2.2.5.3 Le shell VxWorks 2.2.6 API VxWorks 2.2.6.1 Gestion des tches 2.2.6.2 Gestion du temps 2.2.6.3 Les smaphores 2.2.6.4 Manipulation des interruptions 2.2.6.5 Gestion de la mmoire 2.2.6.6 Communication par messages 2.3 CLEOPATRE 2.3.1 Objectifs 2.3.2 Organisation du projet 2.3.3 Dmonstrateur 2.3.4 Perspectives de march 2.4 BOSSA 2.4.1 Objectifs 2.4.2 Les composants BOSSA 2.4.3 Du noyau Linux BOSSA 2.4.4 BOSSA : une hirarchie dordonnanceur Conclusion Bibliographie

Sommaire

Chapitre 3

Conception de lexcutif temps rel

70 71 71 72 73 75 77 79 80 81 82 84 86 87 88 91

3.1 Objectif 3.2 Cadre du travail 3.3 Architecture gnrale du systme 3.4 Module temps rel 3.4.1 Module des tches 3.4.1.1 Entit tche 3.4.1.2 Entit smaphore 3.4.1.3 Files dattentes 3.4.1.4 Pile des tches apriodiques 3.4.1.5 Rsum 3.4.2 Module dordonnancement 3.4.2.1 Ordonnancement des priodiques 3.4.2.2 Ordonnancement des apriodiques 3.4.2.3 Rsum Conclusion

Chapitre 4

Ralisation de lexcutif temps rel

92 93 93 94 95 95 96 96 96 97 97 97 97 99 99 100 101 101 101 102 103 104 104 106

4.1 Choix de larchitecture matrielle 4.2 Langages et environnement de programmation 4.3 Parties de lexcutif 4.4 Ralisation de la partie dmarrage 4.4.1 Le boot 4.4.2 Partie 16-bit (mode rel) 4.4.2.1 Fonctions utilitaires 4.4.2.1.1 Manipulation de chanes de caractres 4.4.2.1.2 Manipulation de donnes en mmoire 4.4.2.1.3 Conversion Dcimale-ASCII 4.4.2.1.4 Conversion Hexadcimale-ASCII 4.4.2.1.5 Rcriture des fonctions vsprintf, printf 4.4.2.1.6 Rcriture de putchr 4.4.2.2 Initialisation machine avec dtct16 4.4.2.2.1 Dtection de la CPU 4.4.2.2.2 Mmoire tendue et conventionnelle 4.4.2.2.3 Dtection des disques 4.4.2.2.4 Sauvegarde dinformations hardware 4.4.2.2.5 Mise en place du basculeur 16-bit 4.4.2.2.6 Chargement de la partie 32-bit 4.4.2.2.7 Activation de la ligne A20 4.4.2.2.8 Initialisation de la table des segments (GDT) 4.4.2.2.9 Passage en mode protg

Sommaire

4.4.3 Partie 32-bit (mode protg) 4.4.3.1 Mise en place du basculeur 32-bit 4.4.3.2 Initialisation de la table des vecteurs dinterruption (IDT) 4.4.3.2.1 Les routines dinterruption 4.4.3.3 Programmation du PIC 8259A

106 107 108 110 110 112 112 115 116 117 117 118 119 120 120 121 121 123 124 125 125 126 126 127 129 130 130 131 132 133 133 134 135 136 137

4.5 Module temps rel 4.5.1 Cration dune tche 4.5.2 Cration dun serveur pour les apriodiques 4.5.3 Test de faisabilit 4.5.4 Cration dun smaphore 4.5.4.1 Ajouter un smaphore dans une file 4.5.4.2 La primitive P(s) et le protocole priorit plafond 4.5.4.3 La primitive V(s) et le protocole priorit plafond 4.5.5 Ordonnancement des tches temps rel 4.5.5.1 Activation de lhorloge temps rel RTC 4.5.5.2 Linterruption dhorloge temps rel 4.5.5.3 Ordonnancement des tches priodiques 4.5.5.3.1 Election dune tche priodique 4.5.5.4 Ordonnancement des apriodiques 4.5.5.4.1 Serveur des apriodiques 4.5.5.4.2 Election dune apriodique 4.5.5.4.3 Signal apriodique 4.5.5.5 Chargement de contexte dune tche priodique 4.5.5.5.1 Premire commutation de contexte 4.5.5.5.2 Commutation de contexte 4.5.5.6 Retour de linterruption dhorloge temps rel

4.6 Interface utilisateur temps rel (API) 4.6.1 Manipulation des tches 4.6.2 Manipulation des smaphores 4.6.3 Manipulation du temps 4.6.3.1 Dterminer le temps dune routine 4.6.4 Routine daffichage temps rel

4.7 Performances obtenues Conclusion Bibliographie Conclusion gnrale Annexes

Chapitre 1

Les concepts temps rel

Ce chapitre introduit des gnralits, dfinitions et, des notions, sur les systmes informatiques temps rel qui serviront de base pour aborder les prochains chapitres. Nous avons jug utile, dintroduire en premier lieu, un historique, travers lequel, nous prsenterons un bref aperu, des dates ou poques, qui ont marqu lvolution des systmes informatiques temps rel.

1.1.

Historique [DP 91]

La premire apparition du terme temps rel tel que nous lentendons aujourdhui, concide peu de choses prs avec lavnement des microprocesseurs et le dveloppement du traitement numrique de linformation, cest--dire bel et bien au dbut des annes 1970. Les puces ont entran lintgration de lordinateur dans lenvironnement industriel : le calculateur industriel tait n. La ralisation dapplications soumises de fortes contraintes temporelles devenait possible, le dlai de rponse exigible variant considrablement en fonction de la dynamique caractristique de chaque processus et des marges de tolrance des paramtres contrls. La mise en place dune hirarchie de systmes en temps rel au moyen de microordinateurs permet dviter les problmes techniques trs complexes que soulverait la mise en uvre dun systme global quivalent sur un ordinateur de taille importante. Il est cependant juste de constater que le dveloppement de ces calculateurs industriels et, dune manire plus gnrale, de linformatique industrielle, ne date que du dbut des annes 1980. Avec lavnement de ce que lon appelle les nouvelles technologies, lobjectif premier est de raliser des traitements de plus en plus complexes le plus rapidement possible. Le terme de temps rel nest certes pas nouveau, il correspond toujours une catgorie bien prcise de traitements critiques dans le temps.

1 Les concepts temps rel

1.2.

Quest-ce quun systme temps rel ?

Pour comprendre lide des systmes temps rel, nous avons prfr entreprendre la dfinition par des exemples [PAL 04], afin de donner quelques milieux concrets, sur lesquels souvrent les systmes temps rel et den comprendre les principes. Pour cela, considrons le cas dun avion de ligne, quip dun pilotage automatique. Lordinateur de bord doit, calculer la trajectoire, en fonction des paramtres extrieurs (position de lavion en hauteur, en latitude et longitude, vitesse) et doit garantir priodiquement, des rsultats fiables, et notamment, un temps de traitement infrieur de loin la seconde. A prsent, considrons la situation suivante dans un aroport. Un passager se rapprochant dun distributeur automatique, afin de se procurer un billet davion, pour un certain vol Tizi-ouzou, Paris partant dans 5 mn. Lutilisateur fournit en entre des informations (le dpart, la destination, la classe ) lordinateur. Celui-ci, aprs avoir accept la requte, lui dite le billet en quelques secondes. Ce systme, est-il un systme temps rel ? . En effet, dans les deux cas, les systmes sont des systmes temps rel, dans la mesure o les traitements des informations doivent, seffectuer dans des dlais bien limits, sous peine de consquences pouvant tre graves. Ces exemples donnent, une ide intuitive quant la dfinition des systmes temps rel ; dans les prochains paragraphes, nous prsenterons dune faon plus formelle, les gnralits et les dfinitions lies aux systmes temps rel.

1.3.

Prsentation gnrale [SB 98]

Les systmes temps rel sont, en gnral, constitus de deux parties: le systme contrl, processus physique qui volue avec le temps, appel aussi procd ou partie oprative, et le systme contrlant appel aussi partie commande qui est un systme informatique qui interagit avec le premier. Le systme contrlant prend rgulirement connaissance de ltat du procd par le biais de capteurs, calcule la prochaine action raliser sur la base des dernires mesures puis applique une consigne au processus command par le biais dactionneurs (voir figure 1.1).

1 Les concepts temps rel

Figure 1.1. Systme temps rel

Un systme est qualifi de temps rel si sa correction ou sa validit ne dpend pas 1 2 uniquement de la justesse des rsultats obtenus mais aussi des instants de production de ces rsultats, car les diffrentes activits dun tel systme doivent ncessairement sexcuter dans des laps de temps limits appel chances. Le respect des contraintes temporelles est un aspect fondamental et spcifique aux systmes temps rel, constituant la caractristique principale qui les distingue des systmes informatiques classiques (non temps rel). Dune manire gnrale, nous distinguons trois types de systmes temps rel: les systmes temps rel contraintes strictes qui sont des systmes pour lesquels le non respect d'une chance ne peut tre tolr (exemple: la commande du moteur dun avion) car cela peut engendrer une catastrophe ; les systmes temps rel contraintes relatives, par opposition, tolrent les dpassements des chances ; les systmes temps rel contraintes mixtes qui comprennent des programmes contraintes strictes et dautres contraintes relatives.

Selon lquipement contrl, les contraintes de temps peuvent tre de divers ordres, de lordre: de la milliseconde: systme radar,... de la seconde: systme de visualisation,... de quelques minutes : chane de fabrication,... de lheure: raction chimique,... 1 et 2 : Dans la littrature, le terme dterminisme est utilis pour exprimer ces deux notions.

1 Les concepts temps rel

1.4.

Structure dun systme de contrle [SB 98]

Le systme de contrle consiste en une structure matrielle munie dun ensemble de logiciels permettant dagir sur le systme contrl. La structure matrielle correspond lensemble des ressources physiques (processeurs, cartes dentre/sortie, ...) ncessaires au bon fonctionnement du systme. L'architecture matrielle peut tre: monoprocesseur: tous les programmes s'excutent sur un seul processeur en paralllisme apparent, multiprocesseur: les programmes sont rpartis sur plusieurs processeurs partageant une mmoire commune, rparti: les programmes sont rpartis sur plusieurs processeurs dpourvus de mmoire commune et d'horloge commune. Ils sont relis par un mdium de communication par lequel ils peuvent communiquer par change de messages.

La partie logicielle du systme de contrle comprend : dune part, un systme dexploitation appel excutif temps rel charg de fournir un ensemble de services (voir figure 1.2) que les programmes de lapplication peuvent utiliser durant leur excution. Il doit en particulier : * adopter une stratgie pour partager le temps processeur (notamment dans un systme multitches) entre les diffrentes activits en attente dexcution en favorisant celles qui ont les dlais critiques les plus proches ; * grer laccs aux ressources partages ; * et offrir des mcanismes de synchronisation et de communication entre les activits du systme de contrle. dautre part, afin de garantir un fonctionnement correct du procd, des programmes sont implants par lutilisateur et traduisent les fonctions que doit raliser le systme de contrle pour la prise en compte de ltat du procd et sa commande. Ces programmes se prsentent sous la forme dun ensemble dunits dexcution appeles tches.

1 Les concepts temps rel

Figure 1.2. Structure dun noyau temps rel

1.5.

Excutif temps rel

Un excutif temps rel est en dfinitive, un noyau temps rel, pour lequel un certain nombre de services est ajout (gestionnaire mmoire, gestionnaire dentres/sorties,) et respectant des principes fondamentales, dont nous avons prcdemment prsent les grandes lignes, et nous essayerons dy apporter des dtails dans les prochains paragraphes qui suivront. Cependant, ne nous intresserons de prs quaux concepts qui seront mis en uvre dans notre travail, et nous naborderons pas la gestion mmoire et entres/sorties, tant donn que les techniques utilises pour celles-ci, sont semblables celles des systmes classiques (non temps rel). 1.5.1. Principes de base du multitche Un systme informatique est dit, en multitche, sil permet alternativement dans le temps, lexcution de plusieurs programmes coexistant en mmoire, tout en assurant leur intgrit. En vue dclaircir davantage le principe de multitche, quelques dfinitions essentielles sont prsentes dans les sous paragraphes suivants :

1 Les concepts temps rel

1.5.1.1.

Notion de processus1

Cest une entit dynamique qui nat, qui vit et qui meurt, par opposition la notion de programme qui est une entit statique qui occupe un espace en mmoire ou sur disque et qui, tant quelle nest pas excute, ne produit aucune action [SB 03]. Dautre part, un programme peut tre vu comme un ensemble de modules (sousprogrammes) et lexcution dun module donne naissance un processus [SB 03]. 1.5.1.2. Contexte dun processus [SB 03]

Un contexte sera reprsent dans une structure regroupant les informations essentielles pour lexcution du processus comme le contenu des registres, sa pile dexcution son masque dinterruption, son tat, son compteur ordinal, ses indicateurs, un pointeur vers sa table des pages, sa cl dcriture en mmoire, etc. Les diffrents tats que peut prendre un processus sont les suivants (figure 1.3) :

actif

Attente dvnement

bloqu

Allocation de lUC Interrompu Evnement arriv

activable

Figure 1.3. Etats des processus.

1. Les notions prsentes pour les processus sont, galement valable pour les tches. Cependant, nous aurons tendance mesure que nous progressions dans ce chapitre, dutiliser le terme tche, auquel nous dfinirons par la suite, les spcificits, pour servir en sens le concept temps rel.

1 Les concepts temps rel

tat bloqu : le processus ne dispose pas de toutes les ressources ncessaires pour excuter linstruction suivante. Cela est d au partage des ressources dont le nombre est limit ; avec lhypothse que les ressources que ncessite un processus ne lui sont pas toutes alloues la fois, ce qui est le cas dans la plupart des systmes ; tat actif : le processus dispose de toutes les ressources ncessaires et il sexcute ; tat activable ou prt : il dispose de toutes ses ressources, hormis lunit centrale (CPU), occupe par un autre processus.

Le blocage est soit : blocage matriel : le blocage est d la demande dune ressource alors que celle-ci nest pas disponible ; il nest pas prvu par le programmeur ; blocage intrinsque : le blocage est prvu par le programmeur. La transition de ltat activable ltat actif se traduit par la modification du vecteur dtat du processus par un processus particulier, le processus du systme charg de lordonnancement des tches appel ordonnanceur, ou scheduler en anglais (voir paragraphe 1.5.2.1.). La transition de ltat actif ltat bloqu est provoque par le processus lui-mme ; le blocage est intrinsque ou matriel . La transition de ltat actif ltat activable est provoque par la prise en compte dune interruption plus prioritaire que le niveau en cours ou bien par lordonnanceur, la fin dun quantum de temps dans un systme temps partag. La transition de ltat bloqu ltat activable est provoque par un processus du systme la suite de larrive dun vnement attendu par le processus. Cette dernire transition ne saccompagne pas automatiquement dune commutation de contexte tandis que les trois premires sont toujours suivies dune commutation de contexte. Larrive dun vnement est signal par une interruption. Par consquent, prendre en compte un vnement revient traiter linterruption correspondante. Lensemble des processus du systme est reprsent en gnral par une liste chane dont chaque lment est un bloc de contrle de processus et pourrait avoir la structure dcrite figure 1.4.

1 Les concepts temps rel

Process_id tat Priorit droits daccs Pointeur vers la table des pages ou zones mmoire

mot dtat courant vnement attendu pointeur

Contexte processus suivant

Figure 1.4. Contexte dun processus.

1.5.1.3.

Zones mmoire dun processus

Dune faon gnrale, un processus est compos de trois zones mmoire, comme le montre la figure 1.5. Zone programme : contient le code excutable du processus ; Zone de donnes : les donnes initialises, les donnes non initialises et les donnes statiques (externes, globales ou dclares comme statiques) rsident dans cette zone ; Zone de pile : nous y trouvons gnralement des informations temporaires (variables locales, adresses de retour, paramtres ).

Lallocation de ces zones est assure par lexcutif, qui dispose dun gestionnaire mmoire lui permettant lors du lancement dun processus, dattribuer celui-ci, des pointeurs contenant ladresse du dbut de chacune des trois zones cites. Ces pointeurs feront partie du contexte du processus lanc.

1 Les concepts temps rel

zone programme Contexte du processus

ptr_programme

zone de donnes

ptr_donnes

ptr_pile zone de pile

Figure 1.5. zones associes au processus.

1.5.1.4.

Les appels au systme

Lobjectif de tout excutif temps rel est, doffrir un environnement dans lequel les processus peuvent, exploiter aisment et efficacement les ressources systme. En effet, il nest pas commode, dire mme fastidieux, de rcrire chaque fois et dans chaque programme les routines complexes et usuelles (exemple : faire une entre sortie sur disque). Cet amas de code se voit alors rduire une seule instruction dappel de fonction. Pour faire un appel systme, le mcanisme ne se limite pas gnralement des procdures ou fonctions implanter en mmoire. Lexcution de ces fonctions se fait, dans lespace mmoire de lexcutif. La quasi-totalit des processeurs actuels disposent, dinstructions et des mcanismes pouvant assurer le bon passage du mode utilisateur (ct programme), au mode systme (ct excutif). Gnralement, une exception est produite lors dun appel systme, provoquant ainsi un droutement vers un gestionnaire traitant, o sera analys le type de fonction sollicite par lappelant, en tenant compte des paramtres rcuprs depuis la pile ou les registres. Ces derniers contiendront au retour les rsultats de lappel systme. (Voir figure 1.5).

1 Les concepts temps rel

10

Pour les excutifs temps rel, et en particulier ceux des systmes embarqus, le temps de rponse de tout appel systme doit tre connu et fourni par le concepteur de lexcutif ; ce dernier doit entre autres borner ce temps, afin de respecter le dterminisme en temps. Chaque fonction systme (y compris les routines dinterruptions ) se voit alors attribue, un temps maximal de traitement, qui doit aussi tre pris en compte par les dveloppeurs dapplications temps rel.

processeur registres

paramtres et valeurs de retour zone de pile

appel au systme

programme utilisateur

noyau

fonction systme excutif

Figure 1.6. droulement dun appel systme

1 Les concepts temps rel

11

1.5.1.5.

Section critique

Un systme multitche est souvent concern par un partage de ressources. Dans la plupart des cas, ces ressources peuvent tre utilises que par un seul processus la fois et, leur utilisation, ne peut tre interrompue. Tandis que la ressource CPU peut, contrer par elle-mme la simultanit daccs, les procdures dans lesquelles le code est partageable en mmoire ne peuvent y pallier. Un tel code est dit, section critique. Si deux ou plusieurs processus accdent la fois, la section critique, une erreur fatale voire catastrophique se produira.

Exemple Nous pouvons illustrer travers un exemple [PAL 04], le problme li la section critique. Considrons les programmes P1 et P2 dfinis, en langage C.

Void P1(void) { Printf (Je suis P1); }

Void P2(void) { Printf (Je suis P2); }

Processus P1

Processus P2

Supposons prsent le scnario dexcution suivant : P1 effectue une entre sortie, le message Je suis est affich ; P1 est interrompu au profit de P2 ; P2 effectue une entre sortie, et le message Je suis est affich ; P1 reprend de nouveau la main suite une interruption ; Le message P1 est affich aprs une entre sortie ; P1 finit lexcution, et P2 la reprend de nouveau ; Le message P2 est affich aprs une entrs sortie, puis P2 quitte le CPU.

La synthse du scnario dexcution de P1 et P2 conduit au rsultat : Je suis Je suis P1 P2 Laffichage est alors incorrect. Le paragraphe suivant propose, une solution pratique au prsent problme.

1 Les concepts temps rel

12

1.5.1.6.

Synchronisation par smaphores binaires

Propos la premire fois par Dijkstra, un smaphore S est un emplacement mmoire, qui agit comme un verrou, pour protger les sections critiques. Le smaphore peut tre manipul que par deux primitives P(s) et V(s) (indivisibles, ininterruptibles), elles signifient respectivement inhiber et autoriser. Les primitives peuvent tre dfinies en langage C comme suit : [PAL 04]

void P(int S) { while (S ==TRUE); S=TRUE; }

void V(int S) { S=FALSE; }

La primitive P(s) se bloque, tant que la valeur du smaphore S est TRUE. V(s) positionne le smaphore S FALSE, permettant ainsi le dblocage au niveau de P(s). Nous montrons ci dessous, lutilisation pratique de ces primitives, par deux processus concurrents.

Processus_1 . . P(S) Section critique V(S)

Processus_2 . . P(S) Section critique V(S)

Le smaphore S doit tre initialis FALSE, pour que le premier processus demandant la section critique, puisse y accder.

1 Les concepts temps rel

13

Nous pouvons appliquer le prsent principe, pour rsoudre le problme auquel nous sommes confronts, dans le paragraphe prcdent. Il suffit alors dajouter les primitives P(S) et V(S) de la manire suivante :

Void P1(void) { P(S); Printf (Je suis P1); V(S); }

Void P2(void) { P(S); Printf (Je suis P2); V(S); }

Processus P1

Processus P2

Nous supposons comme dclar global, le smaphore S et initialis FLASE. Que ce soit le processus 1 ou le processus 2 qui accde le premier la section critique, ceci ninflue point lexcution de lautre. En effet, le processus faisant appel la primitive P(S), exclue lautre. Ce nest quune fois la primitive V(S) est excute que le processus exclu ou bloqu puisse reprendre lexcution. Ce qui nous donnera toujours un affichage correct. Il existe une autre variante de smaphores utilise galement par les excutifs. Il sagit des smaphores compte, destins la protection des ressources rentrantes mais pas forcement critique. Autrement dit, protger une ressource dont le nombre maximum de processus pouvant y accder simultanment est fix, par la valeur du smaphore.

Remarque : Contrairement aux systmes classiques, o on pose gnralement la condition de Dijkstra suivante : Chaque processus en section critique doit, sortir au bout dun temps fini. . Les excutifs temps rel doivent quant eux satisfaire cette condition, mais aussi dterminer ce temps de blocage, et ce, pour encore satisfaire la notion de dterminisme ; les prochains paragraphes mettront en relief les techniques utilises et mettre en uvre dans notre travail.

1 Les concepts temps rel

14

1.5.2. Ordonnancement des tches temps rel 1.5.2.1. Notion de tches temps rel

Dans la littrature, le terme tche est souvent prfr pour signifier, la priodicit ou la manire cyclique dexcution, que ce, du processus dont laspect est attach plutt, au sens de lunicit de la demande dexcution. Cependant, la tche obit parfaitement, aux principes du multitche pralablement noncs le cas chant. Les tches doivent entre autres respecter des dlais critiques imposs par les dynamiques de lenvironnement contrler. Dun point de vue temporel, les paramtres suivants peuvent caractriser une tche [SB 98] : la date de rveil : qui correspond linstant partir duquel la tche peut commencer son excution , la dure dexcution : gale la borne suprieure du temps processeur ncessaire lexcution de la tche, le dlai critique : qui est lintervalle de temps, partir de la date de rveil, durant lequel la tche doit sexcuter. En dehors de cet intervalle, son excution devient inutile. la priode : est lintervalle de temps fixe qui spare les arrives successives dune tche. Ce paramtre concerne les tches actives par un signal priodique provenant dune horloge temps rel interne, cest le cas par exemple de lacquisition de donnes. Ce type de tches est appel tches priodiques.

Les tches dont la date de rveil nest pas connue avant la mise en exploitation du systme sont dites tches apriodiques. En gnral, les tches priodiques assurent le droulement normal des fonctions de commande du procd alors que les tches apriodiques traitent les alarmes et les tats dexception [SB 98].

1 Les concepts temps rel

15

1.5.1.2.

Problmatique

Au paragraphe 1.5.1.5. (Section critique), nous avons prsent les ressources du systme informatique et nous avons cit la ressource processeur, comme tant une ressource qui peut bien par elle-mme, contrer le problme de la simultanit daccs. Rellement, cette constatation nest valable, que si une considration du processeur comme systme isol, est faite. En effet, avant lattribution du processeur une seule tche, celle-ci peut tre rsultat dune slection, parmi les tches coexistant en mmoire, assure par lodonnanceur. Les ordonnanceurs qui effectuent ce travail nont quune vision trs gnrale des tches. Ils ne considrent pas les traitements quelles effectuent, mais utilisent, pour effectuer leur slection, des paramtres dfinis lavance comme la priodicit de la tche ou son chance,... [LT 91]. La comptition pour laccs une ressource critique est un problme classique et est connu sous le nom dexclusion mutuelle, pour lequel il existe une varit de solutions plus ou moins complexes. Dans le domaine du temps rel, il sagit non seulement de garantir laccs exclusif aux ressources critiques (qui est le rle de lexcutif temps rel) mais aussi et surtout de minimiser le temps dattente pour laccs ces ressources. Il existe des protocoles dits dallocation de ressources intgrs aux algorithmes dordonnancement et capables de rduire le temps dattente des tches bloques pour lobtention de ressources afin que celles-ci ne dpassent pas leurs chances [SB 98]. Sachant que les algorithmes dordonnancement sappliquent aux configurations de tches priodiques, nous pourrons apprhender les tches apriodiques avec ces algorithmes si nous les transformons, par exemple, en tches priodiques particulires appeles serveurs [SB 98].

1 Les concepts temps rel

16

1.5.1.3.

Algorithmes dordonnancement [SB 98]

Plusieurs critres peuvent dfinir un algorithme dordonnancement : 1.5.1.3.1. Premptif / non premptif Un algorithme dordonnancement est : non premptif: si toute tche qui commence son excution doit tre acheve avant quune autre tche obtienne le processeur ; premptif: si une tche peut tre interrompue au profit dune autre et tre reprise ultrieurement.

Les algorithmes non premptifs sont faciles mettre en uvre ; de plus, ils ont un faible cot puisque les changements de contexte sont minimiss et il ny a pas lieu de grer laccs concurrent aux ressources critiques. Cependant les algorithmes premptifs sont plus efficaces puisquils offrent une excution parallle des tches en ayant plus de libert pour choisir une solution dordonnancement.

1.5.1.3.2. Hors ligne / en ligne Un algorithme dordonnancement est dit : hors ligne : lorsque toutes les tches ainsi que leurs caractristiques temporelles sont connues avant le dmarrage de lapplication. La construction dune 1 squence dexcution des tches respectant les contraintes temporelles est possible et lordonnanceur se rduit une entit appel rpartiteur qui ne fait que lancer les tches dans lordre dict par la squence. Il est vident quune telle approche ne peut prendre en compte des tches dont la date dactivation nest pas connue au dpart. en ligne : lorsque la squence dexcution est construite au fur et mesure uniquement avec les tches prtes linstant courant ; ce qui permet la prise en compte et lexcution des tches apriodiques.

1. Une squence dexcution est dite valide si toutes les tches se sont excutes dans le respect de leurs contraintes temporelles et de ressources.

1 Les concepts temps rel

17

1.5.1.3.3. Conduit par la priorit Lordonnanceur tel quil a t dfini prcdemment est lune des fonctions principales de lexcutif temps rel. Il est charg dattribuer le processeur chaque tche avant son chance en utilisant un algorithme dordonnancement. On dit quun algorithme dordonnancement est conduit par la priorit sil excute chaque instant la tche la plus prioritaire. La priorit est ou bien affecte par le concepteur de lapplication en fonction de la criticit des tches ou encore assigne de manire automatique en fonction dun paramtre temporel caractrisant les tches telles que la priode ou lchance qui refltent lurgence et non limportance de la tche au sens applicatif. Une classification de ces algorithmes est base sur le type de la priorit instaure entre les tches, qui peut tre fixe ou dynamique. Un algorithme priorit fixe affecte, chaque tche, une priorit qui reste constante durant lexcution de cette dernire. Un algorithme priorit dynamique recalcule la priorit des tches durant leur excution.

1.5.1.4.

Algorithmes dordonnancement priorits fixes sans partage de ressources

Avant de dtailler ce prsent paragraphe, nous avons jug ncessaire, dintroduire une modlisation sur laquelle nous nous appuierons, pour prsenter les notions et dfinitions attaches. Nous mettrons laccent que sur lalgorithme RM, qui sera voqu lors des prochains chapitres. Pour le lecteur intress par dautres variantes, il peut consulter les rfrences suivantes : [SB 98, SB03]. 1.5.1.4.1. Modlisation dune tche Nous pouvons reprsenter du point de vue temporel, une tche priodique Ti par les paramtres suivants [SB 98] (voir figure 1.7.) : ri : la date de premire activation, C i : la dure maximale d'excution, Di : le dlai critique maximal que Ti est tenue de respecter, Pi : la priode qui est l'intervalle de temps maximal sparant deux instances successives de Ti.

Nous avons ncessairement les relations suivantes: 0 C i P i D i Remarque : Lorsque la priode Pi est gale au dlai critique Di la tche est dite chance sur requte.

1 Les concepts temps rel

18

tant rveille alatoirement, une tche apriodique est caractrise par le triplet (ri , Ci ,Di ) o: ri : la date initiale de rveil de la tche, C i : la dure maximale d'excution, D i : son dlai critique

Figure 1.7. Les caractristiques temporelles d'une tche priodique [SB 98]

1.5.1.1.2. Condition ncessaire de validation

Pour une configuration donne, nous dfinissons le facteur dutilisation U comme tant le pourcentage dutilisation du processeur par les tches priodiques: U = (Ci / Pi) Il nest videmment pas possible dutiliser le processeur au-del de ses capacits cest--dire dpasser un taux doccupation de 100%: cest la condition ncessaire pour une configuration de tches priodiques : U 1

1 Les concepts temps rel

19

1.5.1.1.3. Algorithme Rate Monotonic (RM)

Liu et Layland dans [LL 73] ont propos, lalgorithme du Rate Monotonic, qui est la base des thories sur lordonnancement des tches priodiques. Il peut tre utilis, pour ordonnancer des tches sur un monoprocesseur. Lalgorithme repose sur le principe suivant : La priorit dune tche est inversement proportionnelle sa priode. Autrement dit, la grande priorit est associe la tche de plus petite priode. Et pour le cas des tches de mme priode, leur priorit est fixe alatoirement. Notons que cet algorithme est, optimal pour les tches chance sur requte. *Thorme (Rate Monotonic) [LL 73] : Toute configuration de n tches priodiques chance sur requte est fiablement ordonnance par RM si :

(Ci / Pi ) n (21/n 1)
i=1

* La condition est suffisante mais pas ncessaire. 1/n * Lorsque n est grand : n (2 1) converge vers Ln2=0.69 Exemple 1 [SB 03] : Soit lexemple de deux tches A et B dont les caractristiques sont donnes au tableau 1.1. La priorit de A est suprieure celle de B car la priode de A est infrieure celle de B. Si on droule la squence dexcution, on saperoit que la squence est valide (Figure 1.8) (La flche montante symbolise le rveil de la tche, et la flche descendante symbolise la fin de son chance).
Tches Date de rveil Dure dexcution Dlai critique Priode

A B

0 0

2 3

6 5

6 8

Tableau 1.1. Caractristiques temporelles des tches

1 Les concepts temps rel

20

Tche A

10

11

12

Tche B

Figure 1.8. Squence valide obtenue avec RM pour la configuration du tableau 1.1.

Nous pouvons vrifier facilement, le test dordonnanabilit. Dans le cas o la condition ntant pas vrifie, nous pourrions rien conclure quant la possibilit dordonnancement, car mme dans ce cas-ci, lordonnancement peut tre valide (la condition est suffisante mais pas ncessaire).

Exemple 2 : Soient les tches A,B, et C, dont le triplet les caractrisant est respectivement : (r=0, C=3, P=20) ; (r=0, C=2, P=5) ; (r=0,C=2,P=10). Suivant lalgorithme RM, priorit(B) > priorit(C) > priorit(A). En appliquant la condition suffisante dordonnanabilit :

(Ci / Pi ) = 3/20 + 2/5 + 2/10 = 0.75 n(21/n 1) = 0.77


i=1

La condition est vrifie. Le diagramme de Gantt correspondant est donn la figure 1.9.

1 Les concepts temps rel

21

Tche A

20

Tche B

10

12

15

17

20

Tche C

10

12

14

20

Figure 1.9. squence dexcution valide avec RM

1.5.1.1.4. Algorithme Deadline Monotonic (DM) Il associe la plus forte priorit la tche de plus petit dlai critique. La condition suffisante dordonnanabilit pour cet algorithme est : (Ci / Di) < 1

1.5.1.5.

Ordonnancement des tches apriodiques [SB 98]

Dans le contrle de procd, des vnements alatoires en provenance du procd ou des vnements internes sans aucune synchronisation avec le systme peuvent survenir tout instant. Celui-ci doit reconnatre la nature dun vnement et dclencher lexcution du service li cet vnement. La prise en compte dun tel vnement se fait grce une tche apriodique. Le problme est alors dordonnancer ce type de tches. Une premire solution consiste ordonnancer les tches apriodiques, en second plan, au sein de la configuration des tches priodiques. On commence par ordonnancer lensemble des tches priodiques afin de dduire les temps creux o seront insres les tches apriodiques. Une autre solution consiste ordonnancer les tches apriodiques sur le mme plan que les tches priodiques. Une tche priodique appele serveur est ddie lordonnancement des tches apriodiques.

1 Les concepts temps rel

22

Les caractristiques temporelles du serveur sont celles dune tche classique: rs : la date de rveil, Cs : la dure maximale d'excution rserve lexcution des traitements non priodiques, Ps: la priode value de sorte prendre en compte lensemble des requtes non priodiques.

calcules en fonction des caractristiques des tches apriodiques servir.

1.5.1.5.1. Serveur scrutation [SB 98] Si aucune requte non priodique na t mmorise avant la date dactivation du serveur, celui-ci aura un temps dexcution nul pendant la priode courante (voir figure 1.10). Si, par contre, une requte a t mmorise, le serveur utilisera son temps dexcution Cs sa prochaine activation pour excuter le traitement associ. Si le traitement nest pas termin sur une priode, il sera poursuivi pendant la (les) priode(s) suivante(s). Le temps de rponse (temps coul entre la date de rveil et la date de fin dexcution) des tches apriodiques peut tre important surtout si elles surviennent juste aprs la fin dexcution du serveur. Au niveau de lanalyse de lordonnanabilit, ce serveur est considr comme une tche priodique.

Figure 1.10 Serveur scrutation

1 Les concepts temps rel

23

1.5.1.5.2. Serveur ajournable [SB 98] : Pour remdier lincompatibilit des rythmes darrive, ce serveur maintient son temps dexcution mme si aucune requte non priodique nest survenue (voir figure 1.11). Dans le cas o une requte survient, le serveur excute le traitement associ dans la mesure o son temps nest pas puis ; il nattend pas la prochaine activation pour la servir.

Figure 1.11 Serveur ajournable

1 Les concepts temps rel

24

1.5.1.6.

Algorithmes priorits variables sans partage de ressources :

Comme pralablement nonc, pour ce type dalgorithmes, les tches ont une priorit, qui volue durant la vie de lapplication. Nous citerons les deux principaux existants.

1.5.1.6.1. Algorithme Earliest Deadline (ED) Les tches sont classes par ordre croissant de leur chance. Il est optimal, pour un systme sans partage de ressources. La condition suffisante dordonnanabilit pour les tches priodiques et apriodiques indpendantes est la suivante : (Ci / Di) 1 Il existe, une condition ncessaire et suffisante dordonnanabilit, mais qui concerne que les tches priodiques chance sur requte. Celles-ci doivent alors vrifier lingalit suivante : U 1 (U reprsente le facteur dutilisation du processeur). 1.5.1.6.2. Algorithme Least Laxity (LL) Dans cet algorithme, la plus forte priorit est associe dynamiquement, la tche dans laquelle le temps, sparant la fin dexcution et lchance, est le plus petit. La condition ncessaire et suffisante dordonnanabilit pour les tches priodiques chance sur requte est : U 1 (U reprsente le facteur dutilisation du processeur). Remarque Dans [Hen 75], il a t dmontr, que ED utilise mieux le temps CPU, parmi tous les algorithmes cits prcdemment ( priorits statiques et dynamiques).

1 Les concepts temps rel

25

1.5.1.7.

Problmes lis lexclusion

Comme nous lavons soulign, lexcutif temps rel doit garantir lexclusion mutuelle, entre tches, lors de laccs une ressource. Nous avons abord une technique (smaphores binaires) permettant la rsolution pratique du problme li lexclusion. Cependant, sil y a exclusion mutuelle, lapproche premptive base sur les priorits conduit des situations dinterblocage et dinversion de priorits. Ces deux derniers sont illustrs, travers des exemples, dans les sous paragraphes suivants : 1.5.1.7.1. Interblocage Exemple : Soit lexemple de deux tches priodiques A et B, se partageant deux ressources R1 et R2. Avec priorit(A) > priorit(B) Admettant prsent les situations suivantes (voir figure 1.12.) : 123456789La tche B se rveille la premire et demande la ressource R1. R1 tant libre, la tche B lobtient. La tche A se rveille, prempte B et, demande la ressource R2. R2 tant libre, la tche A lobtient. La tche A est dans la section critique de R2, demande la ressource R1. La tche A se bloque, et attend la libration de R1. La tche B reprend la main ; dtenant R1, elle demande R2. La tche B se bloque, et attend la libration de R2. Le systme se bloque dfinitivement (treinte fatale ou deadlock).

La tche A
0 4 P(R2) P(R1)

La tche B

P(R1)

P(R2)

Lgende : Quantum de temps en section critique.

Figure 1.12. Situation dinterblocage.

1 Les concepts temps rel

26

1.5.1.1.2. Inversion de priorits Exemple : Considrons trois tches priodiques A,B et C avec priorit(A) > priorit(B) > priorit(C), et se partagent une seule ressource critique S. Les notations adopter sur le diagramme de Gantt : La demande dune ressource : (par exemple, par la tche A) A/ Attribution de la ressource une tche : (par exemple, A) A Libration de la ressource : (obligatoirement par la tche en section critique) /* Admettant la squence dexcution de ces trois tches, donne par la figure 1.13.
Tche A

11

Tche B

Tche C

11

13

C/
C C C

A/
C C C C C C

/*
A

/*
Occupation de la ressource S

Figure 1.13 Exemple dinversion de priorits La tche C demande la ressource S linstant 0 et lobtient. La tche C est prempte par la tche A. (car priorit(A) > priorit(C)) La tche A demande linstant 4 la ressource S (dtenue par la tche C) et se bloque. La tche C reprend la main, et elle est toujours en section critique. La tche B prempte la tche C (car priorit(B) > priorit(C)). La tche C reprend lexcution linstant 8 et libre la ressource S linstant 9. La tche A obtient la ressource S linstant 9.

La tche A possde la plus haute priorit dans le systme considr, pourtant, elle a t bloque par des tches moins prioritaires. Ce phnomne auquel nous assistons est appel inversion de priorits.

1 Les concepts temps rel

27

1.5.1.8.

Protocoles dallocation de ressources

Les solutions pour prvenir la situation dinterblocage et dinversion de priorits existent, nous prsenterons les deux protocoles qui seront mis en uvre dans notre travail. Pour le lecteur intress par autres que ceux prsents, il peut consulter [SB 98]. 1.5.1.8.1. Protocole priorit hrite (PPH) Le principe [SRL 90] tant de rehausser la priorit de la tche obtenant la ressource critique, celle de la tche quelle bloque en attente de la mme ressource. Autrement dit, cest attribuer la tche T entrante en section critique, une priorit gale au Max {Pr(T1), Pr(T2), Pr(T3),, Pr(Tn)}, sous condition que les tches : T1 , T2 , T3 , Tn aient une priorit (Pr) suprieure celle de T et attendent toutes la ressource dtenue par T. (la priorit de T tant rtablie, au moment de la libration de la ressource quelle a occupe). De cette manire, aucune tche de priorit infrieure ne pourra, prempter la tche T durant son excution en section critique. Exemple : Nous appliquons le protocole priorit hrite, lexemple donn prcdemment dans le paragraphe 1.5.2.6.2. et nous aurons alors la figure 1.14.
Tche A

Tche B

11

Tche C

11

13

/C
C C C C

/A
C C

/*
A

/* Occupation de la ressource S

Figure 1.14 rsolution dinversion de priorit par PPH.

1 Les concepts temps rel

28

Nous constatons qu linstant 4 (instant o la tche A demande la ressource S), la tche C hrite de la priorit de la tche A. Cest ainsi que la tche B, na pu prempter la tche C linstant 5 (Comme ce fut le cas dans la figure 1.13.). La tche A entre alors en section critique linstant 6 (aprs libration de la ressource par la tche C). Aussi, nous pouvons remarquer le fait que la tche C reprend sa priorit linstant 6 (justifi par le fait que la tche C reprend son excution qu partir du moment o la tche B se termine. Autrement dit, linstant 6 nous avons de nouveau : Pr(B) > Pr(C)). 1.5.1.1.2. Protocole priorit plafond (PCP) En anglais Priority Ceiling Protocol. Ce protocole t propos [SRL 90], pour prvenir la situation dinterblocage que nous avons vu au paragraphe 1.5.2.6.1. Il dfinit une nouvelle notion : priorit plafond (PP) dune ressource, qui est une valeur maximum des priorits des tches qui lutilisent, en posant la condition suivante : Une tche T ne peut entrer en section critique, que si la priorit de la ressource R quelle demande, est strictement suprieure la priorit plafond des ressources en cours dutilisation (hormis celles de T). En section critique, la tche devra hriter de la priorit de la tche la plus prioritaire quelle bloque. Ceci alors sous-entend que le protocole priorit plafond, rsout galement le problme dinversion de priorit. Exemple : Nous pouvons appliquer le protocole priorit plafond, pour rsoudre le problme dinversion de priorit donn au paragraphe 1.5.2.6.2 ; vu le cas similaire prsent en appliquant lhritage de priorit (figure 1.14), nous nous intresserons alors quau problme dinterblocage du paragraphe 1.5.2.6.1. Calculons la priorit plafond pour chacune des ressources R1 et R2 : Pour appliquer le protocole priorit plafond, ceci suppose que nous connaissions priori, les ressources susceptibles dtre utilises ; cela nous permettra alors de pouvoir calculer les priorits plafond de chacune des ressources dans le systme considr. En se rfrant alors lexemple dinterblocage donn (paragraphe 1.5.2.7.1), nous pouvons crire : PP(R1)= Max {Pr(A), Pr(B)} = Pr(A). PP(R2)= Max {Pr(A), Pr(B)} = Pr(A). Le scnario dexcution des deux tches suivant le PCP serait alors le suivant (voir figure 1.15) :

1 Les concepts temps rel

29

La tche B se rveil linstant 1 et sexcute. La tche B demande la ressource R1 ( t=2) qui est libre, et lobtient (P(R1)). La tche A se rveil linstant 4, prempte B (car Pr(A) > Pr(B)). La tche A demande linstant 5 la ressource R2 qui est libre, mais ne lobtient pas. (PP(R2) = Pr(A) nest pas > PP(R1) ; elle ne satisfait pas la rgle nonce par le PCP). Puisque A se bloque, la tche B reprend lexcution et obtient R2 linstant 5. La tche B linstant 5 hrite de la priorit de la tche A. La tche B demande R2 linstant 6 et lobtient. La tche B libre R1 et R2 linstant 8, et sa priorit est alors restaure. La tche A obtient la ressource R2 pour laquelle elle a t bloque, puis R1 ( t=10). La tche A libre la ressource R1 et R2 linstant 12.

Tche A

4 P(R2)

11 P(R1)

V(R1) ;V(R2)

Tche B
0 1 P(R1) 4 5 P(R2) 7 V(R2) ;V(R1) ; restauration de Pr(B).

Pr(B)=Pr(A) (hritage de priorit).

Figure 1.15. rsolution de linterblocage, avec le PCP.

Remarque : Bien que le protocole priorit hrite soit capable dviter linversion de priorit, il ne prvoit cependant pas linterblocage. Il a t abord que pour illustrer le phnomne dinversion de priorit. Nous allons discuter, de limplmentation du protocole priorit plafond dans les prochains chapitres, pour cela, nous allons nous focaliser dans ce qui suit, uniquement sur le PCP.

1 Les concepts temps rel

30

1.5.1.1.3. Facteur de blocage Les solutions que nous avons vus au paragraphe prcdent, permettent de borner le temps d'attente des tches sur l'accs aux ressources. Ces bornes B, peuvent ensuite tre ajoutes au temps d'excution des tches et ainsi tre intgres dans les tests d'acceptation des configurations. Pour le protocole priorit plafond, le temps maximal de blocage B est donn par lalgorithme suivant [TH 95] :

Dbut Soit une tche T: 1. Considrer les tches moins prioritaires que T 2. Slectionner celles qui possdent des ressources communes avec T 3. Considrer uniquement les ressources dont la priorit plafond est priorit (T), soit s ce nombre 4. B = max (dure des sections critiques pour lutilisation de la ressource ci)
i=1,s

Fin. Si T est la tche la moins prioritaire, alors le temps de blocage est nul car il ny a pas de tche moins prioritaire qui peut la bloquer. Exemple : Soit lexemple de cinq tches, dont les caractristiques sont donnes au tableau 1.2, se partageant les ressources c1 et c2 dont le temps des sections critiques correspondant est respectivement t1 et t2 (exprim en s).
Tches Dure dexcution Priode Priorit

t1 4 4 2 0 0

t2 0 0 2 3 3

A1 A2 A3 A4 A5

10 8 10 9 5

60 200 100 60 200

3 1 2 3 1

Tableau 1.2. Caractristiques des tches.

1 Les concepts temps rel

31

En utilisant le protocole priorit plafond, calculons B3 pour la tche A3. Pour cela, supposons que les priorits des tches respectent les rgles de lalgorithme RM. Calculons les priorits plafond des ressources c1 et c2. PP(c1) = max priorits { A1, A2, A3 }= 3. PP(c2) = max priorits { A4, A5, A6 }= 3. Appliquons prsent, lalgorithme de calcul de la dure maximale de blocage. Trouvons les tches moins prioritaires que A3 : A2 et A5.

Considrons parmi ces tches, celles qui partagent des ressources avec A3 : A2 partage c1 et A5 partage c2. Prenons uniquement les ressources dont la priorit plafond est suprieure ou gale la car PP(c1)=3, PP(c2)=3 et Priorit(A3)=2. priorit de A3 : c1 et c2 B3 = max ( t1(A2) , t2(A5) ) = max (4 , 3) = 4. 1.5.1.1.4. Algorithme RM avec partage de ressources En tenant compte du temps maximal de blocage B, le test de faisabilit RM pralablement nonc devient alors comme suit :
i

k=1

(Ck / Pk ) + (Bi / Pi) i (21/i 1)

pour i

1 Les concepts temps rel

32

Conclusion Le premier chapitre nous a permis dintroduire dune faon gnrale, les principes utiliss dans les excutifs temps rel monoprocesseur, en se focalisant sur ceux qui nous servirons de discussion dans les prochains chapitres. Dune faon assez exhaustive, ce chapitre donne des gnralits dun systme temps rel, en mettant en vidence la notion temps et limportance capitale travers laquelle, nous pouvons voir la spcificit dun tel systme. Nous avons abord par la suite la notion dexcutif temps rel, tout en rappelant quelques notions de base du multitche (processus, contexte, les appels au systme, la section critique), et nous avons intgr la notion temps au processus, ce qui nous a amen dfinir la notion de tche. Cette dernire, quelle soit priodique (de priorit fixe ou dynamique ) ou apriodique, nous avons prsent dans chacun des cas, les techniques souvent utilises et utiliser dans notre travail, pour pouvoir les ordonnancer. Pour prsenter lordonnancement des tches, nous les avons spar en catgories, suivant le fait que lordonnancement se fait sur des tches dpendantes ou indpendantes, au sens du partage de ressources. Pour ce dernier, nous avons pass en revue, les protocoles permettant lvitement des problmes lis lexclusion mutuelle, tout en donnant la possibilit de pouvoir calculer ou borner, la dure de blocage dune tche, en attente dune ressource. Le prochain chapitre va illustrer travers des exemples concrets, quelques excutifs temps rel prsents et rencontrs dans le milieu industriel, en essayant de complter et de mettre en vidence les techniques vues dans ce chapitre.

1 Les concepts temps rel

33

Bibliographie

[DP 91] : Alain DORSEUIL et Pascal PILLOT- Le Temps Rel En Milieu Industriel (DUNOD 1991). [Hen 75] : R. Henn, Deterministic Modelle fur die Prozessorzuteilung in einer harten Realzeit-Umgebung , Phd Thesis, Technical Univ. Munich, 1975. [LL 73] : C. L. Liu, J. W. Layland - Scheduling Algorithms for Multiprogramming in a Hard Real-Time Environment- Journal of the ACM, Vol. 20, n1, pp. 46-61, 1973. [LT 91] : Lourent TOUTAIN - Thse de doctorat luniversit du Havre en 1991. Thme : SMASON : Un simulateur pour les systmes rpartis et temps-rel. [PAL 04] : Phillip A.Laplante Real Time Systems Design And Analysis. Third Edition. (A JOHN WILLEY & SONS 2004). [SB 03] : Samia Bouzefrane - Les Systmes dExploitation Unix, Linux, et Windows XP (DUNOD 2003). [SB 98] : Samia Bouzefrane- Thse de doctorat luniversit de Poirier en 1998. Thme : tude temporelle des Applications Temps Rel Distribues Contraintes Strictes base sur une Analyse d'Ordonnanabilit. [SRL 90]: L. Sha, R. Rajkumar, J. Lehoczky, Priority inheritance protocols: an approach to real-time synchronisation , IEEE Transaction Computers, Vol. 39 n9, pp. 1175-1185, 1990. [TH 95] : K. Tindell, H. Hansson, "Real-Time Systems and Fixed Priority Scheduling", Report of Uppsala Univ., oct. 1995.

Chapitre 2

Exemples de systmes et plates-formes temps rel

Nous voulons travers ce chapitre, complter les concepts temps rel prsents au premier chapitre dune part, et dautre part, faciliter labord des prochains chapitres. Les deux premiers excutifs que nous aurons prsenter, couvriront respectivement dune faon assez exhaustive les environnements Linux et Unix temps rel ; quant aux platesformes temps rel, elles montreront un cas pratique dun systme embarqu, et le dveloppement de nouvelles politiques dordonnancement notamment temps rel. Nous avons alors choisi, les systmes suivants : Real-Time Application Interface (RTAI) : variante de Linux temps rel, dvelopp Dipartimento di Ingeniera Aerospaziale, Politecnico di Milano du Prof. Paolo Mantegazza. VxWorks : variante de Unix temps rel, dvelopp par Wind River Systems.

Ainsi que les plates-formes suivantes : Composants Logiciels sur Etagres Ouverts Pour les Applications Temps- Rel Embarques (CLEOPATRE) : Projet lanc par plusieurs organismes franais, en vue 1 de fournir entre autres un RTOS libre. BOSSA : plate-forme ajoute au noyau Linux pour le dveloppement dordonnanceurs de processus. (IUT de Nantes).

1. Real Time Operating System.

2 Exemples de systmes et plates-formes temps rel

35

2.1. Real-Time Application Interface (RTAI) 2.1.1. Historique Le projet RTAI a pour origine le dpartement d'ingnierie arospatiale (DIAPM) de l'Ecole polytechnique de Milan (Politecnico di Milano). Pour des besoins internes, le professeur Paolo Montegazza du DIAPM entreprit de 1 dvelopper un produit inspir de RTLinux mais intgrant quelques amliorations et corrections, concernant en particulier les modes temps rel et, la gestion des nombres flottants. Contrairement RTLinux, RTAI nai pas dvelopp pour crer un produit commercial mais surtout afin d'viter, des cots de licences, sur des RTOS propritaires comme QNX, alors utilis au DIAPM. Du fait de cette optique de dveloppement interne, l'architecture actuelle de la distribution RTAI apparat comme complexe au niveau de la dfinition de l'API (syntaxe et nombre d'appels). RTAI est rapidement apparu aux yeux des responsables du projet RTLinux comme un redoutable concurrent, sachant que RTLinux avait lui une vocation commerciale. 2.1.2. Linux comme systme temps rel Linux n'est pas nativement un systme temps rel. Le noyau Linux est en effet conu dans le but d'en faire un systme gnraliste donc bas sur la notion de temps partag et non de temps rel. La communaut Linux tant trs active, plusieurs solutions techniques sont cependant disponibles pour amliorer le comportement du noyau afin qu'il soit compatible avec les contraintes d'un systme temps rel. Concrtement, les solutions techniques disponibles sont divises en deux familles : 1. Les patchs dits premptifs permettant d'amliorer le comportement du noyau 2 Linux en rduisant les temps de latence de ce dernier. Ces modifications ne transforment pas Linux en noyau temps rel contraintes strictes mais permettent d'obtenir des rsultats satisfaisants dans le cas de contraintes temps rel relatives. Cette technologie est disponible auprs de diffrents projets open source et la notion de noyau premptif est intgre dans le noyau de dveloppement 2.5. 2. Le noyau temps rel auxiliaire. Les promoteurs de cette technologie considrent que le noyau Linux ne sera jamais vritablement temps rel et ajoute donc ce noyau un vritable ordonnanceur temps rel priorits fixes. Ce noyau auxiliaire traite directement les tches temps rel et dlgue les autres tches au noyau Linux, considr comme la tche de fond de plus faible priorit. Cette technique permet de mettre en place des systmes temps rel strictes. Cette technologie est utilise par RTLinux et RTAI.
1. variante de Linux temps rel, dvelopp New Mexico Institute of Technologie par Mickal Barabanov sous la direction du Prof. Voctor Yodaiken. 2. temps durant lequel le processeur est occup excuter un certain nombre doprations, prcdant lexcution de la routine dinterruption ou la fonction systme.

2 Exemples de systmes et plates-formes temps rel

36

2.1.3. Prsentation gnrale Sous RT-Linux et RTAI, les interruptions sont gres dabord par le noyau temps rel et ne sont passes au noyau de Linux uniquement lorsquil ny a pas de tches temps rel (voir figure 2.1.).

Figure 2.1. Architecture de RT-Linux / RTAI.

Dans RTAI, ceci est ralis grce une couche RTHAL (RT Hardware Abstraction Layer). Lors du lancement du RTAI avec RTHAL, les suivantes actions sont ralises [RPG] : Gnration dun duplicata de la table des descripteurs dinterruption (IDT), et du gestionnaire dinterruptions. Ainsi, la nouvelle IDT devient la table valide du systme, quand RTAI est actif. Redirection des interruptions du RTHAL, des fonctions dinterruption enable/disable et les fonctions de flags save/restore, aux fonctions RTAI quivalentes. Celles-ci sont rfrences et regroupes dans une seule structure du RTHAL. Changement du gestionnaire de fonctions dans la nouvelle idt_table celle du dispatcher RTAI ; ce dernier prend alors le contrle du systme et de ses interruptions. Rserver les Timers (8254 et APIC) et les services pour le domaine temps rel.

2 Exemples de systmes et plates-formes temps rel

37

Sous RT-Linux et RTAI, le noyau temps rel, ses composants ainsi que les applications temps rel sexcutent tous dans lespace dadressage du noyau Linux comme des modules du noyau qui sont chargeables et dchargeables dynamiquement. Avantages : - le temps de commutation des contextes des tches est minimis. - modularit du systme.

Inconvnient : un bug dans une tche temps rel peut causer le crash du systme.

2.1.4. Les services RTAI

RTAI peut tre dcompos en plusieurs services lmentaires, comme les schedulers, FIFOs, et mmoire partage (shared memory), et, dun ensemble de services avancs 1 comme POSIX et lallocation dynamique de la mmoire. Ces services sont fournis travers des modules noyau, qui peuvent tre charg ou dcharg dynamiquement avec les commandes standards de Linux : insmod et rmmod. Le module rtai est requis, chaque fois quun service temps rel est sollicit ; quant aux autres modules ils sont ncessaires seulement lorsque le service temps rel associ est dsir [RPG]. Par exemple, si on veut seulement installer les gestionnaires dinterruption, on aura alors qu charger le module rtai. Par contre, si on dsire communiquer avec un processus Linux standard, il faudrait ce moment-l charger le module rtai_fifos, mais aussi le module rtai. Notons quil y a un ordre respecter lors du chargement des modules. Il faut toujours charger le module rtai en premier avant tout autre (car linitialisation des autres modules dpendent des fonctions fournis par le module rtai) [RPG]. Les services lmentaires fournissent un environnement temps rel, avec un ordonnancement premptif priorit fixe, ces quatre modules sont les suivants : rtai : framework de base, gestion des interruptions et un support Timer.. rtai_sched : ordonnancement bas sur la priorit, temps rel et premptif, choisi en fonction de la configuration matrielle. rtai_fifos : communication par FIFO et synchronisation par smaphores. rtai_shm : partage de mmoire.

1. POSIX=Portable Operating System Iterface for Computer Environments (standard IEEE 1003.1b), fondation qui a pour objectif dhomogniser les diffrents systmes Unix commercialiss.

2 Exemples de systmes et plates-formes temps rel

38

Les services avancs sont fournis dans les modules suivants : lxrt : utilise les appels systme de RTAI partir de lespace utilisateur rtai_pthread.o : Pthreads, POSIX 1003.1c rtai_pqueues.o : Pqueues, POSIX 1003.1b (support files de messages) rt_mem_mgr : gestion dynamique de la mmoire pour le temps rel.

2.1.4.1.

Les schedulers

La distribution RTAI fournit trois ordonnanceurs, tous temps rel, premptifs et bass sur la priorit fixe. a- UP scheduler : pour Uni Processor (localis dans le rpertoire upscheduler). Utilis par les plates-formes monoprocesseur. Supporte les timers 8254 (frquence maximale : 1 193 180 Hz). Supporte le mode one-shot ou le mode priodique (pas les deux la fois).

b- SMP scheduler : pour Symmetric Multi Processor (rpertoire smpscheduler). Ddi aux machines multi-processeurs. Supporte les Timers 8254 et APIC. Supporte le mode one-shot ou le mode priodique (pas les deux la fois). La fonction : rt_set_runnable_on_cpus affecte une tche un ensemble de CPUs. La fonction : rt_set_runnable_on_cpuid affecte une tche un processeur prcis.

c- MUP scheduler : pour Multi-Uniprocessor (dans le rpertoire mupscheduler) Ddi uniquement aux machines multi-processeurs. Supporte le mode one-shot et le mode priodique.

2 Exemples de systmes et plates-formes temps rel

39

2.1.4.2.

Inter-Process Communications (IPCs) :

Le terme en anglais Inter-Process Communications (IPCs), dcrit les diffrents mcanismes de synchronisation et de communication entre processus. Linux fournit le standard Systme V IPC pour le partage de mmoire, FIFOs, smaphores, tubes (Pipes), qui peuvent tre utiliss par les processus utilisateurs de Linux, pour le transfert et le partage de donnes. Bien que ces mcanismes ne soient pas disponibles pour les tches temps rel, RTAI fournit un ensemble de mcanismes IPCs, qui peuvent tre utiliss pour transfrer et/ou partager des donnes entre tches et processus, dans les domaines temps rel et lespace utilisateur Linux. Ces mcanismes regroupent dans le RTAI natif [RPG]: - FIFOs temps rel : (First In First Out) est un buffer en lecture/criture, utilis pour le transfert de donnes asynchrones entre les tches temps rel et les processus Linux, ce buffer est ouvert en criture par un processus et en lecture par un autre. - Mmoire partage : fournit un moyen de transfert de donnes dune traite entre le domaine temps rel et lespace utilisateur Linux, travers lequel, une portion de mmoire physique est rserve pour la sentre partager. - Mailboxes : fournit une capacit de transfert de donnes de tailles dfinis par lutilisateur, entre Linux et RTAI. Il est suppos quun format de protocole de messages soit impos au niveau de lapplication. - Smaphores : sont utiliss pour la synchronisation entre tches ou partage de ressources communes. - RPCs (Remote Procedure Calls) : similaire au cas de QNX. Les RPCs transferts un entier non sign ou un pointeur la tche(s) destinataire(s).

2 Exemples de systmes et plates-formes temps rel

40

Pour les IPCs fournis par le module POSIX, on citera [RPG]: - Mutexes : la variable mutex agit comme un verrou dexclusion mutuelle, pour permettre aux threads, le contrle daccs aux donnes. Ceci garantit quune seule thread la fois peut agir sur la donne protge.

- Variables conditionnelles : une variable condition offre un moyen pour nommer un vnement. Ce dernier peut tre vu comme simple conteur avec une valeur limite atteindre, une valeur particulire, ou mme une variable de type flag (set/clear) ; ou plus encore, il peut tre vu comme une concidence, impliquant de multiples vnements. La thread est fortement concerne par ces vnements, car la rencontre dun certain deux, permet la thread de modifier son excution courante vers une phase ou un traitement particulier, suivant la nature de lvnement. La librairie Pthread fournie avec POSIX permet, justement dune part la thread dexprimer son intrt un vnement particulier, et dautre part, de signaler aux threads quun vnement est rencontr.

- La file de messages : POSIX offre une forme dabstraction gnrale de communication entre tches temps rel. La queue de messages, offre la possibilit aux messages de diffrentes tailles dtre insrs ou placs en elle, tout en grant leur rangement suivant leur priorit.

2.1.4.2.1. FIFOs temps rel : Pour une FIFO native RTAI, les suivantes caractristiques sont donnes : Ressemble au mcanisme de tube (pipe). Peut servir la communication entre tches temps rel, entre processus ou encore entre tches temps rel et processus Linux. Peut se crer dans lespace utilisateur ou lespace noyau. Peut tre cre en lui associant un nom. Sa taille peut tre modifie aprs la cration de la FIFO. Supporte plusieurs lecteurs/crivains. Supporte les smaphores pour la synchronisation. Correspond aux supports /dev/rtf0..63 dans le systme de fichiers.

2 Exemples de systmes et plates-formes temps rel

41

Implmentation : Voici prsent, quelques principaux prototypes de fonctions, qui servent manipuler la FIFO (en incluant le fichier rtai_fifos.h dans le module dapplication) :

- Cration dune FIFO : int fd = rtf_open_sized(const char *dev, perm, size) ; - Pour dtruire une FIFO : int rtf_destroy (unsigned int fifo); - Changement de taille dune FIFO dans lespace utilisateur : rtf_resize(int fd, int new_size) - A partir de Linux, la cration se fait : $mknod /dev/rtfX c Y X o: X est le numro infrieur du priphrique (allant de 0 63). c impilque que la FIFO est un priphrique de type caractre. Y est le numro suprieur. Exemple : $mknod /dev/rtf1 c 63 1 (excute partir dun shell Linux). Puis, dans le programme C utilisateur, on peut ouvrir la FIFO et la manipuler : fifo_id = Open(/dev/rtf1, O_READONLY);

2.1.4.2.2. Le partage de mmoire [RPG]:

Les donnes crites ne sont pas mises en queue. Ceci implique un accs direct et non squentiel aux structures de donnes de tailles diffrentes. La mmoire partage peut tre crite ou lue par nimporte quel nombre de processus Linux ou de tches temps rel.

2 Exemples de systmes et plates-formes temps rel

42

Le blocage pour synchronisation nest pas directement support ; un compteur devrait alors tre associ chaque donne pour sassurer de sa bonne mise jour. Lexclusion mutuelle nest pas garantie entre lenvironnement temps rel, et ce, de Linux. Linterruption des lecteurs/crivains nest pas dtecte, il est alors recommand dadopter un mcanisme de protection comme Mutexes ou similaire.

Implmentation : Crer le priphrique de mmoire partage. Ce dernier reste dans le systme, et nous naurons pas le recrer, lors dune prochaine utilisation. Il est implment sous forme dun vritable priphrique. Mais pour une utilisation particulire dadresse mappe on peut utiliser la fonction : adr = rtai_malloc_adr( start_ address, name, size) ; Pour ce faire, on suit les tapes suivantes : Compiler et charger le module rtai_shm $cd <rtai>/shmem $make $insmod rtai_shm De mme, compiler et charger le module dapplication. La cration du priphrique est prise en compte dans le fichier Make (le priphrique est /dev/rtai_shm).

- Pour pouvoir utiliser la mmoire partage partir de lespace utilisateur : adr = rtai_malloc(name, size); o : name : identifiant du bloc (il est de type long non sign). size : est la taille en octets du bloc de mmoire partage (4096 est la valeur par dfaut). adr : est le pointeur renvoy vers la base du bloc cr.

2 Exemples de systmes et plates-formes temps rel

43

- La libration se fait par le biais de la fonction :

rtai_free(name, adr);

- Pour pouvoir utiliser la mmoire partage dans lespace noyau : adr = rtai_kmalloc(name, size); - Pour la libration : rtai_kfree(name);

2.1.4.2.3. Mailboxes (Boite aux lettres) [RPG] Le mailbox est flexible, et possde les caractristiques suivantes : Il peut tre explicitement install, pour prendre en charge des messages de tailles personnalises. Plusieurs metteurs/rcepteurs peuvent se connecter la fois au mailbox, o lordre dans lequel les messages sont pris dpend, de la priorit des rcepteurs. Lorsquun long message devrait tre envoy, le service mailbox offre des fonctions qui permettent au processus denvoyer seulement une partie du message en lui retournant le nombre doctets non envoys du message ou bien, continuer envoyer le message jusqu ce que celui-ci soit accept.

Les mailboxes peuvent remplacer les FIFOs, cependant le nombre dappels la fonction memcpy va doubler, et rendra inefficace la communication, bien que a soit acceptable pour les messages courts. Implmentation : Les services du mailbox sont offerts par RTAI scheduler. Pour pouvoir les utiliser, il faudrait inclure le fichier rtai_sched.h lors de lcriture du module dapplication. Le mailbox est cr et initialis, par le biais de la fonction : result = rt_mbx_init(MBX *mbx, size) ; o : mbx : pointeur vers une la structure de donnes mailbox (dclare dans rtai_sched.h). size : taille du mailbox utiliser, choisie en fonction de la taille des messages envoyer. result : devrait tre nul, sinon il y a erreur de cration du mailbox.

2 Exemples de systmes et plates-formes temps rel

44

- Pour supprimer le mailbox : result = rt_mbx_delete(MBX *mbx) ; - Pour envoyer un message dune faon inconditionnelle (retourner une fois le message en entier a t envoy ou bien, une erreur est survenue) : int msg_size) ; rt_mbx_send(MBX *mbx, void *msg, int

- Pour recevoir un message dune manire inconditionnelle : int rt_mbx_receive(MBX *mbx, void *msg, int msg_size) ;

2.1.4.2.4. Messages RTAI et RPCs [RPG] RTAI offre une facilit de communication de messages inter-tches, par laquelle, une valeur de 32-bit peut tre passe entre les tches temps rel. Remote Procedure Calls (RPCs) fait de mme, mais les tches sont dans ce cas couples en attente dune rponse du receveur. Implmentation : Les messages RTAI ainsi que RPCs, sont implants au niveau du fichier rtai_sched.c, il faudrait alors inclure dans le module dapplication le fichier rtai_sched.h chaque rfrence aux fonctions associes. - pour faire un appel distant inconditionnel : rt_rpc(RT_TASK *task, unsigned int msg, unsigned int *reply); La fonction rt_rpc envoie un message la tche task, et se met en attente dune rponse reply. La tche appelante est alors bloque et mise en file dattente. La tche task rcupre le message par le biais de la fonction rt_receive (faisant partie de la liste des messges RTAI), ralise le traitement le cas chant, puis se termine en lguant en quelque sorte le contrle la fonction appelante, en invoquant la fonction : rt_return(). La fonction appelante est rveille, et retrouve la rponse pointe par reply.

2 Exemples de systmes et plates-formes temps rel

45

2.1.5. Les modules sous Linux Un module noyau Linux est une portion de code qui, lorsquelle est charge, elle devient partie intgrante du noyau Linux ayant accs au mme espace mmoire. Une tche temps rel sexcutant comme un module noyau consiste en trois parties : La fonction init_module() Code spcifique de la tche (API RTAI ou POSIX) La fonction cleanup_module()

Init_module() : - un module noyau doit toujours contenir une fonction init_module - init_module() est invoqu par la commande insmod - init_module() contient des allocations de ressources, la dclaration et le dmarrage de tches.

Cleanup_module() : - Cette entre est invoque lorsque le module est supprim - cleanup_module() est invoqu par la commande rmmod - cest lendroit idal pour la libration des ressources, larrt et la suppression des tches

2 Exemples de systmes et plates-formes temps rel

46

2.1.6. Exemple Nous allons donner un exemple, travers lequel, nous illustrons la manire de procder pour crer un module dapplication temps rel avec RTAI (en langage C), sa compilation, son chargement, tout en dtaillant son code.

// Fichier tache.c #include <linux/module.h> #include <asm/io.h> #include <rtai.h> #include <rtai_sched.h> #define #define #define #define TICK_PERIOD 10000000 STACK_SIZE 2000 LOOPS 1000000000 NTASKS 2

static RT_TASK tache[NTASKS]; static RTIME tick_period; static void Thread(int t) { unsigned int loops = LOOPS; while(loops--) { rt_printk("TASK %d %d\n", t, tache[t].priority); rt_busy_sleep(500000); rt_task_wait_period(); } }

2 Exemples de systmes et plates-formes temps rel

47

int init_module(void) { RTIME now; int i; for (i = 0; i < NTASKS; i++) { rt_task_init(&tache[i], Thread, i, STACK_SIZE, NTASKS - i - 1, 0, 0); } tick_period = start_rt_timer(nano2count(TICK_PERIOD)); now = rt_get_time() + NTASKS*tick_period; for (i = 0; i < NTASKS; i++) { rt_task_make_periodic(&tache[NTASKS - i - 1], now, NTASKS*tick_period); } return 0; } void cleanup_module(void) { int i; stop_rt_timer(); for (i = 0; i < NTASKS; i++) { rt_task_delete(&tache[i]); } }

Commenons par analyser le code : Les fichiers dentte, servent compiler le fichier tache.c, que nous avons crit. #include <linux/module.h> est ncessaire pour pouvoir crer un module noyau. #include <asm/io.h> contient des dfinitions dIN/OUT du x86 dIntel.

2 Exemples de systmes et plates-formes temps rel

48

#include <rtai.h> et #include <rtai_sched.h> dfinitions ou les prototypes de fonctions RTAI temps rel utiliser.

contiennent des

static RT_TASK tache[NTASKS] ; dclare un tableau static de deux tches. RT_TASK est de type : struct tache * (dfinit dans rtai.h). static RTIME tick_period ; RTIME est de type : long long Traitons en premier lieu la fonction, init_module(void), qui sera dailleurs la premire tre excute (la commande : insmod va linvoquer en premier, cest en quelque sorte la fonction main() habituelle). Elle commence alors par crer deux tches en invoquant la fonction : rt_task_init, dont le prototype est le suivant :
int rt_task_init( RT_TASK *task, // contexte de la tche void (*rt_thread)(int), //la thread int data, //paramtres la thread int stack_size, //la taille de la zone de pile int priority, int uses_fpu, void(*signal)(void) );

et ladresse de la fonction thread crite plus haut est donne, comme paramtre. Puisque nous navons pas dfini ou dclar le mode one_shot, le timer 8254 sera alors utilis. La fonction : start_rt_timer, active le timer, en lui passant comme paramtre le nombre de top dhorloge (en anglais tick), signifiant la priode. Ceci aprs avoir converti ces tops, en une valeur, relative la cadence de lhorloge considre (dans ce cas, il sagit du timer 8254) par le biais de la fonction : nano2count. La fonction rt_get_time() renvoie, le temps absolu en unit interne, coul depuis lactivation du timer. La fonction rt_task_make_periodic initialise les tches prcdemment cres, en les dclarant comme priodiques, et dont la date de rveil fixe linstant courant. En invoquant rt_printk, la fonction thread affiche un message, la valeur du paramtre t pass en argument par la fonction rt_task_init lors de la cration de la tche, et, la priorit de la tche. Une fois ceci fait, la tche se bloque pendant 500s, en sollicitant pour cela, la fonction : rt_busy_sleep(int nanosecs), cette dernire bloque la tche pour une priode donne en paramtre, et ne lgue pas pendent ce temps l, le contrle au scheduler (la tche nest pas prempte). Aprs quoi, la tche attend une priode (10 ms), mais peut tre dans ce cas prempte. Ce scnario est rpt par les deux thread en concurrence, tant que le compteur LOOP ne sest pas puis.

2 Exemples de systmes et plates-formes temps rel

49

La compilation : Pour compiler le module, nous pouvons soit, directement procder la compilation, ce qui savre fastidieux si une erreur de frappe survienne, ou que nous aurons recompiler nouveau le module. Pour cela, il est prfrable de crer un fichier Makefile dans lequel nous crirons, les commandes une seule fois. Un exemple du fichier Makefile est le suivant :

all: tache.o CC=gcc RTAISRC=/root/Downloads/kernel/rtai-24.1.13 KERNELSRC = /lib/modules/$(shell uname -r)/build

CFLAGS= -I$(RTAISRC)/include -I. -D__KERNEL__ -I$(KERNELSRC)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE tache.o: tache.c gcc $(CFLAGS) -c -o $@ $< clean: rm -f tache.o

Une fois ce fichier cr, il suffit alors dexcuter la commande : make Ceci va compiler le source nomm tache.c et dlivrera en sortie le module tache.o

Le chargement : Avant de charger le module tache.o cr, nous devons au pralable, charger les modules RTAI (rtai.o et rtai_sched.o), pour cela on excute les commandes suivantes :

2 Exemples de systmes et plates-formes temps rel

50

$cd ./<path rtai> $make $insmod rtai $cd ./<path rtai>/<path rtaisched> $make $insmod rtai_sched $cd ./<path exemple> $make $insmod tache

Le dchargement : Pour dcharger le module tache.o il suffit dexcuter : $rmmod tache Ceci va excuter la fonction : cleanup_module() crite dans le fichier : tache.c Si nous lanalysons, nous constaterions quelle fait appel la fonction : stop_rt_timer(), qui stop le timer, puis deux appels la fonction rt_task_delete sont effectus, pour dtruire les deux tches cres.

2 Exemples de systmes et plates-formes temps rel

51

2.2.

VxWorks

2.2.1. Historique VxWorks est aujourd'hui l'excutif temps rel le plus utilis dans l'industrie. Il est 1 dvelopp par la socit Wind River qui a galement rachet rcemment les droits du noyau temps rel PSOS, un peu ancien mais largement utilis. VxWorks est fiable, faible empreinte mmoire, totalement configurable et port sur un nombre important de processeurs (PowerPC, 68K, CPU32, ColdFire, MCORE, 80x86, Pentium, i960, ARM, StrongARM, MIPS, SH, SPARC, NECV8xx, M32 R/D, RAD6000, ST 20, TriCore). Un point fort de VxWorks a t le support rseau (sockets, NFS, RPC...) disponible ds 1989 aux dveloppeurs, bien avant tous ses concurrents. VxWorks est galement conforme POSIX 1003.1b. 2.2.2. Prsentation gnrale [DP 91] Lapproche propose par lexcutif VxWorks de Wind River Systems, est ne de deux constations : - la premire est quUnix, riche dutilitaires, de possibilits rseaux et de convivialit de dveloppement nest pas en mesure doffrir des outils adapts au temps rel et en consquence de rpondre des performances temps rel ; - la deuxime, est que larchitecture fortement optimise des systmes dexploitation temps rel (tel OS9, par exemple ) ne facilite pas forcement leur utilisation en tant que plateforme de dveloppement. VxWorks est donc au sens strict un excutif temps rel, spcialement conu pour le dveloppement en environnement Unix. La figure 2.2. prsente larchitecture globale de cet excutif, avec les fonctionnalits spcifiquement temps rel et les modules dextension propres lenvironnement Unix. Tout comme beaucoup dautres excutifs de ce type, Unix est vu tel un ensemble logiciel de haut niveau pour le dveloppement des applications, excutes et mises au point sous VxWorks. Le noyau de ce dernier offre des primitives de base de gestion de processus et de smaphores sur lesquelles sont construites les fonctions systme accessible par lintermdiaire du systme dexploitation.

1. http://www.windriver.com

2 Exemples de systmes et plates-formes temps rel

52

Loging

Entres/Sorties Formates (Unix)

Dsassembleur Symbolique

Chargeur (Unix)

Remote login

NFS RPC

Sockets

Debugger symbolique

Systme Systme Smaphores Support de fichiers dE/S coprocesseur

Table de Gestion Gestion Gestion Gestion Symboles mmoire rseau du des systme multitche ITs

Libraires
NOYAU TEMPS REEL

Figure 2.2. Architecture globale de lexcutif VxWorks

2.2.3. caractristiques temps rel [DP 91] Lordonnancement des tches est base sur le principe de priorit (256 niveaux possibles) avec premption. Pour des tches de priorits identiques, cest la technique du round-robin qui est mise en uvre. Le temps de commutation de contexte est indpendant du nombre de tches installes dans le systme ; titre indicatif, sur un 68020 25 Mhz, il est de 17s La synchronisation est assure par signaux, les fonctionnalits tat base sur les primitives de gestion de smaphores. VxWorks supporte trois types de smaphores : - les smaphores boolens, - les smaphores compte, - les smaphores priorit. Ces derniers permettent de contourner leffet subversif des priorits relatives aux tches. En effet, une tche de faible priorit sera susceptible dhriter momentanment de la priorit de la tche de plus forte priorit en attente sur le smaphore. Les trois types de smaphores acceptent des attentes avec time-out et autorisent le chanage des processus dans les files de type FIFO ou priorit. Du point de vue de la communication, lexcutif intgre des outils btis partir des primitives de gestion de smaphores. On dispose de : - files de messages, de type FIFO, de longueur variable et accessibles partir de tout processus utilisateur ou systme, y compris une routine de service dinterruption ; - tubes de communication (pipe), faisant office dinterface entre un processus et une file de message avec lavantage dutiliser des services dentres/sorties indpendants du matriel (fonctions de gestion de priphriques virtuels).

2 Exemples de systmes et plates-formes temps rel

53

Lors de larrive dune interruption, une routine ISR (Interrupt Service Routine) est invoque, lexcutif nintervenant pratiquement pas entre larrive du phnomne dinterruption et lexcution de la routine ISR. Les routines ISR peuvent si besoin est, envoyer des signaux, manipuler des smaphores, des files de messages ou de pipes. Par ailleurs, VxWorks dispose de fonctionnalits autorisant la manipulation des vecteurs dinterruption directement en langage de haut niveau tel que le langage C ainsi que lassociation dune routine crite en C une source dinterruption matrielle. A propos du masquage des interruptions et de la premption, VxWorks minimise les temps de fonctionnement en mode systme, mode dans lequel gnralement tout excutif est non premptible (et au pire, non interruptible) pour assurer lintgrit de manipulation des ressources du noyau (files internes, pointeurs, etc.) de telle sorte que le temps de latence en interruption se rduit 8s. Le fonctionnement en mode systme ne concerne que les manipulations vitales de gestion du multitche et les oprations de base de synchronisation. Tout ce qui concerne les fonctionnalits de communication, de gestion mmoire, de gestion multiprocesseur (par rseaux) est essentiellement excut en mode utilisateur (cest dire dans le contexte du processus concern), donc premptible. Le tableau 2.1. rsume les performances temporelles de VxWorks pour un processeur 68020 25Mhz. Outre les caractristiques prcites, VxWorks intgre une agence de gestion du temps incluant des watchdog, des timer de dlai sur processus, des possibilits de time-out sur oprations du noyau, etc. De mme, lexcutif dispose dune agence de gestion mmoire supportant les fonctions dallocation compatibles C ANSI et Unix.

Commutation de contexte Commutation de tches Oprations sur smaphores (P et V) Latence la premption Latence en interruption

17s 35s 8s 11s 8s

Tableau 2.1. Performance de VxWorks

2 Exemples de systmes et plates-formes temps rel

54

2.2.4. Linterface avec Unix [DP 91] Lune des caractristiques de VxWorks est de sintgrer pleinement dans un environnement de dveloppement de type Unix, et de faire partie de cette nouvelle gnration dexcutifs bass sur ce quasi standard de dveloppement. Qui dit environnement Unix, sous-entend gnralement une machine cible, une machine hte et un rseau , donc le support de toute une srie dutilitaires standard de communication par rseau. La figure 2.3. prsente les diffrents utilitaires de communication rseaux supports par VxWorks.

DRIVER RESEAU

NFS

Debugger source

rlogin

telnet

rsh

ftp

RPC

SOCKETS TCP / UDP IP

ETHERNET

BUS SYSTEME

LIGNE SERIE

INTERFACE UTILISATEUR

Figure 2.3. Lenvironnement de communication de VxWorks

2 Exemples de systmes et plates-formes temps rel

55

On distingue les librairies de communication (sockets) compatibles Unix BSD 4.3, les protocoles de transmission TCP, IP, UDP, le protocole de session RPC, le protocole de transfert de fichiers NFS et les process applicatifs telnet, ftp, rlogin et rsh. Les sockets sont des primitives de communication la base du dveloppement dutilitaires rseau ou dapplication. VxWorks supporte des connexions en mode datagramme (par lintermdiaire de UDP/IP) et en mode connect (grce TCP/IP), ce dernier mode autorisant un contrle de bout en bout du flot de donnes transmis. Le protocole RPC (Remote Procedure Call) assure lappel par les tches VxWorks ou les processus Unix de routines excutes indiffremment par la machine cible (VxWorks) ou hte (Unix). Enfin, signalons brivement les rles respectifs des divers process supports : - rsh : remote shell, permet aux processus applicatifs sous VxWorks daccder par rseau aux commandes Unix ; -ftp : file transfert protocol, autorise laccs partir du systme VxWorks aux fichiers du systme Unix et inversement ; - telnet assure la connexion au shell VxWorks partir de la machine Unix, de mme que rlogin assure aux utilisateurs de la cible (VxWorks) une connexion au shell de la machine hte (Unix). 2.2.5. Environnement de compilation et dexcution [SETR] 2.2.5.1. Chargeur

Lobjectif du chargeur dans lenvironnement VxWorks est de pouvoir lancer lexcutif et/ou les applications. Lors du dmarrage de VxWorks (systme cible), le processus damorce ou de boot, suit les oprations suivantes : Lancement du chargeur la mise sous tension (EEPROM). Chargeur et hte (Unix) communiquent par lien srie. Modification ventuelle des paramtres de boot. Configuration sur la cible (VxWorks) dune interface Ethernet. Chargement par ftp ou rsh de limage. Dmarrage de lexcutif et des tches VxWorks. Montage NFS du rpertoire utilisateur.

Les paramtres de boot peuvent tre les suivants : Adresse IP de lhte (station Unix) et de la cible (VxWorks). Localisation de limage constituant lexcutif. Nom de lutilisateur. Protocole utiliser pour le chargement.

2 Exemples de systmes et plates-formes temps rel

56

Les paramtres gnralement modifis par lutilisateur sont, le nom de lutilisateur, le fichier image et le protocole de transfert. Nous donnons dans ce qui suit quelques commandes du chargeur : Exemple : 1. A partir de lhte (exemple : Sun), on se connecte la cible (VxWorks sur processeur Motorola 68030) par une liaison srie. 2. Affichage et modification ventuelle des paramtres linvite de boot : [VxWorks Boot] : p boot device : ei processor number : 0 host name : SUNKabylie file name : : /exemple/VxWorks/bootimage inet on ethernet (e) : 192.12.11.12 host inet (h) : 192.12.11.1 user (u) : toufik ftp password (pw) (blank = use rsh) : flags (f) : 0x0 target name (tn) : VxTiziOuzou 3. Chargement de lexcutif : [VxWorks Boot] : @ -> CRTL+X : redmarrage de la carte. @ : chargement et lancement de lexcutif. c : modification des paramtres de chargement. p : affichage des paramtres de chargement. ? : aide en ligne.

2.2.5.2.

Compilation croise

Nous pouvons compiler les fichiers dapplication de VxWorks sur la station Sun de lexemple prcdent. Pour cela, il suffit davoir un compilateur crois (supportant galement le jeu dinstruction de Motorola 68030 exemple : cc68k). Bien videmment, le binaire produit, ne sexcutera pas sur la station Sun mais destin lenvironnement VxWorks. De plus, il n y aura pas ddition de liens, celle-ci se fera dynamiquement, lors du chargement du module objet dans la machine cible (sous VxWorks).

2 Exemples de systmes et plates-formes temps rel

57

Exemple : Soit lexemple de programme trivial (bonjour.c) : #include <vxWorks.h> #include <stdio.h> #include <taskLib.h> mafonction() { int id=taskIdSelf(); printf(Bonjour le monde, nom tache :%s. id tache =%x\n,taskName(id),id) ; } N.B : il n y a pas de fonction main (). La compilation sur lhte (pas ddition de liens) : SUNKabylie$cc68k g c bonjour.c DCPU=MC68030

2.2.5.3.

Le shell VxWorks

Puisque labstraction faite dans les excutifs temps rel, est de considrer toute unit dexcution comme tant une tche, le shell est alors vu comme telle, et constitue linterface entre lexcutif et lutilisateur. Les services offerts par un shell VxWorks : Chargement de code et de donnes. Edition des liens. Mise au point (niveau assembleur). Consultation et modification des ressources VxWorks (ex : tches). Gestion de symbole des modules. Services classiques offerts par un shell : variables, redirection dE/S, appel de fonction, etc.

Quelques commandes du shell VxWorks : ls, ll, cd, pwd. Commandes de parcourt du rpertoire utilisateur. ld. Chargement dun module et dition des liens. ModuleShow. Affiche la liste des modules. sp, td, ts, tr, repeat. Oprations sur les tches : cration, suppression, etc. i, ti, checkStack, pc, printErrno. Information sur les tches. help. Aide en ligne.

2 Exemples de systmes et plates-formes temps rel

58

Exemple : Ainsi, pour charger le module cr dans lexemple prcdent, il suffit de se placer dans le rpertoire o se trouve le module. ->cd nom_rpertoire Puis de charger le module : ->ld < bonjour.o Et on pourra excuter le module de deux manires : - soit lexcuter par appel de fonction. - Soit par la cration dune tche. 1re possibilit : ->mafonction() Bonjour le monde, nom tache : cshell. id tache =0x3a8460 2me possibilit : ->sp mafonction task spawned: id = 0x3a5bc0, name = t1 Bonjour le monde, nom tache : t1. id tache =0x3a8460

2.2.6. API VxWorks VxWorks est trs utilis dans les systmes embarqus. A cet effet, il dispose dun seul espace dadressage. Ainsi, les appels au systme ne sont que des appels de fonctions, mais ceci nempche pas le fait que VxWorks soit muni dune API complte, et facilite aux concepteurs dapplications, le dveloppement rapide de leurs programmes, en leur vitant lembrouillement et la prise en compte des spcificits du code noyau. Autrement dit, lutilisateur a comme impression quil dveloppe dans un espace propre lui, sans trop tenir compte des variables noyau (le fait contraire est vu dans Linux temps rel). On se propose de prsenter en bref, les principaux services que fournit lexcutif VxWorks. Les services comme : gestion des tches, gestion du temps, les smaphores, les interruptions, la mmoire et la communication par messages.

2 Exemples de systmes et plates-formes temps rel

59

2.2.6.1.

Gestion des tches

Pour manipuler lentit tche dans un programme C, il faudrait inclure le fichier entte contenant les dfinitions et les prototypes de fonctions de gestion des tches, ceci par le biais du fichier: #include <tasklib.h> - cration dune tche : TASK_ID tId = taskSpawn(char *nom, unsigned char priorit_e, unsigned flags, unsigned taille_pile, VOID_FUNCPTR fonction, void arg1,...);

- suspension /reprise dune tche : STATUS taskSuspend(TASK ID tId); STATUS taskResume(TASK ID tId); - verrouillage et dverrouillage dune tche : STATUS taskLock(); STATUS taskUnLock(); - destruction dune tche : STATUS taskDelete(TASK ID tId);

2.2.6.2.

Gestion du temps

Une multitude de fonctions est offerte pour lutilisateur, en vue de subvenir aux besoins temps rel dans les applications concevoir, nous en citerons que quelques-unes delles. - Pour bloquer une tche pendant une certain nombre de top dhorloge : STATUS TaskDelay(int nb_tick) ; - Pour positionner/consulter le nombre de top dhorloge, depuis linitialisation : STATUS Tickset(ULONG tick) ; ULONG Tickget(void) ;

2 Exemples de systmes et plates-formes temps rel

60

- Pour modifier ou consulter la frquence dhorloge du systme : STATUS SysClkRateSet(ULONG frq) ; ULONG SysClkRateGet(void) ; - Pour crer/activer (excuter une fonction un chien de garde) : int wd=wdCreate() ; wdStart(int wd,int delai,(FUNCPTR)function,param_fonction) ;

2.2.6.3.

Les smaphores

#include <semLib.h> - Pour crer un smaphore boolen / compte / mutex, initialis une valeur val : SEM_ID semBCreate(unsigned options, unsigned val); SEM_ID semCCreate(unsigned options, unsigned val); SEM_ID semMCreate(unsigned val); Telle que : options = {SEM_Q_PRIORITY, SEM_Q_FIFO} - Pour la prise / libration dun smaphore : STATUS semTake(SEM_ID semId, int timeout); STATUS semGive(SEM_ID semId); - Pour la destruction dun smaphore : STATUS semDelete(SEM_ID semId);

2.2.6.4.

Manipulation des interruptions

VxWorks gre jusqu 256 niveaux dinterruption, et permet leur manipulation en donnant la possibilit aux programmeurs dapplications, dassocier une routine dinterruption une fonction C, quils programment. #include <intLib.h> - Pour connecter une routine une interruption : STATUS intConnect(int vecNum,VOID FUNCPTR funcPtr);

2 Exemples de systmes et plates-formes temps rel

61

- Pour positionner le masque dune interruption : STATUS intLevelSet(int level); - Pour bloquer / dbloquer les interruptions : STATUS intLock(); STATUS intUnLock();

2.2.6.5.

Gestion de la mmoire

Rappelons le, toutes les tches possdent un seul espace dadressage, les suivantes fonctions travaillent alors toutes dans le mme espace dadressage (du noyau). #include <memLib.h> - Pour allouer / librer un bloc de mmoire : void *ptr = malloc(unsigned taille); void free(void *ptr); - Pour afficher la mmoire disponible : void memShow(BOOL flag);

2.2.6.6.

Communication par messages

#include <msgQLib.h> - Pour crer une file de messages : MS_Q_ID msgQCreate(int maxMsg, int msgLen,int options); - Pour envoyer / recevoir un message : STATUS msgQSend(MSG Q ID msgQ, void *message, int longueur); STATUS msqRReceive(MSG Q ID msgQ, void *buffer,int maxlen, int timeout);

2 Exemples de systmes et plates-formes temps rel

62

2.3. CLEOPATRE Cest un atelier de dveloppement et de vrification dune bibliothque de Composants Logiciels sur Etagres Ouverts Pour les Applications Temps-Rel Embarques. Projet dvelopp en France, et impliquant plusieurs organismes franais (Institut de Recherche en Informatique de Nantes, Universit de Paris Nord, Laboratoire de Robotique de Paris rattach au CNRS, ROBOSOFT SA, Institut Universitaire de Technologie de Nantes, et le CEA : Service Robotique et Systmes intgrs).

2.3.1. Objectifs [CLEO] Les produits industriels intgrent de plus en plus de logiciels. Ces logiciels, dits enfouis, peuvent influer trs fortement sur la comptitivit du produit final de par les rductions de cot de dveloppement et leurs innovations. Leur qualit principale rside dans leur aptitude supporter, la demande, une volution rapide, facile, peu onreuse, et ce, tout en garantissant une qualit de service prdfinie. Le dveloppement reste, en effet, un aspect souvent mal matris, notamment par mconnaissance des concepts temps-rel. Ce projet apporte des solutions au dveloppement dapplications temps-rel embarques par la mise disposition aprs vrification, de composants logiciels libres et ouverts sappuyant sur Linux. Linux Temps-Rel constitue un standard quil est opportun de faire voluer pour sadapter aux exigences des nouveaux systmes embarqus. Cette volution passe par le transfert des comptences universitaires en matire dinformatique temps-rel (ordonnancement, tolrance aux fautes, gestion de ressources,) et lapport de rponses aux besoins dapplications industrielles de plus en plus complexes. 2.3.2. Organisation du projet [CLEO] Le projet CLEOPATRE, de type exploratoire est organis en sept sous-projets : Les cinq premiers sont la spcification et le dveloppement des composants appartenant quatre tagres (Ordonnancement, Tolrance aux fautes, Mcanismes de synchronisation, Serveurs de tches apriodiques). (Voir figure 2.4.) . Dans le sixime sous-projet, on exprimentera, sur une application relle de robotique mobile, ladquation de Linux temps-rel muni de son noyau configurable et de sa librairie dutilitaires, vis vis des exigences des dveloppeurs. Le dernier sous-projet se chargera de la documentation et de la dissmination via Internet notamment par la cration dun site. Il effectuera une tude de march, tablira un plan de commercialisation dans laquelle il pourra ultrieurement assurer le support technique auprs des utilisateurs finaux

2 Exemples de systmes et plates-formes temps rel

63

Figure 2.4. Les quatre premires tagres de CLEOPATRE

2.3.3. Dmonstrateur [CLEO] Un robot mobile autonome comme dmonstrateur permet de concevoir une multitude de scnarios pour tester et certifier ces composants tant du point de vue de la sret de fonctionnement (fiabilit, scurit) que du respect des contraintes temporelles. Lintgration de composants ddis au traitement temps-rel et conformes au standard Linux dans une plate-forme constitue une avance certaine. Celle-ci est destine non seulement tester les composants et leur interoprabilit mais aussi dmontrer la comptitivit et ladaptativit de Linux temps-rel en vue de son industrialisation.

2.3.4. Perspectives de march [CLEO] CLEOPATRE souhaite, fournir une gamme de composants suffisamment tendue pour toucher un panel le plus large possible de secteurs dapplications, allant des applications les plus critiques, en gnral caractre fortement cyclique (industrie militaire, avionique) aux applications les moins critiques ( multimdia, vido la demande) en passant par des applications o cohabitent des contraintes degr de criticit chelonns (robotique mobile avec tl-opration via Internet). Les perspectives actuelles de ce march sont donc grandes, aussi bien dans les secteurs de haute technologie quau niveau des produits grand public. Ne pas oublier lintrt pdagogique de ces logiciels dans lenseignement universitaire.

2 Exemples de systmes et plates-formes temps rel

64

2.4.

BOSSA

1 2

Dvelopp l Ecole des Mines de Nantes , BOSSA est une plate-forme ajoute au noyau Linux pour le dveloppement dordonnanceurs de processus. 2.4.1. Objectifs L'objectif de BOSSA est de simplifier la conception d'ordonnanceurs de sorte qu'un programmeur d'application puisse dvelopper des politiques d'ordonnancement spcifiques sans tre expert des systmes d'exploitation. Pour ce faire, BOSSA offre les avantages suivants : Simplifier limplmentation dun scheduler : BOSSA inclut un domaine de langage ddi (DSL : Domain-Specific Language), offrant un niveau dabstraction plus lev qui permet lvolution et limplmentation de nouvelles politiques dordonnancement. Un compilateur ddi vrifie le code DSL de BOSSA pour une compatibilit avec lOS cible, et le translate en code C. Intgration simplifie du scheduler : Une politique d'ordonnancement BOSSA est implante comme un module qui reoit les changements d'tat des processus sous la forme d'vnements pour utiliser cette information et prendre des dcisions d'ordonnancement. Scurit : La scurit est garantie tant au niveau de limplmentation de la nouvelle politique quau niveau langage DSL, tant donn que ce dernier ne gnre pas de pointeurs ni de boucles infinies.

2.4.2. Les composants BOSSA Pratiquement, le noyau BOSSA comprend trois parties : Un noyau standard, dans lequel les politiques dordonnancement sont remplaces par des vnements pris en compte par BOSSA. La politique dordonnancement crite par le programmeur contient, des routines grant les vnements possibles de BOSSA. La politique est soit crite en C directement, ou bien en DSL, et translat dans ce cas en C, par un compilateur ddi. Un OS indpendant, qui gre linteraction entre le reste du noyau et la politique dordonnancement.

1.BOSSA est soutenu en partie par France Telecom, Micro$oft, et le Conseil de Recherche Danois. 2. http://www.emn.fr/x-info/bossa

2 Exemples de systmes et plates-formes temps rel

65

2.4.3. Du noyau Linux BOSSA [RTS 05] Prparer un noyau pour qu'il soit utilisable avec BOSSA ncessite l'insertion des vnements cits plus haut des points particuliers du noyau, appels points d'ordonnancement. L'volution du noyau Linux pour supporter BOSSA est assez complexe, pour diverses raisons. D'abord, BOSSA doit tre utilisable avec n'importe quelle version de Linux. Une solution base sur les patches serait insuffisante car les numros de ligne correspondant aux points d'ordonnancement ainsi que le code entourant ces points diffrent d'une version de Linux une autre. De plus, certains changements ncessaires pour supporter BOSSA dpendent des proprits de flux de contrle. Sans compter le fait que toute modification effectue la main sur plusieurs fichiers source (le code source de Linux est de l'ordre de 100Mo) peut gnrer des erreurs. C'est alors que le principe de rcriture a t utilis pour implmenter une fonctionnalit qui contient une collection de fragments de code ainsi qu'une description formelle des points d'ordonnancement. Cette fonctionnalit correspond un ensemble de rgles de rcriture pour dcrire les conditions vrifier en vue d'insrer des vnements spcifiques. Voici un exemple de rgle de rcriture : n:(call try_to_wake_up))=> Rewrite(n,bossa_unblock_process(args)) Cette rgle sera applique chaque fois qu'un appel la fonction try_to_wake_up est trouv. Cet appel sera rfrenc par n. L'utilisation de Rewrite indique que l'appel try_to_wake_up est remplac par un appel bossa_unblock_process. La fonction wake_up_process suivante illustre l'effet de l'application de la rgle dcrite ci-dessus : wake_up_process(struct task_struct *p) { #ifdef CONFIG_BOSSA return bossa_unblock_process(WAKE_UP_PROCESS, p,0); #else return try_to_wake_up(p,0); #endif } Le noyau est rcrit l'aide d'une quarantaine de rgles logiques d'une assez grande complexit implmentes en Ocaml et en PERL par l'intermdiaire de CIL (C Intermediate Language).

2 Exemples de systmes et plates-formes temps rel

66

2.4.4. BOSSA : un hirarchie dordonnanceur [RTS 05] Un ordonnanceur est une application complexe puisqu'il est question de comprendre les conventions utilises dans l'implmentation d'un systme d'exploitation. Il est souvent ncessaire de bien connatre le noyau pour rdiger une nouvelle politique car celle-ci est souvent compltement indissociable du reste du noyau. Idalement, pour pouvoir implanter de nouvelles politiques d'ordonnancement, l'ordonnanceur et le reste du noyau doivent tre compltement dissociables mais parfaitement interfacs. BOSSA propose un niveau d'abstraction spcifique au domaine de l'ordonnancement. Au lieu de faire directement appel des fonctions de l'ordonnanceur (typiquement schedule()), les drivers font appel un systme d'vnements. En effet, la rcriture sur le noyau Linux consiste analyser le code par l'intermdiaire de rgles logiques afin de dtecter les points d'ordonnancement (par exemple lection d'un nouveau processus, changement d'tat d'un processus, etc.). Chaque point d'ordonnancement est remplac par le lancement d'un vnement qui dpend des conditions d'appel. Les vnements sont interprts par le RTS (Run - Time System) de BOSSA (voir figure 2.5.) qui invoque la fonction approprie dfinie par l'ordonnanceur.

Noyau

Noyau Linux Avec des vnements BOSSA

vnements RTS BOSSA

vnement
Etat dordonnanceur

Politique dordonnancement

bossa.schedule Processus lu

Figure 2.5. Architecture de BOSSA.

2 Exemples de systmes et plates-formes temps rel

67

Pour rgler les problmes de cohabitation de programmes temps rel et non temps rel, BOSSA introduit la notion de hirarchie d'ordonnanceurs. Un ordonnanceur de processus est un ordonnanceur classique qui gre les processus en vue de leur attribuer le processeur. Un ordonnanceur virtuel est un ordonnanceur qui contrle d'autres ordonnanceurs. Ainsi, on peut crer un ordonnanceur virtuel avec des ordonnanceurs fils auxquels il peut donner la main selon des critres bien dfinis (par exemple, priorit) ou bien selon une proportion (par exemple on donnera la main une fois sur trois l'ordonnanceur fils numro 1 contre deux fois sur trois l'ordonnanceur fils numro 2). L'ordonnanceur du systme aura donc une forme hirarchique ou arborescente avec comme feuilles des ordonnanceurs de processus et comme nuds des ordonnanceurs virtuels. Lorsque le RTS de BOSSA envoie un vnement de type bossa.schedule, celui-ci est destin au premier ordonnanceur dans la hirarchie. Du point de vue de la programmation, un ordonnanceur virtuel va avoir pour tche principale de propager l'vnement reu vers l'ordonnanceur fils appropri et de mettre jour l'tat de l'ordonnanceur fils. Ainsi, les vnements descendent la hirarchie jusqu' atteindre un ordonnanceur de processus qui va, en traitant l'vnement, agir directement sur les processus qu'il gre.

2 Exemples de systmes et plates-formes temps rel

68

Conclusion Petit soit-il, ce chapitre nous a permis de faire un tour dhorizon, sur les diffrents systmes temps rel existants. Nous avons insist durant ce chapitre, sur les deux systmes temps rel RTAI et VxWorks, afin de voir les diffrents mcanismes de communication entre tches dune part, et que nous navons pas dailleurs abord lors de notre prsentation des concepts temps rel au chapitre prcdent ; dautre part, nous avons prsent travers ces systmes lAPI que doit offrir un excutif temps rel, en vue de donner une ide sur celle que nous aurons prsenter dans les prochains chapitres. Pour voir la retombe du systme RTAI, nous avons prfr la plate-forme CLEOPATRE, qui prend effectivement RTAI comme support de base pour produire un haut niveau dabstraction. Ceci donne alors lide de ce que peut tre la mise en pratique dun excutif temps rel. BOSSA est une plate-forme temps rel qui consiste quant elle en une aide lcriture de nouvelles politiques dordonnancements. Nous avons jug utile de la prsenter, car lavantage, de Bossa, est de pouvoir utiliser des ordonnaceurs temps rel, tout en ayant un systme d'exploitation gnraliste, qui offre plus de fonctionnalits qu'un systme temps rel. A titre indicatif, nous donnons dans ce qui suit, ltat du march concernant lutilisation des systmes temps rel embarqus [SETR].

2 Exemples de systmes et plates-formes temps rel

69

Bibliographie [CLEO] : http://www.cleopatre.org [DP 91] : Alain DORSEUIL et Pascal PILLOT- Le Temps Rel En Milieu Industriel (DUNOD 1991). [RPG] : RTAI Programming Guide 1.0 (http://www.rtai.org). [RTS 05] : BOSSA et le Concert Virtuel Rparti, intgration et paramtrage souple d'une politique d'ordonnancement spcifique pour une application multimdia distribue J. Cordry, N. Bouillot, and S. Bouzefrane. 13th International Conference on Real-Time Systems, Paris, France, April 2005. [SETR] : Systmes Embarqus Temps Rel : VxWorks Universit de Brest, IUP GMI, Singhoff Frank C-208.

Chapitre 3

Conception de lexcutif temps rel

Ce chapitre va prsenter dune faon dtaille la conception de notre excutif temps rel. Nous allons rappeler puis largir lobjectif de notre systme, ce qui nous conduira parler du cadre de travail en se rfrant aux objectifs fixs. Nous allons aborder durant ce chapitre, les raisons qui nous ont conduit, opter pour les mthodes et les politiques adopter, en se basant bien sr, sur les concepts que nous avons vus durant les prcdents chapitres. Nous allons expliciter et expliquer les diffrents modules dvelopper, en les combinant aux stratgies que nous aurons appliquer, et ce, dune faon assez formelle. Loin de larchitecture matrielle, ce chapitre va essayer de sparer au mieux labstraction physique sur laquelle notre excutif sy implantera, et labstraction qui englobera les politiques adopter au sein mme de notre excutif temps rel. Ce chapitre se veut tre une spcification et une solution au but vis travers une question pose indirectement et qui se rptera incessamment tout long de ce chapitre, qui est : quoi faire ? ; il laisse cependant le soin au chapitre suivant, dy apporter une rponse la question du : comment le faire ?. Nous nallons pas adopter une mthode spcifique, pour concevoir notre systme. Nous avons pens au dpart utiliser UML temps rel, mais celle-ci semble plutt donner des solutions et des formalismes sous le paradigme objet, et dautant plus quelle est toujours au stade de la recherche. Les autres mthodes, comme SART nest pas adapte ce genre de conception, puisquelle ne spcifie que les applications temps rel.

3 Conception de lexcutif temps rel.

71

3.1.

Objectif

Nous voulons concevoir un excutif temps rel, simple dans ses mcanismes de base, pouvant mettre en vidence des principes et des politiques connus dans la littrature des systmes dexploitation, et pouvant ainsi intgrer un certain aspect pdagogique. Partant de cette philosophie, cet excutif sera usage gnral, et sadressera aussi bien aux dveloppeurs dapplications temps rel, quaux tudiants et enseignants voulant promouvoir et/ou mettre en relief les concepts rgissant ce systme. Nous devons penser concevoir un environnement, offrant aux dveloppeurs dapplications temps rel, une interface de programmation (API), avec un ensemble de services, la fois restreint et indispensable. 3.2. Cadre du travail

Afin de rejoindre lobjectif de notre travail, nous allons considrer des principes et des politiques bties autour dune architecture monoprocesseur. En vertu de ce qui a t prsent dans les prcdents chapitres, nous allons principalement assurer la gestion des tches priodiques et apriodiques en tenant compte de la faisabilit du systme mais aussi de la synchronisation entre tches. Mme si la spcification nous impose une certaine prcision du systme temps rel savoir, son interaction avec le procd, nous ne pourrons la formuler priori, tant donn que lobjectif est de crer un excutif usage gnral. La portabilit ne sera pas prise en compte, dans la mesure o, le domaine temps rel se limite suivant lobjectif vis, implmenter des politiques et de voir les principes mis en uvre, ce qui porte peu les exporter vers dautres architectures, et dautant plus que ce domaine, impose gnralement la prise en compte des caractristiques de la machine sur laquelle il est implant. Linteroprabilit qui est lie la question de coopration avec dautres systmes, ne sera prise en compte notre niveau, et devrait tre fixe par les applications temps rel, le cas chant. La modularit est un aspect fondamental la conception de notre systme, il permet dune part de subvenir aux besoins fixs en terme de simplicit des mcanismes, et dautre part, faciliter le dveloppement et la maintenance de notre systme. Nous supposons alors connues les notions darchitecture de base dun systme informatique, et les techniques appliques celui-ci, ainsi que les notions prsentes aux prcdents chapitres.

3 Conception de lexcutif temps rel.

72

3.3.

Architecture gnrale du systme

Partant de la notion du systme, qui doit par dfinition avoir des entres et des sorties, et en se rfrant lobjectif fix, lide gnrale de conception peut se rsumer crer un systme qui a pour entre les demandes de lutilisateur et pour sortie, les traitements et les rsultats effectus, suite aux demandes dentre. Etant donn que le systme est un excutif temps rel, et sera implant sur un systme informatique, la premire ide venant lesprit, tant de dfinir le matriel comme une ressource exploiter, sur laquelle notre systme sy reposera. Lutilisateur quant lui, sera plac au niveau dabstraction immdiatement suprieur celui du systme considr. Autrement dit, adopter lapproche en couches. Lutilisateur sera plac dans lespace de lexcutif, spar nanmoins par une interface (API) travers laquelle se fera la communication ou linteraction. Cette philosophie est souvent utilise dans les excutifs temps rel, afin de garantir la modularit du systme et fortiori, minimiser le temps de commutations de contexte, cependant linconvnient est quun bug au niveau dune tche temps rel, entranera le crash du systme. Nous avons donc fait un compromis.

Nous allons expliciter les diffrentes parties qui composent notre excutif, en adoptant une approche modulaire, et feront lobjet des sous paragraphes prochains. La figure 3.1 illustre, larchitecture gnrale de notre systme. Notons que linteraction entre le matriel et lexcutif sera vue plus en dtail, dans le prochain chapitre.

Utilisateur Module temps rel Matriel Notre excutif

Figure 3.1. Architecture gnrale de lexcutif temps rel.

3 Conception de lexcutif temps rel.

73

3.4.

Module temps rel

Avant de dtailler le prsent module, il est ncessaire de donner les grandes lignes auxquelles il fera rfrence. Afin dobir lobjectif du systme crer, qui consiste entre autres fournir un environnement de dveloppement dapplications temps rel, nous allons appliquer les concepts vus au premier chapitre. Pour ce faire, notre excutif doit alors offrir la possibilit de grer des tches priodiques contraintes strictes ; pour cela, nous les associons la politique dordonnancement RM (Rate Monotonic). Ce choix est justifi par la simplicit de son implmentation dune part, et dautre part, il savre comme tant lalgorithme optimal pour des tches chance sur requte (voir thorme RM). Par ailleurs, notre excutif, doit galement prendre en charge la gestion des tches apriodiques. Ceci, en les grant avec une tche priodique particulire dite serveur. Pour ce dernier, nous utiliserons plus exactement le type ajournable, et ce, pour remdier lincompatibilit des rythmes darrive, vue dans le cas dun serveur scrutation. Afin de simplifier lordonnancement des tches apriodiques, celles-ci vont tre gres par la tche priodique serveur, en FIFO. La synchronisation entre tches est essentielle tout excutif. Pour cela, nous allons faire munir notre systme dune gestion de smaphores binaires. En effet, les smaphores comptes demandent nettement plus de complexit les mettre en uvre ; ce qui contredit notre objectif fix en terme de simplicit des mcanismes, et dautant plus que nous aurons protger que des sections critiques, et la rentrance du code ne sera que critique. Comme nonc dans la problmatique de lordonnancement temps rel au premier chapitre, la synchronisation par smaphores, doit tre associe un protocole de rservation de ressources, en vue de borner le temps dattente aux ressources. Par consquent, nous optons pour le protocole priorit plafond, pour son vitement de linterblocage ou ltreinte fatale, mais aussi pour son vitement au phnomne dinversion de priorits. Intuitivement, nous pouvons dcomposer le module temps rel, en deux sous modules : module des tches ; module dordonnancement.

3 Conception de lexcutif temps rel.

74

Ces modules sont issus, certes, dune dcomposition intuitive, mais plus forte raison, dune dcomposition systmique, car, en considrant la partie temps rel comme un systme, il en dcoule une dcomposition en sous systmes, qui doivent rpartir ou prendre en charge les entres et les sorties du premier module les englobant ; or, nous pouvons prendre en charge le flux dentre (du ct utilisateur) par le premier module (tches), et aprs quoi, celui-ci agira sur le second (ordonnancement), pour produire ou provoquer par le biais du matriel, le flux de sortie. (voir figure 3.2.).

Lutilisateur.

Notre excutif.

Le matriel.

Flux

Partie temps rel.

Interactions

Tches

Ordonnancement

Figure 3.2. Dcomposition du module temps rel.

3 Conception de lexcutif temps rel.

75

3.4.1. Module des tches Ce module est cens interagir avec labstraction suprieure (utilisateur), en offrant ce dernier la possibilit de manipuler lentit tche. Trois classes de tches sont considrer, en vue de couvrir lensemble du module des tches, savoir, la classe des tches priodiques, la classe serveur et la classe des tches apriodiques (voir figure 3.3.). Chacune de ces classes est rattache une interface travers laquelle elle peut tre manipule par la couche immdiatement suprieure (utilisateur).

Lutilisateur Classe apriodique Flux. Module des tches

Classe serveur

Classe priodique

Module dordonnancement

Figure 3.3. Les classes rgissant le module des tches.

3 Conception de lexcutif temps rel.

76

Par ailleurs, pour quelle puisse agir sur le module dordonnancement, seules deux classes dentre elles savoir, la classe des tches priodiques et serveur, seront manipules par le module dordonnancement. En effet, seule la classe serveur, est responsable de lordonnancement des tches apriodiques. Pour quelles puissent tre ordonnances, les tches priodiques, aprs leur avoir attribu 1 une priorit (selon RM), seront mises dans une file d'attente, accessible et manipule par le module dordonnancement. Il y va de mme pour la classe serveur, mais la diffrence rside dans le fait que celle-ci devrait contenir une file propre elle pour sa propre gestion des tches apriodiques, autrement elle est considre au mme titre que la classe priodique du ct module dordonnancement. Nous devons aborder la synchronisation dans la classe des tches priodiques, tant donn le fait que le protocole priorit plafond soit mis en uvre. En effet, ce protocole suppose priori la connaissance de chaque ressource susceptible tre utilise, mais aussi du temps dexcution de chaque section critique associe, en vue de borner le temps dattente. Par consquent, le module des tches devra associer pour chacune des tches de la classe priodique, une file de smaphores qui vont tre utiliss par cette tche le cas chant, et ce, avant mme leur mise disposition au module dordonnancement. Le module des tches doit tre en mesure de satisfaire la faisabilit du systme, autrement dit, il devra, de par les caractristiques temporelles de la classe priodique et celle du serveur, dterminer la faisabilit du systme en vrifiant plus particulirement la condition dordonnancement RM vue au premier chapitre et ceci bien sr, aprs avoir dtermin les priorits plafond de chaque ressource utiliser, ainsi que leur facteur de blocage le cas chant. Etant donn que la condition du thorme de faisabilit ou dordonnancement est suffisante mais pas ncessaire, il ne faut donc pas disant stigmatiser le fait dune nonfaisabilit du systme, vu quil peut y avoir des configurations valides ne satisfaisant pas cette condition. Par consquent, le module des tches tchera, de rendre cette condition comme tant optionnelle au systme. Le flux dentre et de sortie liant la couche utilisateur et le module des tches, se rsume essentiellement la manipulation des tches comme pralablement nonc. Lutilisateur pourra travers une interface (API), le liant au module des tches, crer et supprimer des tches dans les diffrentes classes, de pouvoir crer et supprimer des smaphores et de les associer aux tches correspondantes, mais aussi, avoir la possibilit de grer le temps (horloge temps rel), dont il est gnralement le rle de chaque excutif temps rel. Nous allons nous contenter pour un premier temps, de cette discussion sur les services offerts lutilisateur, car nous les verrons plus en dtail, dans le prochain chapitre.

1. Dans notre systme, les tches de mme priode vont avoir une priorit gale.

3 Conception de lexcutif temps rel.

77

3.4.1.1.

Entit tche

Dans notre systme, elle reprsente lunit de base dexcution pour une quelconque manipulation, aussi bien par lutilisateur que par le module dordonnancement. Pour cela, elle introduit travers son contexte, des informations ncessaires pour satisfaire de part et dautre les cts quelle serve. Ce contexte est vu en partie dans le premier chapitre, quant aux informations relatives au matriel, celles-ci seront traites en dtail dans le prochain chapitre. Un bon nombre dinformations sur la tche doit tre, inclus pour prendre en charge les concepts temps rel. Pour cela, nous devons globalement faire munir le contexte de la tche dinformations sur le matriel (contexte de la CPU), et dordonnancement. Pour les deux derniers, ceux-ci doivent tre initialiss lors de la cration de la tche correspondante. Nous nallons pas dans ce cas inclure des informations relatives aux zones mmoires, dans la mesure o les tches temps rel seront dveloppes dans lespace dadressage mmoire du noyau et en outre, le code excutable des applications ainsi que leurs donnes seront confondus. Ceci sous-entend, quil n y aura pas de rservation de mmoire dune faon dynamique au sein du noyau, autrement dit, les applications seront considres crites et figes une fois pour toutes sans possibilit dallocation dynamique de mmoire. Quant la zone de pile, celle-ci est rserve dune manire statique, lors de la cration de la tche, et ne sera rfrence ou intgre que dans le contexte processeur. Pour quelle puisse tre utilisable par le module dordonnancement, nous allons faire ajouter au contexte de la tche temps rel, les informations permettant un ordonnancement en RM. Pour introduire la notion de temps aux tches, la date de rveil de la tche, sa dure dexcution, et sa priode sont ajoutes conformment la politique RM dordonnancement, ainsi que deux compteurs, pour la sauvegarde du temps dexcution restant et la prochaine date de rveil. Et nous devons par ailleurs, avoir des informations sur le type ou la classe de tche (priodique, apriodique, serveur), pour quelle soit suivant sa nature, tre manipule par le module dordonnancement. Aussi, nous devons rajouter des informations sur les ressources susceptibles tre utilises par la tche, prtendant par cela, le facteur de blocage de la tche, la file des smaphores utiliser et ventuellement le smaphore pour lequel la tche pourrait tre en attente. Etant donn que nous aurons grer les tches travers des files dattente, elles devront alors bien videmment avoir des informations comme le prdcesseur et le successeur dans la file. Un ensemble dtats caractrise la tche, des informations comme PRET, SUSPENDU, SEM, ATTENTE, qui dsignent respectivement, la tche prte, tche suspendue, opre en section critique, et attente dune ressource(smaphore). Chaque tche possde son degr de priorit, mis jour chaque cration dune nouvelle tche, disposant galement dune sauvegarde de la priorit initiale lors dun ventuel hritage de priorit en section critique. (voir figure 3.4).

3 Conception de lexcutif temps rel.

78

Contexte hardware Identifiant de la tche Priorit de la tche Sauvegarde de la priorit en section critique Etat de la tche {pret, suspendu, attente, sem} Successeur Prdcesseur La date de rveil de la tche Dure dexcution de la tche Contexte dordonnancement Priode dexcution de la tche Le facteur de blocage de la tche* Classe de la tche {priodique, apriodique, serveur} Utilisation des ressources (oui/non) Identifiant de la file des smaphores* Smaphore pour lequel la tche est en attente* Contexte en utilisation (oui/non)

Figure 3.4. Contexte de la tche temps rel de notre systme.

* linformation est valide, sil y a utilisation des ressources par cette tche.

3 Conception de lexcutif temps rel.

79

3.4.1.2.

Entit smaphore

Chaque ressource du systme sera associe un smaphore. Comme nous lavons nonc, nous allons utiliser des smaphores binaires. Les smaphores seront prsents dans le systme sil y a au moins une tche susceptible de les utiliser, cette dernire devrait ce moment-l spcifier la file des smaphores associs aux tches, pralablement cre. Chaque tche utilisant des ressources critiques, dispose de sa propre file de smaphores. Un smaphore dans notre systme, disposera dautant dentres de prdcesseur et de successeur que de nombre de tches pouvant exister dans le systme. Dune part, ceci est d au fait quun smaphore peut tre prsent dans plusieurs files de smaphores associs aux tches, et dautre part, il nous faudrait imposer cette manire de faire, en vue de pouvoir dterminer ventuellement les ressources communes entre les tches qui seront utilises dans le protocole priorit plafond. Pour simplifier les choses, nous allons dfinir une bijection entre lidentifiant de la tche et le numro du successeur/prdcesseur correspondant dans le smaphore. Ainsi, si on suppose que la tche n, voulant utiliser les smaphores : Si, Si+1, Sj (pour j>i) alors le successeurn de Si serait gal Si+1 . Le raisonnement est analogue jusqu Sj . (Voir figure 3.5). Par ailleurs, le smaphore dispose de deux autres entres successeur/prdcesseur, mais cette fois-ci pour grer une autre file de smaphores lors de lexcution des tches. Cette file est unique, du fait que les smaphores grer sont binaires. Cette file est mise en uvre pour indiquer dune part les smaphores qui sont en cours dutilisation, et dautre part, permettre le recensement des smaphores, en vue de la mise en pratique du protocole priorit plafond. Chaque smaphore dispose de sa propre identit, ainsi que celle de la tche qui le dtient le cas chant. Il dispose galement dune valeur indiquant si oui ou non le smaphore est libre. Puisque les smaphores sont associs au protocole priorit plafond (PCP), nous devons alors faire munir le smaphore conformment au PCP dune priorit plafond. Partant du principe quune section critique peut avoir plusieurs temps dexcution (suivant le nombre ditration ou de boucle, les conditions sur les diffrentes parties du code excuter), nous allons rajouter un tableau de valeurs, contenant les dures dexcution des sections critiques associes aux tches. Ceci bien sr sous la supposition quune tche naura utiliser la mme section critique de diffrentes manires, autrement dit, pour des raisons de simplicit, durant toute lexcution dune tche, si celle-ci utilise plusieurs fois une rfrence une section critique, le code de cette dernire devrait tre le mme chaque fois que la demande par cette tche soit faite.

3 Conception de lexcutif temps rel.

80

Utilisation des smaphores : Si , Si+1,, Sj

La tche n

pred0 pred1 pred2


. . . VIDE

succ0

succ1 succ2

pred0 pred1 pred2


. . .

succ0

succ1 succ2

pred0 pred1 pred2


. . .

succ0

succ1 succ2

predn . . .

succn

predn . . .

succn

predn

succn . . .
VIDE

Smaphore Si

Smaphore Si+1

Smaphore Sj

Figure 3.5. Reprsentation de la nime file des smaphores correspondante la tche n.

3.4.1.3.

Files dattente

Nous avons voqu lors des prcdents points, lutilisation des files dattente, aussi bien pour les tches (priodiques et serveur) que pour les smaphores. Pour mettre en place une file dattente, nous allons la faire doter dun entte contenant les informations comme la tte et la queue de la file, ainsi que le nombre dlments prsents. Les lments de chaque file devront avoir des informations comme prdcesseur, et successeur, afin davoir un double chanage pour une manipulation rapide de la file. Ce principe sera utilis pour toutes les files dattente du systme, y compris celle des smaphores associs aux tches (vue au prcdent paragraphe). La figure 3.6. illustre le principe des files dattente utiliser.

3 Conception de lexcutif temps rel.

81

Entte de la file Tte

Elment 1

Elment 2

Elment n

Queue

Nombre dlments

Figure 3.6. Principe de file dattente de notre excutif.

3.4.1.4.

Pile des tches apriodiques

Larrive des tches apriodiques, comme son nom lindique, se fait dune manire imprvisible. Pour pouvoir les grer, nous allons leur consacrer une pile, contenant les identifiants des tches apriodiques arrives. Comme nous lavons pralablement nonc, la gestion des tches apriodiques est assure par la tche serveur. Celui-ci pour des raisons de simplicit, les ordonnance en FIFO. Le serveur manipule cette pile, en faisant lextraction de lidentifiant le plus ancien arriv. A vrai dire, nous avons abus du terme pile, dans la mesure o les oprations sur une pile se rsument dpiler/empiler, ce qui correspond la politique LIFO. La pile que nous aurons utiliser pour les tches apriodiques, sera similaire dans le principe une pile ordinaire, mais la seule diffrence est que nous allons dpiler toujours depuis le bas de cette pile. Bien videmment, ceci retombe directement sur le principe dune file, mais cest justement pour viter toute confusion avec les autres files dattente du systme, que nous avons choisi de la baptiser autrement. La figure 3.7. illustre ce principe.

3 Conception de lexcutif temps rel.

82

La dernire tche apriodique arrive.

Identifiant n . . . Identifiant 2 Identifiant 1 La prochaine tche apriodique extraire par le serveur.

Figure 3.7. Pile des identifiants des tches apriodiques.

3.4.1.5.

Rsum

Pour rcapituler, nous allons donner pour chacun, des lments, que nous avons pralablement dfini, les files auxquelles il appartient et/ou manipule. Les tches priodiques et la tche serveur (sil y a gestion des apriodiques), vont tre toujours associes une file dattente des tches priodiques prtes. - Les tches priodiques (hormis le serveur) susceptibles dutiliser des ressources (smaphores), vont chacune avoir une file des smaphores associs aux tches. - Les smaphores vont tre associs une file de gestion de smaphores. - Les tches apriodiques vont tre gres par le serveur(ajournable), et se trouveront dans la pile des tches apriodiques. (Voir figure 3.8.). Pour la dynamique rgissant ces lments, celle-ci est prise en charge par le module dordonnancement, qui fera lobjet du prochain paragraphe. -

3 Conception de lexcutif temps rel.

83

File dattente des tches priodiques prtes.

File des smaphores associs aux tches. Toujours associ Susceptible davoir Tche priodique Smaphore Serveur ajournable gr par appartient

gre File de gestion de smaphores.

arrive Tche apriodique Pile des tches apriodiques.

Figure 3.8. Entits du module des tches.

3 Conception de lexcutif temps rel.

84

3.4.2. Module dordonnancement Ce module peut tre considr comme tant la partie action de la partie temps rel, et manipulera essentiellement les entits dfinies dans le module des tches, conformment aux politiques et stratgies pralablement nonces. Lordonnancement intervient alors quune fois les diffrentes entits du module des tches sont mises en place. Pour grer la classe des tches priodiques, nous allons driver du module dordonnancement, une partie qui soccupera de la recherche partir de la file des tches priodiques prtes, la tche dont la prochaine date de rveil est minimum avec la plus grande priorit. En dautres termes, une partie excutive de la politique RM. La tche ventuellement trouve par cette partie, sera considre comme tant la tche lue du systme. En parlant de classe de tches, nous devons inclure les apriodiques. Nous avons envisag dordonnancer les apriodiques par la tche priodique serveur. Ceci revient dire, que ce nest quune fois la tche serveur est lue, que celle-ci recherchera les tches apriodiques lire, car il y va de la responsabilit de la tche priodique serveur dordonnancer les tches apriodiques. Nous avons vu dans lordonnancement RM, quil peut y avoir des creux temporels entre les tches, autrement dit, la priode durant laquelle aucune tche nest prte tre lue. Nous allons considrer une tche particulire nop_task (pour : no opreration task) que lordonnanceur sollicitera, ds quil n y a aucune tche priodique lire. Par ailleurs, pour pouvoir grer les tches priodiques conformment la politique RM, nous devons faire palpiter lordonnanceur des intervalles rguliers, assur par lhorloge temps rel. Un compteur absolu va tre ddi pour prendre en charge la notion de temps, et de pouvoir ainsi dduire les dates de rveil des tches En outre, il faudrait faire munir le module dordonnancement dune partie qui interagira avec le matriel afin de pouvoir faire charger la tche lue. Cette partie va tre vue plus en dtail dans le prochain chapitre, tant donn quelle prend en charge la spcificit matrielle. La figure 3.10 illustre la dcomposition du module dordonnancement.

3 Conception de lexcutif temps rel.

85

Lutilisateur.

Notre excutif.

Le matriel.

Flux

Entits du module des tches

Partie excutive RM Interactions Interaction hardware

Module dordonnancement

Figure 3.9. Dcomposition du module dordonnancement.

3 Conception de lexcutif temps rel.

86

3.4.2.1.

Ordonnancement des priodiques

La partie excutive RM dans la figure 3.9. est responsable de la gestion des tches priodiques. A chaque top dhorloge mis par le matriel considr, cette partie recherchera dans la file des tches prtes, la tche la plus prioritaire suivant RM, lguant cette tche la partie interaction hardware le cas chant ; le cas contraire, cest la tche nop_task qui sera lue ; ces actions se rpterons indfiniment et chaque top dhorloge. Nous pouvons donc dire que lalgorithme dordonnancement ainsi utilis, est un algorithme inline. Puisque nous avons abord la synchronisation entre tches priodiques, la partie excutive RM devrait alors prendre en charge la gestion des tches manipulant les smaphores. Nous avons cit auparavant, que les tches en attente dune ressource critique (smaphore) ont un attribut ou tat que nous avons dfini comme : ATTENTE. La partie excutive RM, est responsable de rendre nouveau prte (tat : PRET) la tche en attente dune ressource libre. Autrement dit, ds quil y a libration dune ressource attendue par une tche priodique, cette dernire va rentrer en concurrence avec les autres tches, et ce, en modifiant son tat ATTENTE en tat PRET. Pour tre lue, la tche priodique doit avoir un tat parmi {PRET : prte, SEM : opre en section critique}, et avoir la plus grande priorit (attribue lors de sa cration suivant la politique RM), mais aussi avoir une date de rveil suprieure ou gale au compteur absolu associ lhorloge temps rel pralablement dfini. A noter, que la date de rveil de la tche lire sera mise jour en ajoutant chaque fois la priode de cette tche. Cest ainsi que la tche priodique (quelconque ou serveur) ayant pour priode P une prochaine date de rveil R=R+P. La capacit de la tche priodique lue, est rduite dune unit de temps chaque top dhorloge, et ce nest quaprs puisement de cette capacit, que la date de rveil R est de nouveau dtermine. Durant lexcution dune tche priodique, cette dernire est susceptible dtre pempte au profit dune tche plus prioritaire, il sagit alors dun ordonnancement premptif bas sur la priorit, vu au premier chapitre. Dans notre cas, la premption est due au fait qu chaque top dhorloge, il y a lection de la tche priodique la plus prioritaire prte (avec tat PRET ou SEM). Comme nous lavons dj voqu, lordonnancement des tches priodiques demandant une ressource, est combin avec un protocole de gestion de ressources (PCP) afin de borner le temps dattente dune ressource, par une tche priodique(hormis serveur).

3 Conception de lexcutif temps rel.

87

Le protocole priorit plafond (PCP) va tre combin avec lalgorithme dordonnancement, et devra garantir la libration dune ressource au bout dun temps fini et dfini ; et devra par ailleurs parvenir aux situations dinterblocage (treinte fatale), mais aussi au phnomne dinversion de priorits. Nous allons faire munir La partie excutive RM, de protocole priorit plafond. Pour ce faire, nous pensons activer le mcanisme, ds quil y a demande ou libration de ressources. Lors dune demande de ressource (smaphore) libre, ce moment-l, il est recenser les ressources en cours dutilisation, et en se rfrant la priorit plafond de la ressource sollicite, dcider conformment au PCP (vu au premier chapitre), quant lattribution de la ressource libre, la tche demandante. Ce protocole doit en outre, procder lhritage de priorit, dans le cas bien sr , o la tche est prempte par une autre tche plus prioritaire et de plus, elle est en demande de la mme ressource (smaphore) dj dtenue par cette tche prempte. Lors de la libration de la ressource, la partie excutive RM munie du PCP, va restaurer la priorit, sil y a eu hritage de priorit, et libre la ressource. Dans le chapitre suivant, nous allons parler plus en dtail de cette partie, et nous verrons la manire de limplmenter.

3.4.2.2.

Ordonnancement des apriodiques

Pour grer les tches apriodiques, nous devons les associer une tche priodique dite serveur qui se chargera durant sa capacit dexcution, de faire excuter lune des tches apriodique arrive, suivant une politique propre au serveur. Au sein du serveur, nous prfrons grer les tches apriodiques suivant la politique FIFO, tant donne sa simplicit la mettre en uvre. Le serveur est une tche priodique unique dans le systme, nous allons opter pour le serveur ajournable, pour remdier lincompatibilit des rythmes darrive vue dans un serveur scrutation. Autrement dit, le serveur que nous pensons utiliser, devra maintenir sa capacit dexcution, et ce, mme si aucune tche apriodique nest prsente dans le systme, de cette manire, ds quil y a, arrive dune tche apriodique, celle-ci est servie, sans pour autant attendre la prochaine date de rveil du serveur. Ceci renforce en quelque sorte la contrainte des tches apriodiques.

3 Conception de lexcutif temps rel.

88

En absence des tches apriodiques, le serveur est mis ltat SUSPENDU, par la partie excutive RM, et ds quune tche apriodique arrive, le serveur reprend ltat PRET, et pourra servir immdiatement la tche apriodique en lui fournissant toute sa capacit. Cette dernire est exploite par lapriodique arrive, mais elle devrait poursuivre son excution lors de la prochaine chance du serveur, dans le cas o la capacit du serveur savrerait insuffisante devant la capacit de la tche apriodique. Dans le cas o la tche apriodique sachve avant lpuisement de la capacit du serveur, se dernier se mettrait immdiatement ltat SUSPENDU, sauf sil y a davantage de tches apriodiques servir. Comme nous lavons dj mentionn, les tches apriodiques arrivent dans la pile apriodiques, et chaque top dhorloge et en prsence du serveur, il y a vrification de cette pile. De cette manire, nous pouvons envisager dappliquer la stratgie nonce auparavant, qui consiste entre autres servir la tche apriodique ds son arrive par le serveur ajouranble. La partie excutive RM fera donc, lextraction(depuis le bas) de lidentifiant partir de cette pile consacre aux apriodiques, dans le cas bien sr, o le serveur serait en phase de repos (aucune apriodique nest en phase de traitement). Dans le cas contraire, la partie excutive RM devra attendre la terminaison de la tche apriodique en cours de traitement pour pouvoir faire lextraction de lapriodique suivante. Ceci nous renseigne sur le fait que les tches apriodiques sont traites dune faon squentielle par le serveur, suivant leur arrive, et quil n y aura bien videmment pas de premption entre les apriodiques. Nous pensons que le signal darrive des apriodiques, devra tre li un vnement matriel, par le biais des interruptions, en vue de prendre en charge cet vnement. Autrement dit, les interruptions matrielles vont nous servir, dune part, de distinguer la nature de lvnement apriodique arriv, et dautre part, de pouvoir traiter lvnement ds son arrive. Pour cela, nous imposons le fait de connatre la dure de chacune des interruptions, afin de garantir le dterminisme du systme en temps. Cette dure fera une caractristique technique du systme, et doit tre prise en compte par les dveloppeurs dapplications temps rel, pour notre excutif. Nous allons voir plus en dtail la manire dimplmenter cette technique de mesure de temps dinterruptions, dans le prochain chapitre.

3.4.2.3.

Rsum

Pour rcapituler, le module dordonnancement intervient sur lentit tche, en changeant ses tats dans lensemble {PRET, SEM, ATTENTE, SUSPENDU}, en vue dlire une tche priodique conformment la politique utilise. Pour les tches priodiques hormis le serveur, les tats sont illustrs dans la figure 3.10.

3 Conception de lexcutif temps rel.

89

PRET
Entre en section critique Sortie de la section critique

SEM

Attente dune ressource


ATTENTE

Obtention de la ressource

Figure 3.10. Etat dune tche priodique (hormis serveur). La tche priodique serveur prend uniquement deux tats, puisquelle nutilise pas de ressources (voir figure 3.11.). Nous avons par ailleurs vu, que les apriodiques sont prises en compte par la tche serveur, qui est la seule responsable de leur ordonnancement. La figure 3.12. rsume dune faon gnrale le fonctionnement.

PRET

Absence dapriodique SUSPENDU

Arrive dune apriodique

Figure 3.11. Etats du serveur ajournable.

3 Conception de lexcutif temps rel.

90

Signal apriodique

Empiler identifiant

Module dordonnancement Pile des apriodiques Top dhorloge matriel Activer (tat PRET)

SERVEUR ajournable pour le traitement des apriodiques

Dpiler identifiant

Figure 3.12. Traitement de lapriodique.

3 Conception de lexcutif temps rel.

91

Conclusion En voulant concevoir notre excutif temps rel, ce chapitre nous a permis de formuler les spcifications en se rfrant aux objectifs fixs. Partant de ces derniers, nous avons mis en vidence les couches de notre systme, savoir le matriel, lexcutif et lutilisateur (non final). Nous nous sommes limits la couche excutif (partie temps rel), en tenant compte des interactions quil peut y avoir avec les autres couches. Nous avons alors spcifi les stratgies et les politiques qui devront tre mis en uvre, pour atteindre lobjectif de notre travail. Nous avons adopt une approche modulaire, ce qui nous a conduit subdiviser pour un premier temps le module temps rel en deux sousmodules, savoir, le module des tches et le module dordonnancement. Pour ces derniers, et en vertu de ce qui a t prsent aux prcdents chapitres, nous avons parl des tches temps rel, de leur ordonnancement, mais aussi de leur synchronisation par des smaphores, tout en les englobant dans leur environnement modulaire. Pour chaque module, nous avons considr les diffrentes entits quil manipule, et nous avons discut les grandes lignes concernant la mise en place de ces entits conformment aux stratgies et politiques choisies. Avec ce formalisme assez exhaustif, nous sommes en mesure daborder la ralisation, qui mettra en pratique tout ce qui a t prsent dans ce chapitre, en dtaillant davantage les modules, et la manire de les implanter.

Chapitre 4

Ralisation de lexcutif temps rel

A travers ce chapitre, nous allons donner une solution pratique la conception que nous avons prsente auparavant. Les modules, alors conus, seront implants dune manire prserver la smantique ou la logique dont ils sont porteurs, tout en les dotant dune caractristique leur permettant de sadapter un environnement matriel, que nous allons devoir choisir. Une partie sera alors consacre la manire, de faire intgrer des aspects ces modules, tant au niveau matriel que logiciel. Ce dernier se focalisera essentiellement sur le codage, et servira de formalisme pour prsenter chaque fois, les diffrents composants logiciel sous la forme du langage de programmation postul. La spcificit matrielle sera dcrite avec cette mme faon de faire, cependant, nous nous focaliserons sur les interactions bas niveau pour dcrire les caractristiques matrielles que les modules devront prendre en charge. Les politiques et principes, rgissant les modules conus, seront considrs connus, pour nen tenir compte que de leur ralisation. Ils seront prsents dans lordre du fonctionnement de lexcutif, en dautres termes, dcrire la logique des modules, dans lordre chronologique de leur traitement par le systme informatique considr.

4 Ralisation de lexcutif temps rel.

93

4.1.

Choix de larchitecture matrielle

Durant toute la conception de notre excutif temps rel, nous avons suppos les politiques et stratgies bties autour dune architecture monoprocesseur. Le choix est port sur ce dernier dans ce prsent chapitre et devra, rejoindre lide de base et les objectifs fixs. Si lexcutif est conu pour une utilisation spcifique, nous choisirions ce moment-l une architecture aussi particulire, voire ddie. Cest ainsi que des mico-contrleurs, et des processeurs enfouis sont destins le plus souvent aux systmes embarqus, comme les distributeurs automatiques de billets, les robots autonomes Dans notre cas, lexcutif sera comme pralablement nonc, usage gnral et nous devons, choisir une architecture hardware sur laquelle nous pouvons garantir le fonctionnement des modules, du temps rel, conus. Pour notre excutif, nous allons choisir une architecture base sur le x86 dIntel, pour sa prise en compte des conditions ou critres des modules implanter, mais aussi et surtout pour sa forte disponibilit sur le march et son large utilisation par le grand public. Nous jugeons essentiel de prsenter cette architecture mesure que nous progressions dans ce chapitre, afin dclaircir davantage la prise en charge des interactions matrielles se trouvant au bas niveau de notre systme. Cependant, nous supposons connu larchitecture du 8086 dIntel, son jeu dinstruction, mais galement de larchitecture de lIBM PC, et nous nous intresserons, quaux spcificits matrielles du PENTIUM (586 dIntel) accessibles par programmation. 4.2. Langages et environnement de programmation

Pour ltape de codage, nous pensons utiliser deux types de langage, suivant la nature de la partie programmer. En effet, Il est fastidieux voire impossible, de programmer lexcutif tout entier en assembleur. Ni mme encore en langage haut niveau, tant donn que nous aurons programmer des routines tenant compte des spcificits matrielles. Nous avons choisi le langage assemblage Masm (de Microsoft) pour crire les fragments ncessitant un accs bas niveau, mais aussi pour loptimisation du code. Nous navons pas conu notre systme sous le paradigme orient objet ; nous comptons plutt adopter une approche procdurale pour raliser notre excutif. Le langage haut niveau sera donc le langage C (compilateur de Borland), et servira implanter les fonctions ncessaires, pour la mise en pratique des modules que nous avons pralablement dfinis, ainsi que les utilitaires ncessaires aussi bien au niveau excutif quau niveau environnement de programmation. Pour ce dernier, il sagira de lenvironnement Win32, tant donns les logiciels de programmation utiliser. Bien videmment, lenvironnement de programmation ainsi que les langages ninfluent point, quant la manire dont lexcutif sera mis en uvre, ce nest donc quune question de convivialit du ct programmeur de lexcutif temps rel. Nous supposons, ces langages connus, ainsi que leur manipulation dans lenvironnement dans lequel ils oprent.

4 Ralisation de lexcutif temps rel.

94

4.3.

Parties de lexcutif

Pour rejoindre lide de notre conception, et en se basant sur larchitecture matrielle choisie, nous allons procder la ralisation des diffrentes parties de notre excutif. Pour ce faire, nous allons suivre lide de conception, en implmentant les diffrents modules mais cette fois-ci dans le sens inverse, en terme dordre dappartenance aux niveaux dabstraction rgissant notre systme. Autrement dit, nous allons raliser en premier lieu, les parties proches du matriel, pour pouvoir ensuite arriver aux couches suprieures de notre systme. Cest souvent lapproche adopte lors de la ralisation en couches, dans les noyaux de systmes dexploitation. En terme dimplantation de lexcutif, la philosophie adopter consiste considrer des parties concatnes (noyau monolithique) sur disque, lesquelles seront charges la demande et une fois pour toutes. Nous allons faire charger en mmoire lexcutif en parties, ceci afin de permettre la prise en considration des tats de la machine, dune part, et dautre part, pour permettre aisment une ventuelle extension ou dveloppement au sein de ces parties. Cest alors que vient lide de raliser la partie dmarrage de notre excutif. Cette partie sera bien sr, le plus bas niveau de notre systme, et fournira principalement aprs une initialisation de la machine, un environnement assez riche en matire de services systme lmentaires, en vue de dvelopper les couches suprieures. Ces dernires porteront principalement en contexte, sur les modules que nous avons mis en vidence dans le chapitre conception, sajoute bien sr, linterface utilisateur (API). Ces couches seront regroupes dans une seule partie, que nous allons dfinir comme tant la partie oprationnelle. (voir figure 4.1.).

Interface Utilisateur (API) Partie oprationnelle

Module temps rel Partie dmarrage de lexcutif (Initialisation de la machine)

Ordre chronologique de ralisation

Figure 4.1. Les deux grandes parties raliser pour notre excutif.

4 Ralisation de lexcutif temps rel.

95

4.4.

Ralisation de la partie dmarrage

Cette partie a pour objectif dinitialiser la machine sur laquelle tournera notre excutif et de fournir un ensemble assez riche de fonctions, en vue de les utiliser lors de la programmation en haut niveau. Cette partie, et suivant larchitecture du PENTIUM ainsi que de lIBM PC, sera subdivise, en trois sous parties, savoir le boot, la partie 16-bit (mode rel du PENTIUM) et la partie 32-bit (mode protg du PENTIUM). Il faut savoir que pour programmer un noyau, la signification part delle-mme. Partant de rien, nous devons programmer des routines lmentaires qui nous faciliteront la manipulation des donnes en mmoire, des chanes de caractres mais aussi la manipulation des E/S de priphriques. En dautres termes, reprogrammer les fonctions (librairies) que nous incluons habituellement et dune faon vidente dans un langage haut niveau, lors de la programmation dapplications. 4.4.1. Le boot Il faut savoir que lors de la mise sous tension de la machine IBM PC, le processeur excute les premires instructions (en mode rel ou 16-bit) partir dune mmoire non volatile (ROM, FLASH). La routine laquelle appartiennent ces premires instructions excutes en premier lieu est dite bootstrup. Cette dernire est une partie dun programme appel BIOS, qui soccupe de la configuration et de linitialisation des priphriques de base prsents sur la machine (carte graphique, disques, clavier). Aprs quoi, le BIOS suivant sa configuration (sauve au CMOS) charge en mmoire (0000 :7C00h) le premier secteur du disque (secteur physique 0) spcifi dans la configuration. Le BIOS vrifie la signature du secteur (0x55AA) si elle est prsente la fin de ce secteur. Si tel est le cas, il lgue le contrle au programme ainsi charg depuis le secteur 0. Ce programme est appel zone damorce ou boot. Pour programmer le boot, celui-ci devrait tre crit en assembleur, tant donn que nous devons prendre en charge la taille de ce programme. En effet, la taille dun secteur physique est de 512 octets, et nous serons obligs den tenir compte ne pas dpasser cette taille, et dinscrire la fin de ce secteur, la signature dont nous avons parl plus haut. La mission du boot dans notre systme sera de charger dautres secteurs en mmoire et de leur lguer par la suite la main. Autrement dit, charger en mmoire et partir du disque de dmarrage, une partie de notre noyau (partie 16-bit). Nous allons en quelque sorte refaire ce que le BIOS a fait lors du chargement du secteur de boot, mais dans notre cas, nous allons devoir charger un nombre plus important de secteurs (18 secteurs successifs), dans un endroit diffrent en mmoire (par convention 2000h :0100h) et depuis une adresse physique diffrente sur disque (secteur physique 1 succdant le boot). Pour ce faire, nous allons utiliser les routines BIOS, pour pouvoir lire des secteurs physiques partir du disque de dmarrage (ah=2 int 13h), de rebooter dans le cas o les secteurs lire savreraient dfectueux (int 19h), deffacer lcran et dafficher un message en cas de russite/erreur(ah=8 et ah=0eh int 10h), et dattendre dans le cas dune erreur, la confirmation de lutilisateur (touche clavier), pour rebooter (AX=0 int 16h) aprs avoir mis un bip sonore dune dure de 2 secondes (respectivement, envoyer une valeur paire au port 61h et (ah=86h int 15h)).

4 Ralisation de lexcutif temps rel.

96

Notons que pour utiliser linterruption 13h (lire des secteurs physiques) dans notre programme de boot en assembleur, il faudrait spcifier lidentit du lecteur de dmarrage (valeur mise dans le registre DX du processeur lors du chargement du secteur de boot). Notre programme de boot sauvera cette valeur pour une ventuelle utilisation (par convention 1000h :0000). De plus, il est spcifier le numro du cylindre disque (registre CH=0), le numro de la tte du disque(DH=0), lidentit du lecteur (DL=0 disquette), le numro du secteur (CL=2), le nombre de secteurs lire (AL=18), spcifier la fonction dcriture (AH=2) mais aussi ladresse mmoire dans laquelle, les secteurs vont tre chargs (ES:BX=2000h :0100h par convention). Pour le lecteur intress par dautres routines BIOS, il peut consulter la rfrence [Ms dos]. Si aucune erreur nest survenue, lors du chargement de la partie 16-bit (18 secteurs physiques chargs), le boot fera aprs cela, un saut vers cette dernire (2000h :0100h), pour lui lguer le contrle. 4.4.2. Partie 16-bit (mode rel) Comme nous lavons vu, la partie boot est conditionne par sa taille (512 octets). Nous devons alors programmer une autre partie, qui assurera dune part, linitialisation de la machine, en fournissant avant ceci, un nombre de services systmes (librairie) ncessaires, en vue de les utiliser dans un langage haut niveau, et dacclrer ainsi le dveloppement de notre excutif temps rel, et dautre part, faire charger la partie 32-bit (mode protg). Rappelons-le, quil appartient au secteur de boot de charger la partie 16-bit, et ce, partir du secteur physique 1, succdant immdiatement le boot. Pour initialiser la machine, nous devons au pralable et comme nous lavons dj soulign, disposer de fonctions (utilitaires) qui nous permettra un contrle ais de donnes comme les chanes de caractres , et de pouvoir manipuler dans un environnement haut niveau des fonctions comme laffichage Pour cela, nous devons dfinir un ensemble de fonctions, la fois restreint et indispensable et qui fera lobjet du sous paragraphe suivant. Puis, nous allons aborder la manire dinitialiser la machine, moyennant notamment ces fonctions utilitaires que nous avons implantes. 4.4.2.1. Fonctions utilitaires

4.4.2.1.1. Manipulation de chanes de caractres Pour manipuler les chanes de caractres, nous allons rcrire les deux fonctions : const char far *strcpy(char far dest, char far src) ; char far *strcat(char far dest, char far src) ; Ces deux fonctions ressemblent celles dfinies dans la librairie standard du C (string.h), qui consistent respectivement la copie dune chane de caractres, et de la concatnation.

4 Ralisation de lexcutif temps rel.

97

4.4.2.1.2. Manipulation de donnes en mmoire Pour dplacer des donnes en mmoire nous allons rcrire la fonction : char far *memncpy(char far *src, char far *dest, int nbr) ; Copie un bloc de mmoire de taille nbr de ladresse src vers dest. 4.4.2.1.3. Conversion Dcimale - ASCII Pour pouvoir convertir un nombre (non sign) en une chane de caractres (ASCII) en vue dtre affiche : Const char far * decasc(unsigned long i) ; 4.4.2.1.4. Conversion Hexadcimale - ASCII Pour pouvoir convertir une chane de caractres (ASCII) en valeurs hexadcimales (ASCII) nous allons avoir recours la fonction : const char far * hexasc(const char far * ptr, int cpt) ; Elle nous va faire donc renvoyer une chane de caractres, dont le contenu sera en ASCII, et la smantique en hexadcimale. Notons que le nombre de caractre convertir est dfini dans cpt. 4.4.2.1.5. Rcriture des fonctions vspintf, printf Pour afficher une chane de caractres sur la sortie standard, nous allons dfinir trois fonctions : const char far * vprint(char far *chaine, char far *prm) ; void print(char far *str,...) ; void printk(char far *chaine, unsigned char couleur) ;

- La fonction vprint ainsi dfinie, permet de scanner la chane de caractres chaine, et de recenser les endroits o se prsente les paramtres, puis remplacer ces derniers par les valeurs rcupres, depuis le contenu de ladresse de pile prm correspondant au type dargument ainsi scann. Elle ressemble un peu la fonction dfinie dans la bibliothque standard C (stdio.h) sous le nom vsprintf. Cependant notre fonction est beaucoup plus simple et nous donnons ci-aprs les paramtres ou arguments reconnus. %d : valeur en dcimal non signe. %x : valeur en hexadcimal avec 4-digit. %X : valeur en hexadcimal avec 8-digit. %p ou %P : adresse mmoire sur 32-bit. %s : chane de caractres. %c : caractre. %% : caractre %.

4 Ralisation de lexcutif temps rel.

98

Rappelons que la convention du langage C, fait que les paramtres passs pour une fonction quelconque soient toujours empils avant lappel de fonction, dans le sens inverse au sens que nous avons dfini. Par exemple, en faisant, appel la fonction fct(arg1,arg2,arg3) ; largument arg3 sera le premier empil, puis suivi de arg2, et enfin arg1, avant bien sr lappel fct. Il est important de rappeler cette convention, dans la mesure o notre fonction vprint, va dpiler les valeurs passes en argument(trouves suivant lordre et partir de ladresse prm), et de les remplacer lintrieur de la chane scanne chaine, aux endroits o se prsentent les formats prsents prcdemment.

- La fonction print, pralablement dfinie, aura pour mission, dafficher sur la sortie standard (cran), la chane de caractres str, et ce, en tenant compte des ventuels paramtres pouvant tre passs en argument. Elle ressemble la fonction dfinie dans la bibliothque standard C (stdio.h) sous le nom de printf. Notre fonction print utilisera la fonction vprint, en lui passant le premier paramtre str, mais galement ladresse des ventuels paramtres. Cette adresse serait gale ladresse du pointeur str (c--d son adresse dans la pile) laquelle on rajoute 4, car la taille dune adresse mmoire de type FAR (segment : offset), prend 4-octet ou caractres. Donc le paramtre prm se voit alors attribu ladresse du premier paramtre de la fonction print ventuel (correspondant au trois points de largument print). La fonction print devra bien videmment appeler la routine daffichage que nous allons voir dans le prochain point. - La fonction printk crite en assembleur, est disant le bas niveau de la fonction print, car elle est responsable dappeler la routine BIOS daffichage (int 10h), en vue dafficher la chane de caractres chaine avec une couleur ou attribut couleur. En premier lieu, elle dtecte le mode dans lequel se trouve laffichage (graphique ou texte), si cest le mode texte, elle procde laffichage caractre par caractre de la chane chaine, en vrifiant chaque fois sil sagit dune tabulation ou un saut de ligne, car pour les deux cas, un traitement disant spcifique est entam. Les caractres sont affichs grce au service (int 10h) BIOS (ah=9) mais aussi avec (ah=0eh) (voir [Ms dos] pour plus de dtails). Si cest le mode graphique, nous allons utiliser ce moment-l que la fonction (ah=0eh), en vrifiant l aussi la prsence de tabulation et le saut de ligne. Notons que le saut de ligne et la tabulation sont conformment aux caractres dfinis en langage C (c--d respectivement \n et \t).

4 Ralisation de lexcutif temps rel.

99

4.4.2.1.6. Rcriture de Putchr Nous allons galement rajouter une fonction crite en assembleur : void putchr(unsigned char caractere, unsigned char couleur, int colonnes) ; qui permet, dafficher un caractre caractere avec une couleur ou attribut couleur, en le ressassant dans un nombre de colonnes colonnes.

(Les fonctions ainsi dfinies sont dans le source .\utils\16\ leurs prototypes seront dans le fichier .\include\kernel.h les couleurs ou les attributs sont dfinis dans le fichier .\include\couleur.h)

4.4.2.2.

Initialisation machine avec DTCT16

Nous pensons implanter une fonction DTCT16 appele depuis la fonction main , et qui aura pour rle de dtecter le processeur prsent dans le systme (sa frquence dhorloge ), la quantit de mmoire vive (RAM) disponible et les disques (lecteurs disques durs et disquesttes) prsents dans le systme en utilisant les routines BIOS . Nous devons au pralable initialiser les segments ainsi que la zone de pile, pour pouvoir ensuite appeler la fonction main (se trouvant dans .\16\kr16.cpp). Nous allons donc crire dans un fichier en assembleur (se trouvant dans .\16\start16.asm) effectuant cette initialisation, et qui sera concatn lors de ldition des liens au prcdent (fonction main), et sera considr alors comme le startup de la fonction main du langage C. Les informations ainsi collectes seront sauvegardes, dans une structure superstruct (adresse par convention 1000h :0101h), puis affiches sur lcran. Elle mettra aussi en place (par convention 6000h :0000h) le premier fragment dun gestionnaire que nous avons baptis basculeur, qui assurera le retour au mode protg (32bit), lors dune sortie du mode 32-bit vers le mode 16-bit. Elle fera depuis le disque de dmarrage, une copie temporaire de la partie 32-bit vers ladresse 9000h :0000 (par convention). Puis, elle active la ligne A20, en vue daccder aux 64Ko de la mmoire haute. Suite cela, elle pourra dplacer la copie temporaire 32-bit du noyau se trouvant 9000h :0000, vers ladresse physique dfinitive 0x100000. Une fois ceci fait, elle fera linitialisation de la table des segments (GDT) (par convention 4000h :0000), en vue de passer en mode protg. Ce dernier sera activ par la suite, pour lguer ensuite le contrle la partie 32-bit charge. Nous allons dtailler davantage les sous routines auxquelles, la fonction DTCT16 fait rfrence durant son excution, dans les prochains sous paragraphes qui suivront.

4 Ralisation de lexcutif temps rel.

100

4.4.2.2.1. Dtection de la CPU Pour pouvoir dtecter la CPU (identit et frquence dhorloge), nous allons dvelopper une fonction en assembleur, dont le prototype en C est : const char far * init_cpu(char nbr); Cette fonction va retourner suivant le paramtre nbr, lidentit du constructeur de la CPU, son numro didentification, ou sa frquence dhorloge. Respectivement, les valeurs de nbr seront 0,1, ou 2.

Lidentit du constructeur est obtenue grce linstruction du PENTIUM : cpuid, en forant avant cela, le registre EAX zro. La chane de caractres retourne contenant lidentit du constructeur serait la concatnation des valeurs des registres EBX,EDX,ECX. En mettant la valeur 1 dans EAX, linstruction cpuid renvoie dans EAX le numro didentification de la CPU.

Pour dtecter la frquence dhorloge de la CPU, nous allons avoir recours linstruction du PENTIUM : rdtsc, qui fournit le nombre de cycles passs, et ce, depuis la mise sous tension de la CPU. Nous devons en premier lieu, inhiber toutes les interruptions en ne laissant que celle du timer. Pour ce faire, nous allons reprogrammer le PIC 8259A (matre et esclave) en masquant les interruptions arrivant sur les lignes IRQ1IRQ15 et ne laisser que IRQ0 (la programmation du PIC sera vue plus en dtail dans les prochains paragraphes). En vue de mesurer la frquence dhorloge de la CPU, nous allons effectuer deux prlvements des cycles passs grce rdtsc. En effectuant la premire mesure, nous allons avoir le nombre de cycles retourns par rdtsc, dans les registres EDX : poids forts EAX :poids faibles. Aprs quoi, nous allons sauver temporairement ces valeurs dans EBX et ECX respectivement. Nous allons sparer le deuxime prlvement du premier, avec linstruction hlt. Cette dernire consiste bloquer la CPU, tant quil n y a pas dinterruptions. Or nous avons inhib toutes les interruptions, sauf celle du timer, ce qui revient dire que, la CPU se bloquera durant un top dhorloge du timer. Ce dernier est programm par le BIOS, de faon fournir environ 18,206 tops/seconde. En faisant le deuxime prlvement, nous allons lui retrancher la premire valeur mesure (sauve dans EBX, ECX), et ce, pour avoir le nombre de cycles pass depuis le premier prlvement, autrement dit, le nombre de cycles passs depuis un top dhorloge. Cette diffrence sera divise alors par (1/18,206), 6 pour avoir la frquence en Hz puis sur 10 pour avoir la frquence en Mhz.

4 Ralisation de lexcutif temps rel.

101

4.4.2.2.2. Mmoire tendue et conventionnelle Pour pouvoir dtecter la quantit de mmoire disponible, nous allons implanter la fonction crite en assembleur dont le prototype en C est : unsigned long init_ram(short int prm); Cette fonction nous renvoie suivant la valeur de prm, la quantit de mmoire tendue (RAM) ou la quantit de mmoire conventionnelle. Respectivement les valeurs 0 ou 1 du paramtre prm. Pour avoir la quantit de mmoire tendue prsente dans le systme, nous allons la lire partir du CMOS, lemplacement 31h(poids forts) et 30h(poids faible de la quantit de mmoire). Sachant que pour lire/crire une valeur se trouvant lemplacement quelconque y du CMOS, il suffit denvoyer la valeur y au port 70h, puis de lire/crire le contenu depuis/dans le port 71h. Idem pour la mmoire conventionnelle, il suffit de la lire 16h(poids forts) et 15h (poids faibles de la mmoire conventionnelle).

4.4.2.2.3. Dtection des disques Nous devons recenser les disques attachs notre systme, en vue de pouvoir y accder ventuellement. Pour ce faire, nous allons utiliser la routine BIOS (int 13h). Pour recenser les units de disquettes disponibles, nous devons mettre dans le registre DL, la valeur zro indiquant ce type dunit, la valeur de la fonction quant elle, sera de 8 place bien sr dans AH. Pour damples informations, le lecteur peut consulter [Ms dos]. Lors de cette dtection, nous allons principalement sauver dans la structure, les informations comme le nombre de cylindres, de secteurs, et de ttes. Idem pour les disques durs (avec DL=80h). (La dtection des disques, se trouve dans le fichier .\include\disq16.h) 4.4.2.2.4. Sauvegarde dinformations hardware Nous devons sauvegarder les informations collectes sur le matriel (CPU, mmoire ), dans un emplacement mmoire que nous allons devoir dfinir comme rserv ; comme nous lavons dj nonc et par convention, nous utiliserons pour cette sauvegarde une zone mmoire 1000h : 0001h ou en adresse physique 0x10001. Sachant que 1000h :0000h a t rserve par le boot, pour sauvegarder lidentit du lecteur de dmarrage. Pour cela, une structure en C superstruct sera dclare ladresse 1000h :0001h, en vue de sauvegarder les informations que nous venons de citer. (La structure est dclare dans le fichier .\include\dtct16.h)

4 Ralisation de lexcutif temps rel.

102

4.4.2.2.5. Mise en place du basculeur 16-bit Dans le PENTIUM, nous avons principalement deux modes, le mode rel et le mode protg, citons galement le mode virtuel. Pour le premier mode (mode 16-bit), il sagit dun fonctionnement en mode 8086, tandis quau deuxime (mode 32-bit), cest un mode compatible avec le 80386. Les deux modes sont compltement distincts. Les routines BIOS oprent en 16-bit (mode rel), nous ne pouvons alors les utiliser en tant dans le mode 32-bit. Ce qui revient dire, quil va falloir rcrire tous les drivers de priphriques standards pour le mode 32-bit. Nous nous sommes dit alors la chose suivante : Pourquoi ne pas faire commuter le processeur du mode 32-bit vers le mode 16-bit, chaque fois quil y a accs au priphrique (exemple : E/S disque ) ?. Ceci freinera considrablement le systme, mais cest un compromis que nous allons devoir faire, et ce, pour des raisons de simplicit. Pour ce faire, nous avons pens mettre en place un serveur que nous avons baptis basculeur, qui nous pouvons depuis le mode 32-bit, solliciter pour une entre/sortie (doit tre bien sr, prise en charge par le basculeur). Le basculeur doit alors sauver le contexte en cours, mais aussi les paramtres et lidentit de lentre/sortie. Une fois ceci fait, il passe en mode rel, et excute la fonction adquate dans la partie 16-bit, cette dernire tant base sur les routines BIOS. Le basculeur doit retourner en mode protg et restaurer le contexte, tout en mettant disposition de lappelant, les rsultats de lentre/sortie effectue. Toute cette gymnastique doit tre prise en charge de part et dautre (c--d depuis le mode rel et le mode protg). Dans ce paragraphe nous allons dcrire, uniquement le basculeur16-bit. Nous allons crire en assembleur le basculeur 16-bit, puis le copier ladresse mmoire, 6000 :0000h (par convention). Il faut savoir que le basculeur 16-bit ne sera sollicit que par sa partie complmentaire (basculeur 32-bit). Nous pouvons alors tre sr, que les premires instructions effectuer par le basculeur 16-bit, se drouleront en mode protg. Le basculeur 16-bit devra alors en premier lieu, faire dsactiver la pagination (ventuellement active), et ce, en mettant le bit-31 (PG) du registre CR0 zro. Aprs quoi, les registres de segmentation (DS,ES,SS) sont chargs 20h, qui correspond au segment de donnes 16-bit dans la GDT (voir le paragraphe sur linitialisation de le GDT), puis force le bit-0 du registre CR0 0 pour passer en mode rel. Une instruction de saut vers 6000h :$+4 doit tre faite, afin de mettre jour la file des instructions pour le mode 16-bit dune part, et dautre part, pour charger le registre CS avec une valeur de segment valide en mode 16-bit (segment :offset). (voir le paragraphe sur le passage au mode 32-bit). La CPU est dsormais en mode rel, il faudrait alors recharger les segments de donnes pour pointer sur le segment du basculeur 16-bit. Autrement dit, (DS,ES,SS) vont tre forcs 6000h. Il doit aussi initialiser le registre SP pour la pile (0FFF0h), et de redfinir la table des interruptions (IDT), avec comme adresse de base 0 et de taille 3FFFh (255 vecteurs dinterruption en mode rel de taille 4-octect), et ce, moyennant linstruction lidt (voir le paragraphe initialisation de la table dinterruptions).

4 Ralisation de lexcutif temps rel.

103

Le basculeur 16-bit, doit prlever lidentit de la fonction, depuis la zone des paramtres, ladresse 9000h :0050h (par convention), sachant que les premiers 4Fh octets du segment 9000h sont rservs par convention pour la sauvegarde du contexte en mode 32-bit. Suivant la valeur ainsi trouve, il excutera la fonction correspondante, et nous donnons dans ce qui suit, les valeurs associes pour identifier les fonctions :

printk putchr write read

id=1 id=2 id=3 id=4

Notons aussi que les paramtres de ces fonctions, sont retirer depuis ladresse 9000h :100h (par convention), et le buffer ou la zone de donnes (comme par exemple les chanes de caractres afficher ) est ladresse 9000h:0200h (par convention). Une fois la fonction, sollicite, est excute, le basculeur 16-bit doit retourner en mode protg puis lguer le contrle au basculeur 32-bit qui est ladresse physique 0x63000 (par convention), et ce, aprs avoir bien sr, charg les valeurs de retour de la fonction ainsi excute le cas chant. (voir paragraphe : passage en mode protg, pour comprendre la manire dy procder). Remarque Lors de lcriture de ce fragment en assembleur, nous avons tenu compte du fait, que ladresse physique de base de ce programme est 0x60000, et ceci, pour pouvoir intervenir sur le contenu des emplacements dans le programme, dans le cas dun adressage indirect. (Le basculeur 16-bit se trouve dans le fichier source .\16\bascul.asm)

4.4.2.2.6. Chargement de la partie 32-bit Comme nous lavons dj soulign, les parties de lexcutif seront concatnes sur disque. Puisque nous avons charg jusqu prsent 1 secteur physique de boot, et 18 secteurs pour la partie 16-bit. Nous aurons donc notre partie 32-bit au 19ime secteur physique sur disque. Ce qui est quivalent dire que sur une disquette 3pouces1/4, ayant 18 secteurs/tte et 2ttes/cylindre, nous allons avoir lemplacement disque de la partie 32-bit comme suit : Cylindre =0, Tte=1, secteur=1. Il suffit aprs quoi, de faire charger ces paramtres dans les registres du processeur, comme ctait le cas dailleurs lors du chargement de la partie 16-bit, et de lire 18 secteurs vers ladresse temporaire 9000h :0000 (en faisant appel la routine BIOS int 13h) , puis dincrmenter ladresse de 18*512 octets, ainsi que le paramtre Tte de 1 pour lire davantage 18 autres secteurs (tant donn que la partie 32-bit sera plus importante que la partie 16-bit en terme de taille). Aprs activation de la ligne A20 (voir prochain paragraphe), nous allons copier cette partie temporaire ainsi charge, vers une adresse physique dfinitive, se trouvant 0x100000 (par convention).

4 Ralisation de lexcutif temps rel.

104

4.4.2.2.7. Activation de la ligne A20

Il faut savoir que le PENTIUM en mode rel (mode de dmarrage par dfaut), se comporte comme un processeur 8086. Il ne peut alors dans ce mode adresser plus de 1 Mo. Autrement dit, lespace dadressage en mode rel est dans lintervalle suivant : [0000h :0000 FFFFh :FFFFh]. Nous pouvons nanmoins activer la ligne A20 du bus pour que le processeur puisse accder aux 64Ko de mmoire immdiatement suprieure ladresse FFFFh :FFFFh. Cest ainsi que ladresse FFFFh:0010h correspondante bien sr ladresse physique 0x100000 (car 0x100000=FFFF*10h+10h) peut tre accde depuis le mode rel du PENTIUM. Pour ce faire, nous allons devoir lire la valeur du port 92h, puis faire positionner 1, lavant dernier bit des poids faibles de la valeur lue, et de lcrire dans le port 92h. 4.4.2.2.8. Initialisation de la table des segments (GDT) En vue de passer en mode protg et dexcuter la partie charge (partie 32-bit), nous sommes obligs dinitialiser la table des segments (GDT : Global Descriptor Table) du PENTIUM. Rappelons que la GDT, est une table implante en mmoire physique, dont ladresse est sauvegarde dans le registre GDTR (accessible uniquement par les instructions LGDT ou SGDT), contenant la description de chaque segment qui doit tre ventuellement charge dans un registre de segmentation (CS, DS, ES, SS, FS, GS). Le descripteur de chaque segment fait 8 octets. Cest alors quen ajoutant chaque fois la valeur 8 lindex, que nous pouvons indexer ou parcourir lensemble des descripteurs segment prsents dans cette table. Le processeur ajoute bien sr, en vue de localiser un segment dans la table, ladresse de base se trouvant dans GDTR, autrement dit ladresse mmoire physique de la GDT. Notre table va rsider par convention ladresse 4000h :0000 (0x40000 en adresse physique) et doit tre remplie dinformations sur les segments utiliser. Chaque descripteur de segment est dfini comme suit [Intel]: 32 bits BASE 0-15 D A BASE 24-31 G / 0 V LIMIT 16 - 19 P B L LIMIT

0
BASE 16-23

DPL

TYPE

Figure 4.2. Descripteur segment du PENTIUM.

4 Ralisation de lexcutif temps rel.

105

La base, sur 32-bit, est l'adresse linaire o dbute le segment en mmoire. La limite, sur 16-bit, dfinit la longueur du segment. Si le bit G est 0, la limite est exprime en octets, sinon, elle est exprime en nombre de pages de 4Ko. Le type dfinit le type de segment, comme code, donnes ou pile. Le bit S est mis a 1 pour un descripteur de segment et a 0 pour un descripteur systme (un genre particulier de descripteur que nous verrons par la suite). Le DPL indique le niveau de privilge du segment (0-3). Le niveau 0 correspond au mode super-utilisateur. Le niveau 3 est souvent utilis pour le mode utilisateur. Le bit P est utilis pour dterminer si le segment est prsent en mmoire physique. Il est 1 si c'est le cas. Le bit D/B prcise la taille des instructions et des donnes manipules (16-bit ou 32-bit). Il est mis 1 pour 32-bit. Le bit AVL est librement disponible. Dans la table GDT du PENTIUM, le premier descripteur (descripteur 0) est rserv par Intel. Nous devons alors dbuter au prochain, autrement dit lemplacement 8 (taille dun descripteur de segment). Nous envisageons une table avec un descripteur de code (index 8) de privilge 0 et adressant tout lespace dadressage (4Go). Pour le segment de donnes (index 0x10), nous ferons de mme, sauf quune diffrence est noter bien sr au niveau du champ type. La pile utilisera galement ce segment de donnes. Le troisime segment que nous aurons dclarer (index 0x18), concerne le segment de code en mode 16-bit, ncessaire pour prendre la main en passant du mode 32-bit au mode 16-bit. Un segment de donnes (index 0x20) sera associ au prcdent, et prendra en charge laccs aux donnes lors dun basculement du mode 32-bit au mode 16-bit. Puis, nous devons prendre en charge les segments pour le mode utilisateur. Ceci pour une ventuelle utilisation despaces distincts entre le noyau et lutilisateur. Pour cela, nous allons dclarer un segment de code utilisateur (index 0x28) avec le privilge 3 (le plus faible privilge) et son segment de donnes/pile associ (index 0x30) galement avec le plus faible privilge. Une fois les segments dclars, nous allons copier cette table lemplacement spcifi (0x40000), puis de charger avec linstruction lgdt, ladresse de cette table ainsi que sa taille lue depuis un emplacement mmoire, autrement dit, cette instruction doit avoir un adressage indirect, dont le contenu atteindre sera ladresse de la GDT et sa taille.

(Linitialisation de la GDT se trouve dans le fichier source : .\16\init_gdt.asm)

4 Ralisation de lexcutif temps rel.

106

4.4.2.2.9. Passage en mode protg Nous pouvons prsent et aprs avoir charg la partie 32-bit ladresse mmoire physique 0x100000, et initialis la table GDT, pouvoir passer en mode protg. Pour ce faire, il suffit de positionner le bit-0 du registre CR0 1. Il va falloir avant ceci, inhiber les interruptions, tant donn que nous navons pas initialis au pralable une table de vecteurs dinterruption (IDT). Aprs cela, nous devons vider la file des instructions (prsentes dans le cache), et ce, en faisant un saut inconditionnel, vers linstruction suivante. Nous devons ensuite charger les descripteurs segment de donnes (DS, ES, SS, FS, GS) avec la valeur index correspondante dans la table GDT. Pour notre cas elle serait de 0x10. Nous sommes prsent en mode protg, nous devons faire un saut (FAR) vers la partie 32-bit charge. Puisque le langage assembleur MASM ne supporte pas ce genre dinstruction (saut vers CS :EIP), nous devons avoir son code instruction. Pour ce dernier, il sagit de prcder le tout dune valeur 66h, afin de dire au processeur quil devra prendre le format 32-bit de linstruction, suivi de linstruction de branchement vers ladresse de la partie 32-bit charge (CS=08 :EIP=100000h) dont le code est : 0eah, 00100000h,08. Bien sr, la valeur 8, correspond lindex 8 (code segment) dans la table GDT. (La fonction qui permet le passage en mode protg est crite en assembleur, se trouvant dans le fichier source : .\16\mod_prtg.asm).

4.4.3.

Partie 32-bit (mode protg)

Cette partie sera disant de base, pour le reste des parties qui seront ralises. En effet, nous allons se baser sur cette partie pour implmenter les stratgies et politiques de notre excutif. Cest en partie pour cette raison, que nous allons devoir considrer les parties venir, savoir, les modules temps rel et linterface utilisateur, comme tant rattaches la partie 32-bit fortiori en terme de compilation. Autrement dit, nous allons considrer la partie 32-bit, comme la partie mre de toutes les parties venir, tant donn que ltat du processeur, dans lequel sopreront ces modules ainsi que leur compilation se fera en mode 32-bit. Notons que les fonctions utilitaires dfinies dans la partie 16-bit, seront utilises et recompiles pour ce prsent mode. Un peu comme la partie 16-bit, nous devons tablir quelques initialisations, avant le lancement de la fonction main de la partie 32-bit. Nous allons alors crire en assembleur un programme qui prendra le premier contrle ds attribution par la partie 16-bit (lors du passage en mode protg). Ce programme fera linitialisation de la pile ladresse physique 6FFFFCh (par convention) en forant ESP cette valeur, puis invoquera la fonction main de la partie 32-bit. (Le startup pour la partie 32-bit est localis dans le ficher source : .\32\start32.asm.) (La fonction main quant elle, sera place dans le fichier source: .\32\kr32.cpp.) (Les fonctions utilitaires pour le 32-bit sont dans le source : .\utils\32).

4 Ralisation de lexcutif temps rel.

107

Une fois la fonction main est appele, celle-ci son tour fera un appel pour mettre en place la deuxime partie du basculeur(basculeur 32-bit). Ce dernier est bien sr complmentaire celui dj prsent (basculeur 16-bit). Pour prendre en charge les interruptions matrielles et logicielles, une routine est appele pour mettre en place les vecteurs dinterruption et les routines correspondantes, dans une table ddie en mmoire appele IDT dans le PENTIUM. Puis une fonction est appele pour programmer le PIC 8259A, en vue de prendre en charge les lignes dinterruptions IRQ suivant les niveaux dfinis dans la IDT. Des fonctions dinitialisation temps rel sont appeles, pour aprs quoi, faire appel lapplication temps rel de lutilisateur (application_tr). Nous allons dtailler dans les sous paragraphes suivants, les diffrentes routines cites cidessus, cependant, vu son importance, le module temps rel sera considr comme paragraphe indpendant.

4.4.3.1.

Mise en place du basculeur 32-bit

Comme nous lavons dj soulign, cette partie est en dfinitive, complmentaire celle prsente dans le paragraphe portant sur le basculeur 16-bit. Cette partie crite galement en assembleur fera, la copie du programme basculeur 32-bit ladresse mmoire physique 0x63000 (par convention). A remarquer que cette partie se logera juste au-dessus de la partie basculeur 16-bit, mais sans pour autant avoir un quelconque chevauchement. Lors dune ventuelle extension, il faudrait penser ce que les deux parties soient distinctes et de veiller garder leur intgrit en mmoire. Ajoutons le fait que les instructions, du basculeur 16-bit sont diffrentes de celles du basculeur 32-bit, tant donn que nous ferons une compilation diffrente et dautant plus que le mode du processeur dans chacun des cas est diffrent (mode rel et mode protg). La routine basculeur 32-bit, commence par enregistrer le contexte processeur par le biais de la fonction sauver_context, savoir, les registres gnraux respectivement (EAX, EBX, ECX, EDX, DS, ES, SS, EDI, ESI, EBP, ESP, CS, EIP) mais aussi, ladresse et la taille des tables IDT et GDT (avec les instructions respectivement sidt et sgdt) et ventuellement le rpertoire des pages CR3. Le contexte est comme nous lavons dj vu, sera enregistr partir de ladresse physique 0x90000 (par convention). Notons que pour le registre EIP (conteur ordinal), celui-ci nest pas accessible par instruction, et nous allons seulement enregistrer un emplacement connu du programme que nous avons appel retour, et partir de-l, le basculeur 32-bit poursuivra son excution lors du retour depuis le basculeur 16-bit.

4 Ralisation de lexcutif temps rel.

108

Une fois le contexte enregistr, nous devons faire un saut (FAR) vers le basculeur 16-bit. Ce dernier comme nous lavons suppos, se logera ladresse mmoire physique 0x60000. Etant donn que lassembleur MASM, ne supporte pas les sauts longs, nous devons encore du coup, crire le code de linstruction correspondante (jmp far 18h :60000h). Bien sr 18h est lindex du descripteur de code 16-bit, dclar dans la GDT. Le code instruction du saut, doit tre prcd par 67h tant donn que nous sommes sur le point de passer dun segment de code 32-bit vers un segment de code 16-bit, sinon une erreur de protection gnrale se produira et la machine va redmarrer puisquil n y a pas encore de prise en compte dinterruptions ce niveau-l. Au retour (point retour cit prcdemment), nous allons bien videmment faire linverse de ce qui a t fait, notamment en restaurant le contexte de la CPU depuis ladresse physique 0x90000. Nous ajoutons le fait que le passage de paramtres ventuels pour les fonctions excuter en mode rel, que nous avons vu dans le basculeur 16-bit, ne seffectue pas ce niveau (basculeur 32-bit), mais il appartient la fonction (appelante), de prendre en charge lempilement ou lenregistrement de ses paramtres, avant lappel au basculeur 32-bit. Cest pour cela que nous avons song dailleurs, dcrire les fonctions dE/S prise en charge par le basculeur 16-bit, sous forme de macros, en langage C, afin de procder lenregistrement de paramtres, de lidentifiant de la fonction et lappel au basculeur 32bit, chaque fois quil y a appel de fonctions dE/S prise en charge depuis le mode protg. (Le basculeur 32-bit est dans le fichier source suivant : .\32\bascul.asm) 4.4.3.2. Initialisation de la table des vecteurs dinterruption (IDT)

Cette table permet la prise en charge des interruptions, en contenant des descripteurs (voir figure 4.3) ayant les adresses mmoire physique des routines dinterruptions, pour chaque interruption prise en charge. Cette table est consulte par le processeur chaque interruption. Son adresse en mmoire physique et sa taille sont initialises avec linstruction lidt, et charges dans le registre IDTR du processeur. Nous allons devoir mettre en place cette table (IDT), en vue de prendre en charge les interruptions.

Figure 4.3. Descripteur dinterruptions[Intel].

4 Ralisation de lexcutif temps rel.

109

Pour ce faire, nous allons crire un ensemble de fonctions, qui permettent la mise en place de la IDT, et les routines dinterruption correspondantes. init_idt est une fonction appele depuis la fonction principale main, qui permet justement la mise en place de la IDT, et ce, en appelant son tour, la fonction : int set_idt(void* offset, short int type,short int numero_descripteur) ; selecteur, short int

Cette fonction permet de remplir la IDT, en ayant comme paramtres, les informations du descripteur dinterruption mettre en place. Le paramtre offset permet de spcifier ladresse physique de la routine dinterruption traiter. Le paramtre selecteur permet de spcifier le segment de code avec lequel se fera le traitement de la routine dinterruption (la contenu de CS lors du traitement de linterruption). Le paramtre type permet de spcifier le type du descripteur (voir figure 4.3). Le paramtre numero_descripteur permet de spcifier le numro de linterruption, en vue de placer le descripteur dinterruption, lindex correspondant la IDT. Sachant que la IDT peut tre parcourue, en ajoutant chaque fois 8-octet son index (taille du descripteur).

Nous allons prendre en charge les 17 NMI (Non Maskable Interrupt), dont le numro dinterruption varie de 0 17 (convention Intel), les autres jusqu 39h sont rserves par Intel. Nous devons galement prendre en charge les interruptions provenant des priphriques (IRQ), notre convention est dassocier le numro 50h linterruption provenant de lIRQ0 jusqu 57h (IRQ7). Puis 60h pour IRQ8 jusqu 67h (IRQ15). Il faudrait alors, appeler au sein de la fonction init_idt la fonction set_idt 17 fois (correspondent aux NMIs), ajoutant 16 fois (correspondent aux IRQs). Ce qui fait 33 appels de la fonction set_idt. Cette dernire bien sr est appele, avec des paramtres diffrents, tant donns les diffrents numros des interruptions et les adresses des routines dinterruption correspondantes. Notons que ladresse o se logera la IDT est par convention ladresse physique 0x50000. Cette adresse sera prise comme adresse de base par la fonction set_idt, pour pouvoir indexer la table et de mettre en place les descripteurs dinterruption. Nous devons ensuite, indiquer au processeur lemplacement et la taille de la IDT ainsi cre, et ce, en les chargeant avec linstruction lidt, avec le mme format de paramtres que ceux de la GDT prcdemment vue. Nous devons alors lui spcifier avec un adressage indirect, ladresse mmoire physique de la IDT (0x50000 par convention) ainsi que sa taille (256 niveaux * 8 octects des descripteurs = 2048 octects). (Les fonctions init_idt et set_idt sont dans le fichier source suivant : .\32\init_idt.cpp).

4 Ralisation de lexcutif temps rel.

110

4.4.3.2.1. Les routines dinterruption Pour une routine dinterruption dans notre systme, nous allons la prendre en charge avec deux fonctions. Une de ces fonctions sera crite en assembleur, en vue de faire des prtraitements avant le traitement dinterruption. Lautre fonction sera crite en C, pour traiter linterruption proprement dite. Nous devons alors programmer les 33 fonctions en assembleur et en C, tant donn le nombre dinterruptions prendre en charge dans la IDT. Cependant, et pour des raisons de simplicit, nous nallons pas crire le code qui traitera les NMIs, nous nous contenterons dafficher un message pour signaler larrive de linterruption, et ventuellement faire une boucle sur elle-mme, dans le cas dune erreur fatale (Erreur de protection gnrale ). Ce raisonnement est aussi valable pour les routines prenant en charge les interruptions matrielles. Nous nous contenterons l aussi, uniquement des priphriques prendre en charge (le clavier(IRQ1), PIC esclave(IRQ2), lhorloge temps rel (IRQ8)). Pour les autres IRQs, leur routine ne disposeront daucun traitement. Ce sont les routines crites en assembleur, qui aprs leur ralisation du prtraitement dinterruption, vont appeler les fonctions crites en langage C. Donc, lors de la mise en place de la IDT, nous devons spcifier ladresse des routines crites en assembleur, et non pas celle crite en C. (Les routines crites en assembleur sont dans le fichier source : .\32\it.asm. Les fonctions traitant les interruptions sont dans le fichier suivant : .\32\ints.cpp).

4.4.3.3.

Programmation du PIC 8259A

Pour que nous puissions raliser physiquement, ce que nous avons suppos lors de la mise en place de la IDT, savoir, la prise en charge des interruptions de priphriques (IRQ), nous devons programmer le PIC, de telle sorte ce quil dlivre les numros de demande dinterruptions compris entre [50h - 57h] correspondant [IRQ0-IRQ7] pour le matre, et [60h - 67h] correspondant [IRQ8 IRQ 15] pour lesclave. Nous allons donc faire une redirection des IRQ, pour quelles ne puissent pas entrer en conflit avec les interruptions NMI du PENTIUM rserves par Intel. Par exemple, et avec cette configuration, le PIC fournira la valeur 51h au processeur chaque interruption venant du clavier (IRQ1), rappelons que cette valeur, va servir au processeur comme index dans la table des vecteurs dinterruption (IDT) pour rcuprer le vecteur dinterruption partir de cet emplacement et dexcuter par la suite la routine correspondante (driver clavier dans ce cas).

4 Ralisation de lexcutif temps rel.

111

Pour ce faire, nous allons en premier lieu initialiser le PIC matre et esclave, et ce, en mettant respectivement dans les ports 20h et A0h la valeur 11h. Cette valeur va servir en partie indiquer au PIC que nous allons lactiver (ICW1) grce la valeur 1 du poids fort, et dutiliser le ICW4 indiqu par la valeur 1 du poids faible. Puis envoyer les valeurs retourner pour IRQ0 et IRQ8 respectivement au matre et esclave, et comme nous lavons nonc, nous allons utiliser les valeurs 50h et 60h. Il faudrait alors envoyer ces valeurs respectivement au matre et esclave (ICW2), sur les ports 21h et A1h. Il faudrait par la suite initialiser le ICW3, en envoyant la valeur 4 au matre et la valeur 2 lesclave respectivement au port 21h et A1h. Pour la valeur 4 = (000100)2 qui est mise dans ICW 3 de lesclave, la position du 1 dans le mot, va indiquer la broche laquelle lesclave est attach, et dans ce cas, elle correspond la broche numro 2, autrement dit IRQ2. Idem pour la valeur 2 mise dans le ICW3 de lesclave. Nous avons spcifi dans la configuration (ICW1) que nous allons utiliser le ICW4. Pour ce dernier, nous allons envoyer la valeur 1 au port 21h et A1h respectivement du matre et esclave. Cette valeur va indiquer aux PICs, quil sagit dun mode normal 8086. (voir documentation du PIC 8259A pour plus de dtails). La fonction : void init_pic() ; sera charge de faire cette initialisation. Aprs que cette dernire soit faite, les deux paramtres passs en argument la fonction : void masquage_it(unsigned ICW2_Esclave) ; char ICW2_Master, unsigned char

vont servir masquer/dmasquer les interruptions, suivant le fait que le bit 1 sert de masquage et 0 pour dmasquer linterruption correspondante la position du bit dans le mot. (Les paramtres sont envoyer respectivement vers le port 21h et A1h). Comme nous lavons dj abord, nous allons uniquement pour des raisons de simplicit, prendre en charge le clavier(IRQ1), le PIC esclave(IRQ2), et lhorloge temps rel (IRQ8). Ce qui revient dire, envoyer les valeurs suivantes : 0xF9 et 0xFE respectivement au matre et lesclave. (Les deux fonction ci-dessus, se trouvent dans le fichier source : .\32\init_pic.cpp).

4 Ralisation de lexcutif temps rel.

112

4.5.

Module temps rel

Une fois linitialisation de la machine est faite, la fonction principale main fait appel la fonction application_tr, dans laquelle se trouve le code utilisateur (module dapplications temps rel). Comme nous lavons nonc lors de la conception, lutilisateur va pouvoir lancer des tches temps rel, dans lespace dadressage du noyau. Ceci sous-entend, que lapplication temps rel de lutilisateur va faire partie du noyau. Ce qui revient dire aussi, que lutilisateur devra recompiler le noyau, chaque fois quil y a modification dans le module dapplication temps rel (fonction application_tr). Du point de vue utilisateur, son application sera dveloppe au sein de la fonction application_tr. Mais du point de vue noyau, le code sera considr comme une poursuite dexcution ou mme un simple appel de fonction application_tr. Pour pouvoir dvelopper ses applications temps rel, lutilisateur pourra manipuler des fonctions pour crer/supprimer des tches et des smaphores, implantes au niveau module des tches. Il dispose galement dun ensemble de fonctions utilitaires pour les tches, et de gestion du temps. Lutilisateur na pas, se soucier, quant lordonnancement des tches temps rel. Celui-ci doit lui tre totalement transparent, et dautant plus que les fonctions dordonnancement sont implantes de sorte, ne servir que la politique dordonnancement, et noffrent aucun service lutilisateur. Nous allons aborder dans les sous paragraphes suivants, les diffrentes fonctions permettant la manipulation des tches (ct utilisateur et ordonnancement), des smaphores, mais aussi de fonctions pour la manipulation du temps (extension de lAPI). (la fonction application_tr doit tre crite par lutilisateur dans le fichier source : .\treel\appli_tr.cpp). 4.5.1. Cration dune tche Pour crer une tche temps rel priodique/apriodique, lutilisateur doit appeler la fonction : int creer_tache(THREAD thread, DATE ri, TIME ci, TIME pi, unsigned int num_file_sem) ; Qui permet dinitialiser une tche temps rel priodique, dont le code ou la routine dexcution associe est indiqu par le paramtre thread, qui nest rien dautre quune adresse vers une fonction excuter. A noter que THREAD est de type (void *). La premire date de rveil ri de cette tche, est spcifie dans le deuxime paramtre (par rapport lhorloge logique absolue), dont le type DATE est double (64-bit). Ci et Pi indiquent respectivement la capacit dexcution de la tche et la priode de la tche (en units dhorloge logique absolue) et TIME est de type unsigned long (32-bit). num_file_sem indique le numro de la file des smaphores associs cette tche, ce numro est spcifi par lutilisateur lors de la cration de la file (voir add_semaphore).

4 Ralisation de lexcutif temps rel.

113

Pour crer une tche apriodique, il suffit de mettre la priode de la tche 0. Ce qui revient dire que le paramtre Pi=0. A ce moment-l, le paramtre ri (date de rveil) devient inutile, dans la mesure o la tche apriodique survient comme son nom lindique dune manire compltement alatoire. Lors de lappel la fonction creer_tache, celle-ci recherche dabord un contexte libre en appelant la fonction get_tache_libre. Cette dernire parcourt, le tableau global de structures de contexte des tches (la taille du tableau est de 256 par convention, dfinie par max_tache), en vrifiant lintrieur de chaque structure, le champ nomm magic, sil contient la signature ou la valeur 0xBABA. Si tel nest pas le cas, elle retourne le numro de la structure libre (non signe), sinon un nombre ngatif (-1) est renvoy. Le numro positif renvoy par get_tache_libre, va servir didentifiant la tche crer. Le cas contraire, la fonction creer_tache va aussi renvoyer la valeur (-1) indiquant lutilisateur, limpossibilit de crer la tche. Sil y a un espace libre pour la tche, la fonction creer_tache va tester la valeur du paramtre Pi (priode) en vue de dterminer le type de la tche (priodique/apriodique). Sil sagit dune tche priodique, il faudrait tester si cette tche est susceptible dutiliser des ressources (smaphores), et ce, en vrifiant la file des smaphores associe aux tches dont le numro est donn en paramtre (num_file_sem). Si la file nest pas vide, il faudrait alors sauver cette valeur dans le contexte de la tche, et plus prcisment dans le champ : sched.ressource.file en indiquant aussi que la tche utilise des ressources, en mettant une signature 0xFAFA dans le champ sched.ressource.magic. Puis remplir les autres champs, id (identifiant de la tche), sched.pi (la priode), etat (mis ltat PRET), sched.type (mis PERIODIQUE), mais galement la date de rveil sched.ri, et le compteur associ sched.cpt_ri (sur lequel, le calcul de la prochaine date de rveil est effectu). Pour initialiser la zone de pile (2048 octets par convention pour chaque tche), un espace est rserv dune faon statique lemplacement mmoire physique 0x5FFFFE (par convention), et cette adresse sera considre comme le bas de la pile pour la premire tche. Cest ainsi que pour rserver un espace de pile pour la tche i, il suffit de retrancher la valeur ((i+1)*2048) ladresse 0x5FFFFE, pour retrouver le bas de la pile de la tche i. A noter que la premire zone ( partie de 0x5FFFFE) est rserve pour une future utilisation do la valeur du (i+1) dans la formule prcdente. La valeur retrouve sera sauve dans le contexte de la tche (contexte hardware) et plus prcisment dans le champ : tss.esp et de faire charger cet emplacement mmoire, ladresse de retour une fois termine qui, sera ladresse de la fonction : nop_thread(boucle sur elle-mme), dans la mesure o, les tches sont censes excuter les routines dune faon indfinie dans le temps, et dautant plus que nous naurons pas charger dautres modules une fois les tches termines. Le champ temp_pr, qui sauve la priorit, dans le cas dun hritage de priorit au sein dune section critique, est initialis 0 (indique quaucune priorit nest sauve). Le champ tss.eflags (relatif au hardware) sera initialis la valeur 0x200, pour faire positionner le bit IF de la CPU (Interrupt Flag) 1 et les autres 0.

4 Ralisation de lexcutif temps rel.

114

Une fois ceci fait, il faudrait calculer la priorit de la tche parmi celles prsentes dans le systme, et ce, conformment la politique RM. Cest ainsi que la fonction set_priorite est appele avec les paramtres ncessaires, savoir, lidentifiant de la tche, et la priode de la tche (rappelons que la priorit suivant RM, est plus grande pour les tches dont la priode est plus petite). La fonction set_priorite, repose sur un algorithme dinsertion, cest dire, que si nous avons les tches T1, T2 avec des priorits P1, P2, tel que P1<P2, et que nous aurons insrer une tche T3, dont la priorit savre intermdiaire au prcdentes, nous devons ce moment-l, donner la priorit de T2 T3, puis faire incrmenter celle de T2. Le raisonnement est analogue pour n tches. Comme nous lavons soulign dans la conception, les tches avec une mme priorit se verront attribuer une mme priorit. La fonction get_min_ri est ensuite appele par creer_tache, et ce, pour dterminer lidentifiant de la tche, avec la plus petite date de rveil, et qui sera mise dans la variable globale id_min_ri, en vue dtre utilise par lordonnanceur. La fonction add_file_pret, qui permet dinsrer une tche dans une file, sera appele avec les paramtres suivant : &tache[i] et &file_pret_periodque indiquant respectivement, ladresse de la tche et ladresse de la file des tches priodiques prtes. Aprs ceci, le compteur global des tches priodiques est incrment de 1. Sil sagit par contre dune tche apriodique (priode nulle), il faudrait ce moment-l, juste remplir le champ id (identifiant), sched.type (mettre la valeur APERIODIQUE), dappeler la fonction add_file_pret mais avec cette fois-ci ladresse de la file des tches apriodiques appele file_serveur. Puis dincrmenter le nombre de tches apriodique (variable globale nbr_tache_aperiodique).

Une fois lun des deux grands points faits (priodique/apriodique), il faudrait continuer charger le contexte de la tche, dont les informations cette fois-ci concernent aussi bien les tches priodiques que les apriodiques. Cest alors que la fonction creer_tache, charge le contexte de la tche (quelle soit priodique/apriodique) dinformations suivantes : Le champ sched.ci (la capacit dexcution pass en argument), sched.cpt_ci (indique la capacit courante de la tche, cest un compteur dailleurs auquel, la valeur de la capacit, sera dcrmente chaque top dhorloge). Le champ tss.eip, va tre charg de la valeur thread (pass en paramtre), indiquant ladresse du code ou de la routine excuter par la tche. Enfin la signature du contexte (comme quoi, le contexte est pris ou rserv par une tche), en mettant la valeur 0xBABA dans le champ magic. Et la valeur de lidentifiant de la tche est retourne lutilisateur. (la fonction creer_tache est dans le fichier source : .\treel\tache.cpp)

4 Ralisation de lexcutif temps rel.

115

4.5.2. Cration dun serveur pour les apriodiques Sil y a cration dune tche apriodique, celle-ci devrait tre alors associe la tche priodique serveur en vue dtre ordonnance. La fonction permettant de crer un serveur est : int creer_serveur(DATE ri, TIME ci, TIME pi) ; Les paramtres indiquent respectivement la date de rveil du serveur, sa capacit et sa priode (Idem aux paramtres creer_tache). Les valeurs de retour sont : Positive : serveur cr, et la valeur indique son identifiant. -1 : contexte de tche plein (erreur de cration). -2 : un serveur est dj cr (erreur de cration). Etant donn que la tche serveur est en dfinitive une tche priodique, la fonction creer_serveur fait alors entre autres, appel la fonction : creer_tache que nous avons dfinie dans le paragraphe prcdent. La fonction creer_serveur test sil y a prsence dun serveur dans le systme, en inspectant la valeur de la variable globale : etat_serveur, et renvoie une erreur (-2) si elle nest pas nulle. Sinon elle fait appel la fonction : creer_tache ((THREAD)&serveur_tache, ri, ci, pi, 255) ; serveur_tache est la fonction associe au serveur que nous allons voir en dtail dans les prochains paragraphes. Les paramtres ri, ci, pi, sont ceux passs en argument la fonction creer_serveur. Pour viter lutilisation des ressources par le serveur, nous allons mettre comme numro de file de smaphore, la valeur 255 qui est suprieure au nombre de files associes aux tches dclares (32), ce qui entranera le fait que la fonction creer_tache va refuser cette valeur et ne pas accepter lutilisation de ressources pour cette tche. Une fois ceci fait, il faudrait tester la valeur retourne par la fonction creer_tache ainsi appele. Si aucune erreur nest survenue (tche cre), ce moment-l, il faut mettre la valeur etat_serveur 1, pour dire quil y a cration dun serveur, et denregistrer aprs ceci, lidentifiant dans id_serveur en vue dtre repr par lordonnanceur. Puis redfinir le type de la tche du champ sched.type SERVEUR aprs quil aurait t fix par la fonction creer_tache la valeur PERIODIQUE. Il faudrait galement, remettre le serveur ltat SUSPENDU, dans le cas o la variable globale contenant le signal apriodique (signal_aperiodique) serait 0. Pour enfin retourner lutilisateur lidentifiant du serveur. (voir le fichier source: .\treel\tache.cpp).

4 Ralisation de lexcutif temps rel.

116

4.5.3. Test de faisabilit Une fois toutes les tches cres, il faudrait tester leur faisabilit en vrifiant pour cela, la condition dordonnancement RM vue au premier chapitre. Comme nous lavons dit lors de la conception, il ne faudrait pas que cette condition soit stricte, autrement dit, le test doit tre fait, mais ninflue pas sil ne satisfait pas la condition RM. La fonction de ce test est : int faisabilite( ) ; cette fonction teste en premier lieu, la file des tches priodique prtes, pour sassurer quil y a au moins une tche qui est pralablement cre. Le cas chant, vrifier sil y a utilisation de ressources, et ce, en vrifiant la variable globale utilisation_ressources. Si cest le cas, il faudrait calculer alors les priorits plafond en faisant appel la fonction set_priorite_plafond. Cette dernire, doit attribuer chaque ressource(smaphore cr) la priorit plafond = max{Priorits(Ti) pour i=1,n} telle que Ti est susceptible dutiliser la ressource concerne, sue aprs avoir parcouru la file des smaphores associe une tche. Une fois les priorits plafond fixes, pour chaque ressource (smaphore), la condition de faisabilit sera faite en faisant appel la fonction condition_RM, et tout en parcourant la file des tches priodiques prtes. Deux cas sont alors envisageables. Dune part, la tche est susceptible dutiliser des ressources (en prsence de la signature 0xFAFA dans le champ sched.ressource.magic du contexte de la tche), ce moment-l, la fonction condition_RM sera appele avec les paramtres Ci, Pi, Bi, i, indiquant respectivement la capacit dexcution, la priode de la tche, le facteur de blocage de la tche, et lidentifiant de la tche. Suivant ces paramtres, la fonction condition_RM va pouvoir dterminer en utilisant le quotient cumul (Ci/Pi) sauv dans la variable relle 1/i globale facteur_U, si (Ck / Pk ) + (Bi / Pi) i (2 1), et pour viter dcrire des fonctions qui prennent en charge la puissance dun nombre rel, nous avons pens utiliser plutt un tableau de rels, dclar global (tableau_RM) contenant les valeurs du 1/i terme : i (2 1), quil suffit daccder avec lindice i. Si la condition nest pas vrifie condition_RM retourne 1, sinon elle retourne 0. Dautre part, si la tche nutilise pas de ressources, il faudrait appeler dans ce cas, la fonction condition_RM avec les paramtres suivants Ci, Pi, 0, i, idem aux premiers, sauf que cette fois-ci, le facteur de blocage Bi est bien sr nul. Lorsque nous avons voqu le facteur de blocage Bi, nous navons pas expliqu la faon, de le dterminer. En ralit, sil y a utilisation de ressources, un appel est fait la fonction determiner_Bi(int id) avec id lidentifiant de la tche. La fonction determiner_Bi est limplmentation de lalgorithme de K. Tindell, et H. Hansson propos au premier chapitre, pour la dtermination du facteur de blocage. Elle retourne donc le facteur Bi, qui est le temps maximum de blocage dune tche par les moins prioritaires quelle, utilisant la mme ressource. Notons que si le test de faisabilit est russi dans le cas dutilisation de ressources, le facteur Bi est ajout au contexte de la tche dans le champ : sched.Bi (voir le source .\treel\tache.cpp).

4 Ralisation de lexcutif temps rel.

117

4.5.4. Cration dun smaphore Pour que lutilisateur puisse utiliser un smaphore, il faudrait dabord le crer par la fonction : SEMAPHORE creer_semaphore() ; Cette fonction retourne ladresse mmoire physique de la structure du smaphore cr, sil y a erreur elle retourne un pointeur nul (NULL). Un peu comme la fonction creer_tache, la fonction creer_semaphore doit en premier lieu vrifier sil y a une structure de smaphore libre, en appelant la fonction get_sem_libre, qui parcourt lensemble du tableau de structures smaphores, en vrifiant chaque fois la signature 0xBABA. Si aucune signature trouve dans le champ magic, la fonction get_sem_libre retourne immdiatement le numro de la structure du smaphore, qui va servir didentifiant ce smaphore durant toute son utilisation. Si aucune structure libre trouve, une valeur ngative est renvoye, et ce moment-l, la fonction creer_semaphore retourne un pointeur nul (NULL). Une fois ceci fait, il faudrait initialiser les lments de la structure du smaphore, en mettant dans le champ val (valeur du smaphore) la valeur 1, dans le champ id lidentifiant du smaphore, dans le champ priorite (priorit plafond) la valeur 0, puis marquer la structure comme tant prise, en mettant dans le champ magic la valeur 0xBABA et de retourner enfin ladresse de cette structure (SEMAPHORE). 4.5.4.1. Ajouter un smaphore dans une file

Pour pouvoir utiliser un smaphore cr, et comme nous lavons prcis dans la conception, il faudrait dabord lajouter dans une file de smaphores associs une tche. Pour cela, il faudrait appeler la fonction : int add_semaphore(unsigned unsigned long temps_SC) ; int num_file, SEMAPHORE sem,

lentier num_file, est un numro qui doit tre donn par lutilisateur, et reprsente le numro de la file dans laquelle sera insr le smaphore sem ; cette file est appele lors de la conception : file des smaphores associe une tche. Les valeurs permises vont de 0 31 (par convention), et reprsentent le nombre ou le tableau de files dclares comme globales. Le paramtre smaphore spcifie, le smaphore cr par la fonction creer_semaphore. Quant au troisime paramtre, il spcifie le temps (en unit dhorloge logique absolue) de la section critique associe au smaphore sem.

4 Ralisation de lexcutif temps rel.

118

Il faudrait intervenir notamment dans cette fonction, sur les champs de la structure du smaphore sem, qui sont les suivants : time[file_sem], npred[file_sem], nsucc[file_sem], qui reprsentent respectivement : le temps de la section critique associe au smaphore sem,(nous avons suppos lors de la conception quun smaphore naura par simplicit quun seul temps associ une section critique pour une mme tche) ; le prdcesseur dans la file numro file_sem ; le successeur dans la file numro file_sem ;

4.5.4.2.

La primitive P(s) et le protocole priorit plafond

Pour que lutilisateur puisse utiliser une ressource (smaphore) au sein du code associ une tche priodique, nous allons rcrire la primitive P(s) de Dijkstra en vue de prendre en charge le protocole priorit plafond. En faisant appel la fonction : void P(SEMAPHORE s) ; celle-ci, devra en premier lieu vrifier si la valeur du smaphore s, est 0 (si la ressource est prise). Si cest le cas, elle doit non seulement attendre la remise 1 de la valeur du smaphore, mais aussi procder ventuellement lhritage de priorit. Pour ce dernier, la primitive vrifie dabord, si la priorit de la tche en cours (dont lidentifiant est dans la variable globale courant_id) faisant appel cette primitive, est suprieure la priorit de la tche qui dtient le smaphore s (lidentifiant de la tche qui dtient s, se trouve dans le champ id_tache du smaphore s). La primitive ce moment-l doit procder, lhritage de priorit, et ce, en sauvant la priorit de la tche qui dtient le smaphore s, dans le champ temp_pr de cette tche, puis forcer sa priorit celle qui demande s, dont la priorit est suprieure. Une fois ceci fait, la primitive doit mettre ltat de la tche en ATTENTE, et sauver ladresse du smaphore s pour qui, elle est attente, et ce, dans le champ du contexte de la tche, sched.ressource.attente, puis boucler sur elle-mme. Dans le cas o le smaphore serait libre (valeur du smaphore 1) lors de lappel la primitive P(s), elle ne doit pas dtenir directement le smaphore s, avant de vrifier la condition pose par le protocole priorit plafond. La condition comme nous lavons dj vue dans le premier chapitre, consiste vrifier si la priorit plafond du smaphore s est strictement suprieure toutes les priorits plafond, des smaphores en cours dutilisation par les autres tches. Pour cela, la primitive doit parcourir la file des smaphores (excluant ceux possds par la tche demandant s) puis comparer la priorit du smaphore s, celle du smaphore trouv, dans la file des smaphores. Si elle nest pas suprieure (priorit) pour lun des smaphores trouvs dans la file, il faudrait alors bloquer la tche qui demande la ressource (le smaphore s ). Avant ceci, et en vue de faire un hritage de priorit, la primitive doit vrifier la priorit de la tche en cours demandant le smaphore s, si elle est suprieure celle de la tche dtenant le smaphore trouv dans la file des smaphores, et dont la priorit plafond est suprieure celle du smaphore s. Procder le cas chant lhritage de priorit, comme vu plus haut.

4 Ralisation de lexcutif temps rel.

119

Il faudrait mettre aprs quoi, la tche demandant s, en attente, en forant comme dj vu, son tat ATTENTE, et mettre aussi dans le champ sched.ressource.attente, du contexte de cette tche, ladresse du smaphore s. Une fois ceci fait, il faudrait boucler, tant que le smaphore pour qui lattente est faite, nest pas encore libr (sa valeur est 0). Une fois le smaphore libr, le scheduler est responsable de mettre la tche ltat PRET. La primitive est ce moment-l rveille, et doit refaire depuis le dbut la vrification de le la valeur du smaphore, cest--dire, depuis la toute premire tape o il est question de vrifier si la valeur du smaphore est 0 (voir plus haut). Maintenant aprs avoir pass toutes ces vrifications, le smaphore s est en mesure dtre dtenu par la tche le demandant. La primitive doit ce moment-l, mettre 0 la valeur du smaphore (pour indiquer que le smaphore s est pris), puis de mettre dans le champ id_tache de la structure du smaphore s, lidentifiant de cette tche, de mettre galement ltat de cette tche ltat SEM pour indiquer que la tche va oprer en section critique, et enfin ajouter le smaphore s dans la file des smaphores, en faisant appel la fonction add_sem_file(s,&file_sem_courant), tel que &file_sem_courant, correspond ladresse de la file des smaphores.

4.5.4.3.

La primitive V(s) et le protocole priorit plafond

la fonction : void V(SEMAPHORE s) ; est aussi rcrite en vue de prendre en charge le protocole priorit plafond, et de suivre galement la logique de la primitive P(s), pour librer le smaphore s dtenu par le biais de celle-ci. En premier lieu, la primitive V(s) doit vrifier sil y a eu hritage de priorit, en vrifiant pour cela, le champ temp_pr du contexte de la tche dtenant le smaphore s, sil nest pas nul. Dans ce cas, il faudrait restaurer la priorit, en forant la priorit de la tche, celle sauve dans le champ temp_pr, puis de mettre ce dernier 0. La primitive doit appeler par la suite, la fonction rem_file_sem(s,&file_sem_courant), pour retirer le smaphore s de la file des smaphores. Il faudrait galement rendre ltat de la tche librant s ltat PRET (aprs avoir t ltat SEM). Et enfin, mettre 1 la valeur du smaphore s.

(les primitives P et V sont dans le fichier source : .\treel\schedule.cpp).

4 Ralisation de lexcutif temps rel.

120

4.5.5. Ordonnancement des tches temps rel A travers ce paragraphe, nous allons discuter de la faon dordonnancer les tches priodiques. En partant de lactivation de lhorloge par lutilisateur, suivi de ladministration dinterruption dhorloge temps rel, puis la slection de la tche priodique et le chargement de son contexte, et enfin la commutation de contexte et le retour de linterruption ; nous allons nous accentuer sur toutes ces tapes, tout en abordant galement lordonnancement des tches apriodiques.

4.5.5.1.

Activation de lhorloge temps rel - RTC

Sur les machines bases sur une architecture Intel, la RTC est constitue du processeur MC146818 de Motorola et dune RAM de 64 octets aliments par une pile ; ainsi lhorloge temps rel continue fonctionner mme lorsque lalimentation secteur est coupe. Les demandes dinterruption gnres par la RTC arrivent sur lentre IRQ8 du deuxime contrleur dinterruption PIC 8259A. [SB 03] La RTC est accessible par les ports dE/S dadresse 70h pour le registre dadresse et 71h pour le registre de donne. La RAM contient des registres dtat et de contrle adressables individuellement ; ce sont les registres A, B, C et D. [SB 03] Dautres cellules conservent lheure courante sous la forme : seconde, minute, heure, jour, mois, anne. La RTC peut tre programme pour quelle dlivre des impulsions dhorloge priodiques arrivant sur lIRQ8, et par dfaut, il y a 1024 interruptions dhorloge / seconde. Nous allons programmer la RTC, pour quelle nous dlivre des interruptions priodiques, en vue de les utiliser pour ordonnancer les tches. Pour ce faire, nous allons crire la fonction : void activer_horloge(); qui doit tre appele par lutilisateur une fois toutes les tches cres. Cette fonction initialise la RTC, en envoyant la valeur 0Bh au port 70h, pour slectionner le registre B, puis denvoyer par la suite, la valeur lue depuis le port 71h (la donne) en mettant son bit 5 (interruption priodique) 1, autrement dit, armer linterruption priodique.

4 Ralisation de lexcutif temps rel.

121

4.5.5.2.

Linterruption dhorloge temps rel

A chaque top dhorloge temps rel, une interruption 60h (IRQ8) se produit. Le processeur va indexer dans la table IDT, pour extraire ladresse de la routine dinterruption, qui dans notre cas est ladresse de la routine int60 crite en assembleur. Cette routine va excuter en premier lieu linstruction pushad qui empile respectivement les registres suivants : EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, puis sauvegarde la valeur du registre ESP dans la variable _esp dclare globale pour une future utilisation. La routine int60 appelle par la suite la fonction call_int60 crite en C. La fonction call_int60 commence par incrmenter le compteur absolu cpt_absolu (dclar global), qui reprsente le temps absolu du systme ou dune autre manire, lhorloge logique comme nous lavons dj nomm dans les paragraphes prcdents. Cette horloge logique est incrmente comme nous venons de le dire, chaque appel de fonction call_int60, autrement dit, 1024 incrmentation par seconde. Suivant la variable globale etat_IT (non 0, le scheduler est actif, et 0 inactif) la fonction call_int60 va faire appel la fonction schedule_tr qui soccupe de lordonnancement des tches temps rel. (La routine int60 est dans le fichier : .\32\it.asm ; call_int60 se trouve dans : .\32\ints.cpp). 4.5.5.3. Ordonnancement des tches priodiques

Comme nous lavons cit prcdemment, la fonction : void schedule_tr(); soccupe de lordonnancement des tches priodiques, en adoptant pour cela, la politique Rate Monotonic. La fonction prend en charge, trois cas pour pouvoir sparer les tches et les actions associes entreprendre, en inspectant dans chacun des cas la variable globale courant_id, qui rappelons le, contient lidentifiant de la tche en cours initialis la valeur -1. Le premier cas est trait si la variable, courant_id est 1, autrement dit, sil sagit de la premire excution de la tche. Dans ce cas, la fonction schedule_tr charge le contexte de la tche nop_task (tche priodique qui boucle sur elle-mme) dinformations comme, ladresse de la routine dans le champ tss.eip, le registre eflags dans le champ tss.eflags, et puis la zone de pile, ladresse de pile que nous avons rserv (voir cration de tche), qui par convention est lemplacement 0x5FFFFC, et cette dernire sera mise dans le champ tss.esp du contexte de la tche nop_task. Cette dernire rappelons-le, sexcute uniquement lorsquil n y a aucune tche priodique excuter durant un ou plusieurs tops dhorloge, en dautres termes, elle est sollicite pour combler les vides ou creux temporels pouvant exister entre tches priodiques. Une fois ceci fait, la fonction schedule_tr teste si la tche dont la date de rveil est minimale (tche identifie par la variable globale id_min_ri initialise lors de la cration des tches), est infrieure ou gale lhorloge logique (cpt_absolu), autrement dit, savoir si

4 Ralisation de lexcutif temps rel.

122

la tche est prte tre rveille. Le cas chant, elle doit vrifier si cette tche sagit dune tche priodique quelconque ou bien de la tche priodique serveur. Pour ce dernier, nous y reviendrons dans le paragraphe abordant lordonnancement des apriodiques. Quant aux autres tches priodiques, la fonction schedule_tr va ce moment-l, sauver lidentifiant de cette tche priodique (dont la date de rveil est minimale) dans la variable globale courant_id, et de raliser par la suite le chargement de contexte de cette tche, en appelant dans ce cas, la fonction premiere_commutation, et comme paramtre ladresse du contexte de la tche avec lidentifiant courant_id. A noter que le chargement et la commutation de contexte seront vus dans les prochains paragraphes. Le deuxime cas est trait, si la variable courant_id est 2, ce qui veut dire que linterruption dhorloge est apparue au moment de lexcution de la tche nop_task. Il faudrait alors chercher la tche la plus prioritaire dont la date de rveil est minimum, dans la file des tches priodiques prtes, et ce, en faisant appel la fonction get_next_tache, qui retourne NULL (pointeur nul) sil n y a aucune tche priodique prte dans la file au moment cpt_absolu, ou bien retourne ladresse du contexte de la tche lue. Si la valeur retourne par get_next_tache, nest pas nulle, il faudrait alors, appeler la fonction de chargement de contexte : commuter, qui sauvegarde le contexte de la tche pass en premier paramtre, et charger le contexte de la tche pass en deuxime paramtre, ce qui retombe faire passer dans ce cas, les paramtres suivants : &nop_tr et &p, qui correspondent respectivement ladresse du contexte de la tche nop_task, et celle de la tche trouve dans la file des tches priodiques prtes. Le troisime cas est le cas par dfaut, cest--dire, si lidentifiant contenu dans la varaible courant_id est une valeur quelconque, autrement dit, linterruption est survenue au sein dune tche priodique quelconque (y compris la tche serveur). Si la tche savre tre la tche serveur, ce moment-l, un traitement spcifique lui sera consacr et nous laborderons au paragraphe traitant lordonnancement des apriodiques. Il faudrait par ailleurs, et aprs avoir dcrment la capacit dexcution (cpt_ci), tester si la capacit de la tche nest pas puise, ce qui revient dire, tester la variable sched.cpt_ci, du contexte de la tche identifie par courant_id, si elle est nulle. Dans ce cas, il faudrait recalculer la date du prochain rveil de cette tche, et ce, en forant le champ sched.cpt_ri prendre la valeur : (sched.cpt_ri (ancienne valeur) + sched.pi (la priode de la tche)) puis de recharger sched.cpt_ci par sched.ci. Une fois ceci fait, il va falloir faire appel la fonction get_next_tache. Si cette dernire renvoie un pointeur non nul, il faudrait ce moment-l, charger le contexte de la tche correspondant ce pointeur et de sauver le contexte courant, (par le biais de la fonction commuter) et par la suite, mettre jour la variable courant_id celle de lidentifiant de la tche ainsi charge. Si par contre, la fonction get_next_tache renvoie un pointeur nul, il faudrait charger plutt le contexte de la tche nop_task (par le biais bien sr, de la fonction commuter), et de forcer la variable courant_id prendre la valeur 2. La figure 4.4. rsume ces trois cas, sous un automate.

4 Ralisation de lexcutif temps rel.

123

date de rveil ri > horloge logique cpt_absolu

get_next_tache renvoie NULL.

courant_id

-2

get_next_tache nul
courant_id

get_next_tache renvoie NULL.

-1
courant_id quelconque

courant_id=id_min_ri

get_next_tache nul

Figure 4.4. Automate dtats du scheduler.

4.5.5.3.1. Election dune tche priodique Comme nous lavons dj vu, llection dune tche priodique, se fait par le biais de la fonction get_next_tache, qui parcourt la file des tches priodiques prtes. Dans cette dernire, si une tche priodique est dans un tat ATTENTE (attente dune ressource), il faudrait vrifier ce moment-l, si la ressource pour laquelle cette tche est en attente serait libre, et de rendre ainsi ltat de cette tche ltat PRET, en vue de la faire rentrer en concurrence avec les autres tches priodiques. Pour slectionner une tche parmi dautres, conformment la politique Rate Monotonic, il va falloir vrifier si la prochaine date de rveil cpt_ri de chacune des tches est infrieure ou gale lhorloge logique (cpt_absolu), mais aussi, tester si cette tche est dans lun des tats suivants {PRET,SEM}, puis de sauver temporairement la tche jusqu ce quune autre tche plus prioritaire soit trouve, et prendra alors sa place. Cette faon de faire sera applique durant tout le parcourt de la file des tches priodiques prtes, pour renvoyer la fin ladresse de la tche priodique qui est sauve temporairement. Si par contre, aucune tche nest trouve ou encore ne satisfait pas les conditions cites, un pointeur NULL (valeur 0) sera retourn.

4 Ralisation de lexcutif temps rel.

124

4.5.5.4.

Ordonnancement des apriodiques

Les tches apriodiques sont ordonnances par la tche priodique serveur. Ce dernier tant avant tout une tche priodique, quil faudrait tenir compte durant lordonnancement, ou encore durant les trois cas ou tats qui composent notre fonction schedule_tr. Dans le premier cas (courant_id est 1), il sagit de la premire excution du scheduler, et si aprs test de lidentifiant contenu dans id_min_ri, savre correspondre la tche serveur, il faudrait alors faire appel la fonction get_aperiodique en vue dextraire en FIFO depuis la pile des apriodiques, lidentifiant de la tche apriodique, et de le placer dans une variable globale aperiodique_id, qui sera accessible par la tche serveur, dont le code dexcution est crit au sein de la fonction : void serveur_tache( ) ; Bien sr, il va falloir aussi par la suite, faire le premier chargement du contexte avec celle du serveur en appelant la fonction premiere_commutation, comme ctait le cas dailleurs pour les tches priodiques. Le cas o courant_id est 2, cest--dire, une interruption survenue au sein de la tche nop_task, il faudrait ce moment-l faire juste un appel la fonction get_aperiodique, pour extraire ventuellement lidentifiant dune tche apriodique depuis la pile des apriodiques et de le placer dans la variable globale aperiodique_id, puis de poursuivre les tapes vues dans lordonnancement priodiques correspondantes ce cas. Dans le cas par dfaut (courant_id quelconque), il faudrait en premier lieu faire appel la fonction get_aperiodique, puis de tester par la suite si lidentifiant courant_id correspond ce du serveur, tout en vrifiant la disponibilit dune apriodique (aperiodique_id non nul). Si tel est le cas, dcrmenter le compteur de la capacit de lapriodique sched.cpt_ci, et de le vrifier par la suite sil est puis. Dans ce dernier cas, il est recharger la capacit sched.cpt_ci par celle de sched.ci, et de mettre 1 les variables globales suivantes : aperiodique_suivante et reinitialiser_serveur qui indiquent respectivement sil y a une apriodique en phase de traitement, autrement dit, lautorisation dextraire davantage les ventuelles tches apriodiques par get_aperiodique, et pour lautre variable, indiquer la fonction commuter quil sagit dun chargement de contexte particulier rserv au serveur. Une fois ceci fait, au sein de ces conditions, il va falloir galement, tester la variable globale signal_aperiodique, qui indique ltat de la pile des apriodiques. Si cette dernire contient un lment (identifiant dune apriodique), ce qui revient dire aussi que la variable signal_aperiodique est 1, il faudrait ce moment-l, faire appel la fonction get_aperiodique tant donn que lancienne tche apriodique est puise en capacit et quil y a davantage de tches apriodiques traiter. Mais si par contre la pile des apriodiques est vide, il faudrait alors, suspendre le serveur en mettant son tat SUSPENDU. Une fois ces actions ralises, lordonnancement des priodiques correspondant ce cas, se poursuit alors ce niveau.

4 Ralisation de lexcutif temps rel.

125

4.5.5.4.1. Serveur des aperiodiques Comme nous lavons cit prcdemment, le code excutable ou la fonction associe la tche priodique serveur est serveur_tache. Cette dernire, vrifie sil y a une apriodique disponible au traitement, en vrifiant la variable aperiodique_id, mais aussi, sassurer que ltat du serveur est dans ltat PRET. Dans ce cas, elle extrait ladresse de la fonction (se trouvant dans le champ tss.eip du contexte de la tche), associe lapriodique dont lidentifiant est aperiodique_id, et fait appel cette fonction. Cest pour cela, que nous disions que les tches apriodiques dans notre systme, vont sexcuter dans le contexte du serveur. Les threads ou les fonctions associes aux apriodiques vont avoir alors la mme zone de pile que celle du serveur, autrement dit, il sagit dun simple appel de fonction lapriodique lanc depuis la fonction associe au serveur (serveur_tache). Aprs le retour depuis la fonction associe lapriodique appele, le serveur est mis ltat SUSPENDU. (la fonction serveur_tache est dans le fichier source : .\32\schedule.cpp). 4.5.5.4.2. Election dune apriodique Llection dune apriodique ne se fait pas de la manire dont elle se fait celle des tches priodiques. Ceci est d principalement la simplicit mis en uvre pour ordonnancer les apriodiques. En effet, la fonction get_aperiodique qui soccupe de llection ou vrai dire de lextraction de lapriodique depuis la pile des apriodiques, est tablie suivant FIFO. La fonction get_aperiodique intervient directement sur la pile des apriodiques, elle est conditionne nanmoins par ltat de la variable globale aperiodique_suivante, qui indique sil y a une apriodique en phase de traitement, puisque nous avons suppos un traitement squentiel des apriodiques, et doivent sexcuter alors une aprs lautre. Dans le cas o il n y aurait pas dapriodique en phase de traitement par le serveur (aperiodique_suivante est 1), la fonction get_aperiodique devra par la suite, tester sil y a toujours un signal apriodique autrement dit, tester la variable globale signal_aperiodique si elle est 1. Si cest vrifi, deux cas sont alors prendre en charge : - Le premier cas, le sommet de la pile des apriodiques est diffrent de son bas, en dautres termes, la pile des apriodiques contient un lment, il faudrait alors envisager dextraire du bas de la pile des apriodiques (bottom) llment et dcrmenter bottom, puis mettre llment extrait dans la variable globale aperiodique_id, et de rendre ltat du serveur ltat PRET. Le deuxime cas est en dfinitive, une suite au premier, qui consiste tester si le sommet de la pile des apriodiques est devenu gal au bas de celle-ci. Dans ce cas, il va falloir mettre la variable globale signal_aperiodique 0, pour dire que la pile des apriodiques est vide.

A noter que pour les deux cas, la variable globale aperiodique_suivante sera mise 0 pour signifier que lextraction est effectue, et ne pas excuter prochainement la fonction get_aperiodique tant que la prsente apriodique extraite, ne sest pas encore puise en capacit lors de son traitement par le serveur des apriodiques. (La fonction get_aperiodique est dans le fichier source : .\32\schedule.cpp)

4 Ralisation de lexcutif temps rel.

126

4.5.5.4.3. Signal apriodique Nous avons abord dans les sous paragraphes prcdents, que ltat de la pile des apriodiques est reprsent par la variable globale signal_aperiodique. Nous avons suppos lors de la conception, que les diffrents signaux des apriodiques fournis par les capteurs externes au systme, seront associs aux diffrents niveaux dinterruption dans le systme. Il appartient alors lutilisateur, de mettre une fonction imbrique dans la routine dinterruption correspondante au signal de lapriodique ou encore, au capteur externe associ. Nous avons implant cette routine en langage C, quil suffit lutilisateur dinsrer dans lune des routines dinterruption (haut niveau) associe au signal apriodique. La fonction : void signaler_aperiodique(int id) ; permet dempiler dans la pile des apriodiques, lidentifiant de la tche apriodique id, en manipulant la variable globale top_aperiodique initialise ladresse du dernier lment de la structure pile_aperiodique. La fonction signaler_aperiodique permet galement, aprs cet empilement, de mettre 1 la variable globale signal_aperiodique pour dire que la pile des apriodiques contient un lment. (la fonction signaler_aperiodique est dans le fichier source: .\32\schedule.cpp la dclaration de la structure de pile des apriodiques est dans : .\include\proc.h).

4.5.5.5.

Chargement de contexte dune tche priodique

Nous avons abord dans le paragraphe 4.5.5.3. (linterruption dhorloge temps rel) quune routine int60 est excute, et elle sauvegarde suite cela, le contexte en excutant linstruction pushad. Il faut savoir qu ce moment-l, le traitement se fait au sein dune routine dinterruption, et que le contexte respectivement ci-aprs est empil par le processeur lors de linterruption dhorloge temps rel : EFLAGS, CS, EIP. Ce qui revient dire, quaprs avoir excut pushad, nous aurons tout le contexte ncessaire lexcution de la tche, il suffit aprs quoi, de sauver le sommet de la pile contenant ce contexte, pour pouvoir le manipuler, lors du chargement de contexte. Pour cela, nous dclarons une variable globale _esp, qui sauvegarde le sommet de la pile aprs empilement du contexte de la tche interrompue (voir figure 4.5).

4 Ralisation de lexcutif temps rel.

127

Le sommet de la pile est sauv dans la variable _esp

EDI ESI EBP ESP EBX EDX ECX EAX EIP CS EFLAGS

Empils par linstruction pushad au sein de la routine int60.

Empils par la CPU lors de linterruption.

Figure 4.5. Sauvegarde du contexte lors de linterruption dhorloge temps rel.

4.5.5.5.1. Premire commutation de contexte Nous avons abord dans le paragraphe 4.5.5.4. (Ordonnancement des tches priodiques) ainsi que dans le paragraphe 4.5.5.5 (Ordonnancement des apriodiques), que nous devons faire appel la fonction premiere_commutation, sil sagit de la premire excution du scheduler, autrement dit, la premire interruption dhorloge temps rel. La fonction : void premiere_commutation(struct tache * succ) ; permet de sauver le contexte suivant : EFLAGS, CS, EIP dans cet ordre et ladresse de la zone de pile dfini dans le champ tss.esp du contexte de la tche succ. Ceci est d au fait que lors de la premire interruption, la zone de pile est celle du noyau que nous avons dfinie dans le startup (entte de la fonction main) par convention 0x6FFFFC, or, la zone de pile consacre aux tches priodiques dbute 0x5FFFFC, et varie suivant lidentifiant de la tche priodique (voir cration dune tche priodique). Et dautant plus quil n y aura pas de sauvegarde du contexte courant, tant donn que ce dernier sagit de ce, du noyau. Une fois EFLAGS, CS, EIP sont empils dans lespace de pile consacr la tche succ, il faudrait par la suite redfinir la variable globale _esp ladresse de cette nouvelle zone de pile consacre la tche succ, et ce, en la dcalant en amant par rapport aux trois informations sauves (EFLAGS, CS, EIP) de 8 positions, pour tablir la configuration donne dans la figure 4.5. la figure 4.6 illustre un tel chargement.

4 Ralisation de lexcutif temps rel.

128

Forcer la variable _esp cette adresse.

Initialis 0 lors de la rservation des zones de pile associes aux tches. EIP CS EFLAGS

Adresse de la zone de pile de la tche succ (tss.esp)

Figure 4.6. Remplissage de la zone de pile par la fonction premiere_commutation.

La fonction premiere_commutation est toujours appele depuis la fonction dordonnancement schedule_tr. Celle-ci est appele depuis la fonction call_int60, qui, son tour est appele par la routine int60. Lors du retour cette dernire, il faut dpiler le contexte que nous avons empil au dpart (instruction pushad), et ce, avec linstruction popad. Mais avant cela, remarquons que la zone de pile dans laquelle nous avons sauv le contexte de la tche est totalement diffrente de celle qui est en cours. Cest en partie pour cette raison que nous avons dailleurs dclar la variable globale _esp, pour lutiliser forcer ce niveau le pointeur de pile ESP de la CPU. ESP pointera dsormais vers ladresse contenue dans _esp, autrement dit, la pile de travail de la CPU est celle que nous avons dfinie dans la figure 4.6. Dans notre cas (premire commutation), en tenant compte de la configuration de la pile prsente dans la figure 4.6. linstruction popad va dpiler dans les registres correspondant la CPU, toutes les cases grises (voir figure 4.6), ce qui quivalent dire, que tous les registres seront initialiss 0. Il y aura aprs quoi, linstruction iretd, qui sagit bien sr dune instruction de retour dune interruption. En lexcutant, la CPU va dpiler les informations (EIP, CS, EFLAGS) de la pile, or, la zone de pile est bel et bien celle de la tche que nous avons voulu charger par la fonction premiere_commutation.

4 Ralisation de lexcutif temps rel.

129

4.5.5.5.2. Commutation de contextes Un peu similaire au sous paragraphe prcdent, traitant la premire commutation, dans ce cas prsent, il faudrait charger le contexte de la nouvelle tche lue pass en paramtre la fonction commuter, mais aussi, sauver le contexte de la tche en cours pass galement en paramtre. La fonction : void commuter(struct tache *pred, struct tache * succ) ; sauvegarde le contexte de la tche en cours pred, et charge le contexte de la tche succ. Pour ce faire, la fonction commuter devra en premier lieu se positionner ladresse mmoire contenue dans la variable globale _esp (sommet de la pile du contexte en cours), puis partir de l, lire les informations empiles (voir figure 4.5.) et les sauvegarder dans les champs tss de la structure du contexte de la tche pred. Une fois ceci fait, il va falloir charger le contexte de la tche succ dans sa zone de pile, or, la zone de pile de la tche succ est sauve dans le champ tss.esp. Ce dernier va servir de pointeur de base, pour remplir les informations des champs du tss de la tche succ. Une fois les informations du contexte de la tche succ sont charges dans sa zone de pile, il faudrait aprs quoi, redfinir la variable globale _esp, pour quelle contienne la nouvelle adresse de pile, autrement dit, ladresse du sommet de la pile de la tche succ contenant le contexte ainsi charg. Remarque Nous avons cit dans le paragraphe 4.5.5.5. (Ordonnancement des apriodiques), quune variable globale reinitialiser_serveur est mise 1 pour indiquer la fonction commuter, que le traitement sera particulier (tche priodique serveur). En effet, la fonction commuter teste chaque fois cette variable, et si elle est 1, alors quelques informations du contexte du serveur seront rinitialise. Ces informations sont : tss.eip, tss.esp, tss.eflags. qui seront forces respectivement aux valeurs suivantes : &serveur_tache, _esp_serveur, 0x200. Qui signifient respectivement, ladresse de la fonction ou de la routine du serveur, ladresse de pile donne lors de la cration du serveur (rinitialisation), et la valeur EFLAGS, autorisant les interruptions. Aprs cela, il va falloir remettre 0 la variable globale reinitialiser_serveur. Cette rinitilisation est ncessaire lorsque le serveur finit lexcution dune tche apriodique. Rappelons que cette dernire intervient dans lespace serveur, et quil faudrait alors rinitialiser la fin du traitement de lapriodique.

4 Ralisation de lexcutif temps rel.

130

4.5.5.6.

Retour de linterruption dhorloge temps rel

Le retour depuis la routine dinterruption temps rel, se fait certes par linstruction iretd, mais avant ceci, un bon nombre doprations doit tre effectu au sein de la routine int60. Tenant compte du mcanisme dinterruption du PIC 8259A, il faudrait aprs chaque traitement de linterruption, envoyer ce contrleur le signal EOI (End of Interrupt), qui indique au PIC, que linterruption est traite, et il peut dsormais servir les interruptions moins prioritaires. Dans notre cas, linterruption dhorloge temps rel est sur lIRQ8, autrement dit, sur la broche 0 du PIC esclave. Ce qui veut dire encore, quil va falloir envoyer le signal EOI, aussi bien au PIC matre qu lesclave. Pour pouvoir envoyer EOI au matre, il faut envoyer la valeur 0x20 au port 0x20, et pour le cas de lesclave, la valeur 0x20 au port 0xA0. Par ailleurs, lhorloge temps rel dlivre un signal priodique, mais pour quelle puisse le faire priodiquement, nous devons lire la valeur du registre C du CMOS en dautres termes, envoyer la valeur 0xC au port 0x71, puis lire depuis 0x71. Cette faon de faire est impose par le constructeur, du fait que plusieurs interruptions peuvent surgir depuis lIRQ8 (signal dalarme, interruption priodique ), ainsi en lisant les bits status du registre C, nous serons en mesure de savoir, lidentit du signal dinterruption mis, par lhorloge temps rel. Mais puisque nous nallons pas utiliser dautres signaux dhorloge temps rel, nous nous contenterons juste de lire le registre C du CMOS, sans pour autant vrifier lidentit de linterruption. Une ventuelle utilisation des autres signaux de la RTC, impose ce moment-l, la prise en compte de lidentit de linterruption et les traitements adquats. Ce nest quaprs tous ces traitements, que linstruction iretd est finalement excute.

4.6.

Interface utilisateur temps rel (API)

En plus des fonctions cites dans les paragraphes prcdents, nous devons enrichir lensemble de ces fonctions (API) pour dune part, offrir la possibilit lutilisateur de manipuler le temps (horloge logique considre), et dautre part, moyennant ces fonctions, lutilisateur sera en mesure de dterminer le temps pris par chaque routine du systme, en vue de respecter le dterminisme en temps. Cest ainsi que lutilisateur pourra savoir, le temps de latence du scheduler, des interruptions Nous avons jug utile de rappeler avant cela, la liste de fonctions offertes lutilisateur, que nous avons dfinie lors de la description de notre systme.

4 Ralisation de lexcutif temps rel.

131

4.6.1. Manipulation des tches #include <kernel.h> #include <proc.h> int creer_tache(THREAD pi,u16 num_file_sem) ; thread, DATE ri, TIME ci, TIME

Permet de crer une tche priodique/apriodique (voir paragraphe 4.5.1). int creer_serveur(DATE ri, TIME ci, TIME pi) ; Permet de crer un serveur de tches apriodiques (voir paragraphe 4.5.2.). int faisabilite() ; Etablie le test de faisabilit RM, pour lensemble des tches prsentes dans le systme (voir paragraphe 4.5.3.) . int supprimer_tache (int id_tache) ; Permet de supprimer une tche quelle soit, priodique, apriodique, ou serveur. Les tches sont alors retires de la file dattente associe, et leur contexte est libr (magic=0). Retourne 0 en cas de russite 1 sinon. void suspendre_tache(u16 id); Permet de suspendre une tche priodique (y compris serveur), dont lidentifiant est id. void suspendre_tache_courante(); Permet de suspendre une tche priodique courante (en cours dexcution). void suspendre_tache_delai(TIME t) ; Suspendre la tche en cours, durant un temps t, exprim en s. TIME est de type long. void reprendre_tache(u16 id); Reactive une tche priodique (tat PRET) dont lidentifiant est id. int tache_courante() ; Renvoie lidentifiant de la tche courante. etat etat_tache(unsigned int id) ; Renvoie ltat de la tche id. (Ensemble dtats {PRET, SUSPENDU, SEM, ATTENTE}).

4 Ralisation de lexcutif temps rel.

132

void signaler_aperiodique(unsigned int id) ; Voir paragraphe 4.5.5.4.3.

4.6.2. Manipulation des smaphores #include <kernel.h> #include <proc.h> SEMAPHORE creer_semaphore(); Permet de crer un smaphore. Retourne ladresse du smaphore cr ou un pointeur NULL en cas derreur. int supprimer_semaphore(SEMAPHORE sem); Permet de rendre la structure du smaphore sem, libre pour une ventuelle allocation, cependant le smaphore sem nest pas retir de la file des smaphores, sil y est. int add_semaphore(int num_file,SEMAPHORE sem,long time) ; Rajoute le smaphore sem, avec un temps dexcution en section critique time, dans la file numro num_file des smaphores associs une tche priodique (voir paragraphe 4.5.4.1) void init_file_sem(); Initialise 0 toutes les files des smaphores, pour viter tout ventuel conflit. void P(SEMAPHORE s); Primitive de Dijkstra, pour obtenir le smaphore s. void V(SEMAPHORE s) ; Primitive de Dijkstra, pour librer le smaphore s.

4 Ralisation de lexcutif temps rel.

133

4.6.3. Manipulation du temps #include <kernel.h> DATE get_absolute_time() ; Renvoie la valeur du compteur absolu (horloge logique) de type double (64-bit), qui est incrmente chaque interruption dhorloge temps rel (par dfaut, 1024 IT /seconde). DATE time2absolute(char hh, char mm, char ss); Convertit le format hh : mm : ss, en valeur du compteur absolu (horloge logique). Exemple : time2absolute(31,02,11) retourne ((31*3600+2*60+11)*1024). DATE date_sys2absolute(char hh, char mm, char ss) ; Convertit la date (lheure) courante du systme sous la forme hh : mm : ss en valeur du compteur absolu. Si la date spcifie en paramtre est coule, la fonction retourne 0. char lire_heure() ; Renvoie lheure (hh) actuelle du systme. char lire_minute() ; Renvoie les minutes (mm) du systme. char lire_seconde() ; Renvoie les secondes (ss) du systme. void activer_horloge(); Voir paragraphe 4.5.5.1.

4.6.3.1.

Dterminer le temps dune routine

Pour que lutilisateur puisse satisfaire le dterminisme en temps, toutes les fonctions ou routines crites dans ses applications temps rel, doivent alors tre dtermines en temps dexcution, cest--dire, lutilisateur doit tre en mesure de savoir le temps pris par chaque routine quil a crit. Pour les routines systme (temps de latence du scheduler ou dinterruption) celles-ci seront donnes titre indicatif, mesures sur un processeur donn, mais que lutilisateur devra retester si lexcutif est implant dans un environnement matriel (CPU) diffrent, tant donn que le temps dexcution dune routine est troitement li la frquence dhorloge de la CPU sur laquelle le code sexcute.

4 Ralisation de lexcutif temps rel.

134

Pour mesurer le temps dexcution dune fonction, celle-ci devra tre place entre deux fonctions de mesure. La premire fonction (prologue) de mesure sera appele _p_time, et la deuxime (pilogue) _v_time. Leurs prototypes en C sont : void _p_time(); long _v_time(long frequence_cpu); La fonction _p_time va faire appel la fonction rdtsc du PENTIUM, pour lire le nombre de cycles processeur couls depuis la mise sous tension de la CPU, puis stocke cette valeur (64-bit) dans deux variables globales (32-bit) _rdtsc1 et _rdtsc2 respectivement poids faibles, et poids forts. La fonction _v_time va faire galement appel la fonction rdtsc, pour effectuer une autre mesure. A cette dernire sera retranch les valeurs sauves dans les variables globales _rdtsc1 et _rdtsc2 pour navoir que les cycles processeur couls depuis la premire mesure. Il va falloir par la suite diviser la valeur obtenue (cycles processeur couls) sur la frquence dhorloge de la CPU (en MHz) pour la convertir en temps (s) et de la renvoyer. Bien videmment la fonction mesurer sera place entre les deux cites ci-dessus, et le temps coul entre le prologue et lpilogue, ne sera rien dautre que le temps de la fonction que nous voulons mesurer.

4.6.4. Routine daffichage temps rel Comme nous lavons vu, le temps de chaque routine de notre systme, doit tre su, en vue de pouvoir garantir le dterminisme en temps. Il y va alors de mme pour la routine daffichage. Pour cette dernire, lutilisateur doit la prendre en charge comme tant une tche priodique (lui fixant une certaine priode ou priorit). A notre niveau (noyau), nous allons crire que la fonction qui va assurer lE/S (affichage), Il est donc la charge de lutilisateur, dimplmenter les mcanismes ncessaires notamment denvoi de messages afficher par cette fonction. #include <kernel.h> void print(char * chaine,) ; Utilise brut, cette fonction ne permet que de dboguer le noyau, elle nassure cependant pas le dterminisme en temps, tant donn quelle sollicite le basculeur (sortie 16-bit) pour effectuer lE/S par le biais des routines BIOS.

4 Ralisation de lexcutif temps rel.

135

Pour y pallier, nous avons crit une autre fonction : print_tr(char * chaine, ) ; qui permet dafficher les caractres sur lcran, en les projetant directement sur la mmoire physique vido 0xB8000. Ainsi nous pouvons garantir la premption (car la routine est excute en mode 32-bit) et lexclusion mutuelle, mais le temps dexcution reste dpendant de la taille de la chane de caractres afficher. En lui consacrant une tche priodique, lutilisateur pourrait alors viter au sein des autres tches effectuant lappel dE/S daffichage, le temps dattente d lexclusion mutuelle et au temps dexcution de la routine daffichage. Comme nous lavons cit, la routine print_tr, permet dafficher la chane de caractres chaine, en projetant ses caractres un par un dans la mmoire vido du mode texte (mape en mmoire 0xB8000). Pour pouvoir afficher un caractre, il suffit de placer celui-ci, une adresse paire, dcale par rapport ladresse de base 0xB8000, dont cette dernire, reprsente longlet haut gauche de lcran. Quant aux adresses impaires, elles reprsentent la couleur ou lattribut du caractre dont ladresse de ce dernier prcde immdiatement celle de sa couleur. Pour pouvoir agir sur ces cases mmoire, nous avons dfini, deux variables globales cord_x et cord_y, qui permettent de sauver ladresse courante du curseur et qui varient respectivement de [0 79](colonnes) et de [0 23](lignes). Ainsi, il est possible de tenir compte des sauts de ligne, et ce, en incrmentant juste la variable cord_y et en mettant 0 la variable cord_x. Pour scroler lcran, il suffit de copier les lignes dau-dessous vers les lignes dau- dessus. Autrement dit, copier chaque case mmoire se trouvant ladresse mmoire 0xB8000+X vers ladresse 0xB8000+X - (80*2), tant donn que nous disposons de 80 colonnes et chacune de ces colonnes, se dcompose en caractre + attribut. Lexclusion mutuelle est assure par la variable globale sem_affich, initialise 1. Cette variable est un verrou, pour empcher dutiliser simultanment laffichage. 4.7. Performances obtenues

Nous allons donner titre indicatif, les performances obtenues avec notre excutif, sur une machine tournant sur un processeur AMD de 800Mhz. - En prsence de 20 tches priodiques (y compris le serveur), et 10 tches apriodiques, nous avons eu un temps dordonnancement (int 60h) atteignant les 18s. - Pour signaler larrive dune apriodique par le biais dune interruption : 6s. (Avec ces conditions, la prcision ou le dterminisme en temps serait alors : (18+6)s). - Les primitives sur les smaphores P et V, ont des pics de 4s en prsence de 20 tches priodiques utilisant toutes des smaphores. A noter que pour mesurer le temps de traitement du scheduler, il faudrait placer linstruction en assembleur : int 60h entre les deux fonctions de mesure, et dter linstruction : mov esp,_esp se trouvant dans le fichier IT.asm (dans la routine int60), ceci pour ne pas permettre une commutation de contexte mais aussi inhiber les ITs avec linstruction en assembleur cli. Pour les temps dexcution des autres fonctions (API), nous avons jug inutile de les prsenter, dans la mesure o lutilisateur devrait effectuer lui-mme, les mesures, en prsence dune horloge processeur diffrente de celle donne.

4 Ralisation de lexcutif temps rel.

136

Conclusion Au terme de ce chapitre, nous avons prfr dresser des tableaux rcapitulatifs, sur ce qui a t prsent dans la ralisation. Le premier tableau 4.1. montre la configuration du noyau sur disque, en indiquant la position ou emplacement des diffrentes parties composant le noyau, exprim en secteurs physiques. Quant au tableau 4.2, il indique les adresses fixes du noyau en mmoire, elles reprsentent dailleurs celles que nous avons cites dans ce chapitre, comme tant des adresses prises par convention. Le choix des valeurs de ces adresses dpend certes, de larchitecture matrielle, mais aussi de la prise en compte des ventuelles extensions. N du secteur physique. Secteur 0 Secteur 1 Secteur 18 Contenu du secteur. Le Boot Partie 16-bit du noyau Partie 32-bit du noyau

Tableau 4.1. Reprsentation du noyau sur disque.

Adresse mmoire Physique. 0x6FFFFC (sens dcroissant) 0x5FFFFC (sens dcroissant) 0x100000 0x090200 0x090100-0x0901FF 0x090000-0x0900FF 0x070000-0x080000 0x063000 0x060000 0x050000 0x040000 0x030000 0x020100 0x01FFFE (Sens dcroissant) 0x010001 0x010000 0x000000

Contenu de ladresse Sommet de la pile du noyau en mode 32-bit. Dbut despace des piles des tches priodiques (2048 octets pour chaque tche). Partie 32-bit du noyau. Buffer pour les fonctions en mode 16-bit. Charg depuis le mode 32-bit. Zone de paramtres pour fonctions en mode 16-bit. Charg depuis le mode 32-bit. Contexte de la CPU lors du passage 32-bit au 16-bit. Charg depuis le mode 32-bit. Libre. Basculeur 32-bit. Basculeur 16-bit. IDT : table des Interruptions. GDT : table des segments Libre. Partie 16-bit du noyau. Sommet de la pile du noyau 16-bit. Structure contenant le matriel dtect. ID du lecteur de boot (1octet). Vecteurs dinterruption en mode rel.

Tableau 4.2. Reprsentation du noyau et ses donnes en mmoire physique.

4 Ralisation de lexcutif temps rel.

137

Bibliographie

[Intel] : http://www.intel.com [Ms dos] : MS-DOS Avanc. Deuxime dition. (P.S.I 1989), version franaise : ISBN :2-7124-0618-4 [SB 03] : Samia Bouzefrane - Les Systmes dExploitation Unix, Linux, et Windows XP (DUNOD 2003).

Conclusion gnrale

Ce modeste travail nous a permis, de passer en revue les diffrentes techniques utilises dans les systmes temps rel. Il nous a donn lide sur les degrs de difficults, au moment o nous nous apprtions mettre en uvre les principes, les notions et politiques rgissant la thorie du temps rel, travers lexcutif que nous avons conu et ralis. Cette aventure nous a enrichis en matire de programmation, en dveloppant une certaine matrise aux langages qui auparavant, taient obscures, notamment le langage assembleur. A ce dernier, une connaissance de larchitecture matrielle est plus que ncessaire, pour mettre en place les lments de base de notre noyau. La ralit, quimpose cette faon de faire, nous rduque, pour faire preuve dabstraction devant chaque situation ou tat du problme auquel nous sommes confronts. Partant alors de ce principe, nous avons tabli le modle en couche de notre noyau, et nous avons distingu lutilisateur de lexcutif, et ce dernier du matriel. Nous nous sommes bass sur lexploitation du matriel, au profit de lutilisateur(non final). Au sein de lexcutif, nous avons pris en charge les tches temps rel (priodiques, apriodiques associes au serveur). Les tches priodiques, peuvent utiliser des ressources critiques ou se synchroniser par des smaphores binaires. Cette gestion de ressources est associe au protocole priorit plafond, en vue de borner le temps dattente ces ressources, et prvenir notamment les situations dinterblocage et dinversion de priorits. Lordonnancement des tches priodiques est bas sur la priorit fixe de lalgorithme Rate Monotonic, contraintes strictes. Les tches apriodiques sont quant elles, ordonnances avec la tche priodique serveur en FIFO. Nous avons dcouvert durant ce travail, les diffrents systmes temps rel existants sur le march. Nous avons prfr quelques systmes, suivant leur utilisation, mais aussi et surtout pour complter les notions ou concepts de base temps rel que nous avons abord. Ceci donne en partie une ide sur ce que peut tre un systme temps rel, dans un environnement industriel ou mobile, et dans notre cas, il pourrait servir concrtiser les perspectives et donner une ide pratique quant au dveloppement futur de notre systme. Perspectives Notre excutif temps rel est simple dans ses mcanismes de base, ceci afin dobir aux exigences ou aux buts fixs. Par consquent, des perspectives pouvant tre formules, en vue de donner une ide sur ce que peut tre un dveloppement futur de notre systme. Un excutif ou un systme dexploitation doit tre dvelopp par une quipe de programmeurs chevronns. Ceci nous ramne dire, que les diffrentes parties de notre excutif doivent tre maintenues sparment. La partie 16-bit (mode rel) peut servir les tudiants/enseignants intresss, au dveloppement des applications pour le 8086 dIntel, notamment en offrant des routines bases sur les services BIOS du systme, savoir, la prise en compte de priphriques dE/S (Disques), et une interface de commandes, et de former ainsi un OS simple temps partag/temps rel.

Conclusion gnrale

La partie 32-bit est beaucoup plus prometteuse que la prcdente, tant donn quelle prend en charge la technologie Pentium dIntel, et dautant plus quelle est le support de notre excutif. Plusieurs visions en dcoulent, pour nen citer que les pertinentes dentre elles, nous pouvons penser sparer lespace utilisateur de lespace noyau, pour en crer deux espaces compltement distincts, en se basant pour cela sur les nouvelles technologies dIntel x86, qui rduisent de plus en plus le temps de commutation de contexte. Pour les politiques dordonnancement, nous nous sommes limits dans notre travail, au Rate Monotonic priorit fixe ; cependant, limplmentation dun algorithme dordonnancement priorit dynamique serait envisageable, et il suffit ce moment-l, de faire une extension de la fonction get_next_tache dans notre module dordonnancement. Notre excutif souffre du manque de communication entre tches, puisque seule une communication par variable globale est permise. Il est alors comme perspective de dvelopper un moyen de communication plus labor tel que le RPC, ou le mcanisme de botes aux lettres. Sajoutant cela, la transformation des smaphores binaires de notre systme, en smaphores compte. Bien videmment, le volume noyau serait plus important dans ces cas, et il faudrait du coup, effectuer des transformations au niveau de la fonction de chargement du noyau (partie 16-bit), de plus, une fonction de chargement de la partie 32-bit, doit tre mise en place en mode protg, afin de pouvoir assurer le chargement du reste de cette partie (partie 32-bit), puisque uniquement 64Ko immdiatement suprieures au premier mga octet (0x100000), sont accessibles (par la ligne A20) depuis le mode rel. Par ailleurs, nous pouvons songer transformer la partie temps rel, en temps partag, en laissant telles quelles, les diffrentes structures de donnes dj mises en place, dans la mesure o le temps partag peut tre peru comme du temps rel dpourvu de la notion du temps, notre excutif est dailleurs ralis de sorte supporter cette transformation. Il faudrait nanmoins pour ce faire, procder au dveloppement des modules comme la gestion mmoire pagine, la gestion des processus (cration), et dordonnancement, en impliquant notamment la gestion du multitche hardware. Lexcutif est conu et ralis entre autres des fins pdagogiques, il appartient alors aux futurs dveloppeurs de ce noyau, de couvrir davantage de principes des systmes dexploitation, et de promouvoir ceux dj existants dans cet excutif, pour servir cette honorable cause.

Annexes

Annexe. A

A. Compilation de lexcutif
A.1. Organisation des fichiers sources et utilitaires Noyau\ noyau.bin : le noyau temps rel compil. Compiler_exemple_PCP.bat : Lancer la compilation avec lexemple PCP. Compiler_exemple_Periodiques.bat : La compilation avec lexemple des priodiques. Compiler_exemple_aperiodique.bat : La compilation avec exemple dapriodique. Maktreel : le fichier du Make. Boot\ Boot.asm : contient le boot. Boot.inc : contient des macros utiliser dans boot.asm Bios.inc : contient des macros BIOS utiliser dans boot.asm Mak : fichier du Make. 16\ Partie 16-bit du noyau. Bascul.asm : partie 16-bit du basculeur Init_cpu.asm : dtection de la CPU (identit, frquence). Init_ram.asm : dtection de la mmoire vive (tendue et conventionnelle). Init_gdt.asm : Initialisation de la table des segments (GDT). Mod_prtg.asm : Passage en mode protg Printk.asm : fonction daffichage Putchr.asm : fonction putchr( ) Start16.asm : entte de la fonction principale : main( ) kr16.cpp : fonction principale main( ) dtct16.cpp : Initialisation de la machine. wrt_read.cpp : lecture et criture de secteurs physiques mak : fichier du Make

32\ Partie 32-bit du noyau. Bascul.asm : partie 32-bit du basculeur. IT.asm : routines dinterruption (bas niveau). Start32.asm : entte de la fonction main ( ) Kr32.cpp : fonction principale main ( ) Init_IDT.cpp : intialisation de la table des interruptions (IDT) Init_PIC.cpp : initialisation du PIC 8259A. Ints.cpp : routines dinterruption (haut niveau). _w_r.cpp : lecture et criture de secteurs physiques. id_fonct : identificateurs de fonctions pour le basculeur. maktreel : le fichier du Make.

Annexe. A

Treel\ tache.cpp : contient des fonctions pour crer/supprimer tches/smaphores. Schedule.cpp : contient la fonction dordonnancement et lAPI. Rdtsc.asm : mesure du temps des fonctions et routine dattente de dlai. Applic_tr.cpp : Contient lapplication temps rel (au sein de application_tr( )). Maktreel : fichier make de ce rpertoire. Debug\ tache.cpp : Version dbogue de celle prsente ci-dessus. Schedule.cpp : Version dbogue du scheduler. Include\ Les fichiers Include Kernel.h : prototypes de toutes les fonctions du noyau (16-bit et 32-bit). Kbd.h : la map du clavier franais. Proc.h :dclaration de structures des tches/smaphores/files. Idt.h : les prototypes des routines dinterruption. Dtct16.h : superstructure et dclarations pour la fonction dtct16( ) Disq16.h : dtection des disques et chargement de la partie 16-bit. Define.h : des fonctions pour inhiber ou autoriser les interruptions. Couleur.h : contient les attributs de couleur pour laffichage

Utils\ Print.cpp : la fonction daffichage temps rel. String.cpp : les utilitaires de chanes de caractres. Mem.cpp : manipulation de zones mmoire. Decasc.cpp : conversion dcimal - ASCII. Hexasc.cpp : conversion hexadcimal ASCII. Lib\ Kernel16.lib : Librairie de la partie 16-bit Kernel_tr.lib : Librairie de la partie 32-bit et de Treel.

Outils\ Cat.exe : pour concatner le boot avec la partie 16-bit du noyau. Cat32.exe : pour concatener (boot+16-bit) avec la partie 32-bit du noyau. Flink.exe : pour avoir le binaire du fichier excutable (32-bit) sans lentte. Chargeur.exe : installer le noyau sur une disquette. Boch\ VGABIOS-elpin-2.40 : ROM VGA pour la machine virtuelle Bochs. BIOS-bochs-latest : ROM BIOS pour la machine virtuelle Bochs. Boch.conf : fichier de configuration de la machine virtuelle Bochs. DBUG.exe : Machine virtuelle Bochs. Bochsout.txt : fichier de sortie pour la machine virtuelle Bochs.

Annexe. A

Exemples\ PCP\

Exemples dapplication temps rel.

Applic_tr.cpp : exemple dun cas dun interblocage vit par le PCP. Lisez_moi.txt : rsume lexemple. Perio\ Applic_tr.cpp : exemple de 3 tches priodiques en excution. Lisez_moi.txt : rsume lexemple. Aperio\ Applic_tr.cpp : exemple dune apriodique, priodique, signal carr Lisez_moi.txt : rsume lexemple. Compil\ Les compilateurs utiliser.

Bcc.exe : compilateur de Borland C++, pour la partie 16-bit du noyau. Bcc32.exe : compilateur de Borland C++, pour la partie 32-bit du noyau. Masm.exe : appel lassembleur de Microsoft (ML.exe). Ml.exe : Assembleur de Microsoft Masm. Rtm.exe : sollicit par les compilateurs de Borland. Tasm.exe : assembleur de Borland, appel par le compilateur Bcc.exe Tasm32.exe : assembleur de Borland, appel par le compilateur Bcc32.exe. Make.exe : le Make (de borland). Tlib.exe : outil pour la gestion de la librairie (de Borland). Tlink.exe : linker 16-bit (de Borland) pour la partie 16-bit du noyau. Tlink32.exe : linker 32-bit (de Borland) pour la partie 32-bit du noyau.

A.2. Les compilateurs Comme nous lavons soulign dans le chapitre ralisation, nous avons utilis lassembleur MASM (ML) version 6.11 (de Microsoft) pour les routines ncessitant des accs bas niveau. Pour le langage haut niveau (langage C), nous avons choisi, le compilateur BCC version 4.52 (de Borland) pour la partie 16-bit, et BCC32 version 4.52 (de Borland) pour la partie 32-bit. BCC et BCC32 sont respectivement accompagns des diteurs de liens (de Borland) TLINK et TLINK32. BCC et BCC32 font appel respectivement aux : TASM et TASM32 (de Borland), qui sont des assembleurs, par dfaut, de ces compilateurs. Puisque nous effectuons la compilation via assembleur, nous aurons besoins alors de ces assembleurs. Etant donn le grand nombre de fichiers sources compiler, et maintenir, il va falloir adopter une mthode labore pour la compilation, qui consiste utiliser un MAKE (de Borland). Les compilateurs sont trouver dans : Noyau\compil\

Annexe. A

A.3. Utilitaires dvelopps Pour pouvoir manipuler les diffrentes parties du noyau (boot, 16-bit, 32-bit, treel), nous avons cr des utilitaires nous permettant dune part, de concatner (Noyau\Outils\cat.exe) le boot avec la partie 16-bit du noyau, autrement dit, avoir un seul fichier qui contient le boot (512 octets), suivi juste aprs de la partie 16-bit. Dautre part, nous allons rajouter la partie 32-bit du noyau, au fichier ainsi obtenu, mais cette fois-ci la partie 32-bit sera loigne de la fin du premier fichier avec un dcalage spcifi comme paramtre lutilitaire : Noyau\Outils\Cat32.exe. A vrai dire, ce dcalage, est une rservation despace pour la partie 16-bit, pour une ventuelle extension. Contrairement Tlink.exe (de Borland), qui permet de crer un fichier binaire (sans entte de lexcutable), Tlink32.exe (de Borland) quant lui, ne dispose pas doption pour avoir un binaire pur (sans entte de lexcutable). La partie 32-bit et aprs lavoir link, contiendra un entte faisant 1536 octets (600h). Il va falloir ter cet entte, en crant un utilitaire (Noyau\Outils\flink.exe) qui suffit, de fournir en paramtre le fichier excutable et la taille de lentte, pour avoir un nouveau fichier spcifi galement en paramtre, et qui ne contiendra que le code excutable. Cest dailleurs ce fichier binaire qui sera utilis et rajout avec cat32.exe cit plus haut. Nous allons dtailler ces utilitaires dans le prochain paragraphe. A.2. La compilation A.2.1. Le boot Pour compiler le boot (boot.asm), il faudrait utiliser le MASM.exe, qui va gnrer un fichier OBJ, puis le linker avec Tlink.exe /t, pour avoir un fichier binaire. A.2.2. La partie 16-bit et utils Compiler tous les fichiers .asm (avec masm.exe) et .cpp (avec bcc.exe), et les linker avec Tlink.exe /t pour avoir un fichier binaire (ladresse de base par dfaut est 100h, qui concide avec ladresse de la partie 16-bit en mmoire qui par convention est 2000 :100h). A noter quil faudrait dfinir une variable denvironnement __C16__ pour le compilateur Bcc.exe avec loption D__C16__ afin dindiquer au prprocesseur quil sagit dune compilation de la partie 16-bit, et notamment pouvoir diffrencier les prototypes de fonctions dclares dans le fichier kernel.h (suivant le fait que la fonction appartient la partie 16-bit ou la partie 32-bit). En effet, nous avons dclar dans le mme fichier (kernel.h) aussi bien les fonctions 16-bit que celles du 32-bit. De plus, il se peut quune mme fonction puisse tre dclare dans les deux parties, par exemple les fonctions utilitaires (hexasc). En dclarant alors la variable denvironnement __C16__ le prprocesseur va ignorer ou exclure suivant le cas, les dclarations de lune des parties. Il est dclarer galement lemplacement par dfaut des fichiers inclus (Include), et dans notre cas, ils se trouvent tous lemplacement : Noyau\Include

Annexe. A

A.2.3. La partie 32-bit, Treel et utils Compiler tous les fichiers .asm (avec masm.exe), .cpp (avec bcc32.exe), et les linker avec Tlink32.exe, en indiquant ladresse de base 0x100000 (adresse o se logera la partie 32bit par convention), et ce, avec loption B :0xF0000 (1000h est ajout automatiquement cette valeur). Un peu similaire la partie 16-bit, il faudrait l aussi dclarer la variable denvironnement avec loption -D__C32__ pour que le prprocesseur puisse exclure les dclarations ou prototypes de la partie 16-bit se trouvant dans Noyau\Include\kernel.h. Dclarer galement lemplacement des fichiers inclus : Noyau\Include En sortie, nous allons avoir un fichier excutable (contenant un entte). A.2.4. Concatner le Boot et la partie 16-bit Une fois que nous aurions compil le boot et la partie 16-bit, et comme nous lavons soulign, il va falloir ensuite lier ou concatner ces deux parties pour avoir un seul fichier. Pour ce faire, nous allons utiliser lutilitaire cat.exe que nous avons dvelopp en C, qui consiste se positionner la fin du premier fichier, et crire partir de-l , le contenu du deuxime fichier. En sortie, le premier fichier (boot) sera modifi, et sa taille serait la taille du boot (512 octets) + la taille de partie 16-bit. La syntaxe pour lancer Noyau\outils\cat.exe est : cat.exe [fichier1] [fichier2] A.2.5. Extraire le binaire de lexcutable 32-bit Une fois la compilation de la partie 32-bit (partie 32-bit, Treel, Utils) est faite, il faudrait ce moment-l extraire le binaire(sans entte) du fichier excutable produit lors de la compilation (Etant donne la non disponibilit de loption sous Tlink32 (de Borland), pour produire un fichier binaire excutable sans entte). Pour ce faire, nous avons alors dvelopp en C, un utilitaire : Noyau\utils\flink.exe qui consiste se positionner (en octets) sur un emplacement dans le fichier spcifi en paramtre, puis de commencer la lecture partir de cet emplacement, et dinscrire en mme temps dans un autre fichier spcifi galement en paramtre, les donnes lues du premier fichier. Autrement dit, sachant la taille de lentte dun excutable compil en 32bit (qui est de 1536 octets convention Win32), nous pourrons lter et navoir ainsi que le code binaire ou excutable, dans un autre fichier. La syntaxe de Noyau\outils\flink.exe est alors la suivante : Flink.exe [fichier1] [fichier2] [dcalage] A.2.6. Concatner le (boot+16-bit) avec le binaire 32-bit Aprs avoir extrait le binaire de lexcutable 32-bit, il va falloir le concatner avec le fichier (boot+16-bit), ce dernier obtenu avec lutilitaire cat.exe Il faudrait nanmoins laisser un espace libre entre la fin de la partie 16-bit, et le binaire 32bit, et ce, pour une ventuelle extension de la partie 16-bit. Notre convention est de faire fixer le binaire 32-bit, au 19ime secteur physique sur disque (ou bien le 18ime aprs le secteur 0), autrement dit, la partie 16-bit aura ainsi une taille pouvant aller jusqu 17 secteurs physiques (lautre secteur est pris par le boot en premire position). Rappelons que la taille dun secteur physique est de 512 octets.

Annexe. A

Pour ce faire, nous avons dvelopp un utilitaire en C : Noyau\outils\cat32.exe, qui consiste faire concatner le binaire 32-bit spcifi en argument, avec le premier fichier (boot+16-bit) spcifi comme premier paramtre, avec un dcalage du deuxime par rapport au premier exprim en octets (daprs notre convention, le dcalage serait de 9216 octets, qui est quivaut 18 secteurs (incluant le 0) de 512 octets). Il suffit alors de dterminer la taille du premier fichier (boot+16-bit), de se positionner sa fin, et de remplir ou rajouter partir de-l des vides (0xFF), jusqu atteindre la taille de 9216 octets spcifis en argument, puis commencer cet emplacement-l, lcriture du fichier binaire 32-bit qui est donn en deuxime paramtre. En sortie nous allons avoir le premier fichier (boot+ 16-bit) modifi, et contiendra galement le boot+16-bit, un espace libre (de taille : 9216 - taille(boot+16-bit)), mais aussi la partie 32-bit. La syntaxe de Noyau\outils\cat32.exe est alors la suivante : Cat32.exe [fichier1] [fichier2] [taille atteindre pour le fichier1]

Bien videmment, le fichier rsultant suite cette dernire opration ne serait rien dautre que notre noyau, qui va se trouver dans la racine (Noyau\noyau.bin).

A.3. Le Make Etant donn le nombre important doprations ou de commandes pour effectuer la compilation, il faudrait songer tablir une mthode labore, qui va nous faciliter la tche dune part, et dautre part, viter les erreurs qui peuvent en rsulter. Pour ce faire, nous avons choisi dutiliser le Make de Borland. Au sein de chacune des parties compiler, et comme lindique larborescence des fichiers du noyau, nous avons crit un fichier de commandes pour le make, afin de raliser la compilation dune manire automatique. Nous supposons les commandes connues, et nous donnons ci-aprs que le fonctionnement gnral ou la logique avec laquelle le Make opre. Le lancement du Make se fait partir de la racine, via des fichiers BAT. Ces derniers correspondent aux exemples prsents dans le rpertoire Noyau\exemples\ suivant son type, le BAT va faire copier le source de lexemple, depuis le rpertoire correspondant, vers le rpertoire Noyau\Treel. En remplaant ventuellement ce, existant. Puis lance la commande .\Compil\make.exe f DTEST makTreel (pour lancer la compilation). Nous allons voir lutilit de la variable denvironnement TEST lorsque nous allons aborder loutils Bochs.

Annexe. A

Le fichier Maktreel se trouvant dans la racine va faire, son tour des appels travers des commandes du Make, pour le lancement de la compilation des parties suivantes : boot, 16, et 32 mais aussi et finalement la Concatnation, pour produire le noyau suivant la logique dcrite dans le paragraphe prcdent. Chacune des actions lances va effectuer la compilation de la partie correspondante, et galement ldition des liens. La dernire action est la Concatnation, dans cette partie, le boot est concatn avec la partie 16-bit. Le fichier produit va tre concatn avec la partie 32-bit, pour enfin avoir le noyau.bin copi dans la racine (Noyau\).

A.4. Installer le noyau sur disquette Pour pouvoir installer le noyau (Noyau\Noyau.bin) obtenu aprs compilation sur une disquette, nous avons dvelopp un utilitaire en C (compil avec bcc.exe), qui va lire chaque fois 512 octets partir du fichier spcifi en paramtre, et de les crire dans des secteurs physiques partir du secteur 0 de la disquette. Ceci en utilisant les routines BIOS de la librairie du C (16-bit) de Borland. La syntaxe de lutilitaire Noyau\outils\chargeur.exe est la suivante : Chargeur.exe [fichier] Pour viter lcriture de cette commande chaque fois que nous aurons charger le noyau sur disquette, nous avons mis en place un fichier dans la racine (Noyau\), portant le nom : INSTALLER_SUR_DISQUTTE.BAT, qui fera appel au fichier chargeur.exe avec comme paramtre : noyau\noyau.bin (noyau compil).

Annexe. B

B. Exemples dapplications temps rel


En vue de mettre en vidence les services du noyau, nous avons implment quelques exemples qui feront lobjet des sous-paragraphes prochains. Ces exemples sont loin dtre des applications temps rel proprement dites, car, celles-ci sont souvent difficiles mettre en uvre, puisquelles utilisent des capteurs qui ncessitent une prise en charge du ct noyau (drivers de priphriques), ce qui sort de lobjectif de notre travail. Nous allons prendre en charge nanmoins quelques priphriques dE/S standards savoir, laffichage, le clavier, et le port parallle (LPT). B.1. Exemple avec PCP Le premier exemple sera celui vu au premier chapitre (paragraphe 1.5.1.7.1. page 25) traitant linterblocage. Lexemple va dmontrer que la situation dtreinte fatale est vite par le protocole priorit plafond (PCP) (c--d que nous allons avoir en sortie, la solution donne dans la figure 1.15. page 29 du premier chapitre). Pour cela, il faudrait dboguer les primitives P(s) et V(s), en affichant des informations et leur tat de traitement chaque fois que lappel est fait ces primitives ; des informations comme : la tche demandante du smaphore, lidentit du smaphore, lhritage de priorit, et le blocage suite une non vrification de conditions du PCP. Il faudrait alors utiliser la version dbogue du scheduler dans : Noyau\Treel\Debug\schedule.cpp . Le lancement du fichier BAT (exemple PCP) dans la racine (Noyau\) permet de compiler automatiquement la version debug du scheduler en incluant le prsent exemple. Il va falloir aprs cela, implanter les fonctions ncessaires, et ce, dans le fichier rserv aux applications temps rel (applic_tr.cpp) qui sera copi lors de la compilation vers lemplacement : Noyau\Treel\ pour tre compil. Comme nous lavons dj soulign dans la partie ralisation, une fois linitialisation de la machine est faite, un appel de fonction est effectu application_tr( ) en vue de lancer lapplication temps rel. Elle sera considre en quelque sorte, comme la fonction main( ). Au sein de la fonction application_tr( ), nous avons crit le code initialisant les deux tches (thread1 et thread2) conformment lexemple du premier chapitre (interblocage -page 25) mais avant cela, et comme les deux threads sont susceptibles dutiliser des smaphores, il a fallu crer les smaphores (creer_semaphore( ) ) et de les ajouter dans une file qui sera associe aux thread1 et thread2. La premire file, dont nous avons nous mme donn le numro 0, sera celle qui sera associe la thread1, en vue dutiliser respectivement les smaphores R2 et R1. Pour cela deux appels de fonction add_semaphore_file (lordre des appels nest pas tenu en compte) sont ncessaires, pour dclarer avec le numro de file 0, les smaphores (R1 et R2), mais aussi le temps de la section critique associe pour chacun des smaphores utiliser, et dans notre cas, il serait de 2 units de temps pour R1 et de 4 units de temps pour R2. Les units de temps sont les quantums du systme , et il y a 1024tops/seconde. Idem pour la deuxime file, dont le numro que nous lui avons attribu est 1, et le temps dexcution des sections critiques est de 5ut pour R1 et 2ut pour R2.

Annexe. B

Une fois les smaphores dclars et insrs dans la file des smaphores associs aux tches ce nest quaprs cela que nous pouvons procder la cration des tches (thread1 et thread2). Et pour ce faire, il suffit dappeler la fonction creer_tache avec les paramtres comme ladresse de la fonction ou de la thread (thread1 ou thread2), la date de rveil (1ut pour thread1 et 4ut pour thread2), la capacit de la tche ou sa dure dexcution (5 pour la thread1 et 6 pour la thread2), la priode de la tche(100 pour thread1 et 101 pour thread2, ceci pour juste faire en sorte que la thread1 soit plus prioritaire que thread2), et enfin le numro de la file des smaphores utiliser (comme nous lavons dj suggr, le numro de file 0 pour la thread1 et le numro de file 1 pour la thread2). Il faudrait tester chaque appel de fonction creer_tache le numro renvoy par celle-ci, sil est ngatif alors il sagit dune erreur sinon il reprsente lidentifiant de la tche. Pour tester la faisabilit ou lordonnanabilit de ce systme, il va falloir lancer la fonction faisabilite( ), qui, dans notre cas, va dterminer les facteurs de blocage de chacune des tches, en les calculant avec lalgorithme de K.Tindell et H.Hansson donn au premier chapitre (Facteur de blocage page 30). Une fois les facteurs de blocage calculs, la fonction faisabilite( ) va vrifier la condition de faisabilit RM en tenant compte des facteurs de blocage calculs (voir premier chapitre page 31). La fonction renvoie un nombre ngatif en cas dune non satisfaction de cette formule. Rappelons que cette condition est ncessaire mais pas suffisante. Nous devons aprs cela, lancer lordonnancement de ces tches, en faisant appel la fonction activer_horloge( ). Pour le corps de thread1 et thread2, nous avons tout simplement imit le comportement de lexemple dinterblocage. pour respecter les dlais dattente notamment entre les primitives sur les smaphores, nous avons utilis la fonction attendre_tache_delai dont le dlai pass en paramtre est exprim en s. Le source de cet exemple est le suivant :

Annexe. B #include <kernel.h> #include <proc.h> SEMAPHORE R1; SEMAPHORE R2; /********************************************************************/ thread1() { suspendre_tache_delai(1000); P(R2); suspendre_tache_delai(2000); //attendre 2000s = 2ms P(R1); suspendre_tache_delai(2000); V(R1); V(R2); } /********************************************************************/ thread2() { suspendre_tache_delai(1000); P(R1); suspendre_tache_delai(4000); //attendre 4000s P(R2); suspendre_tache_delai(2000); V(R2); V(R1); } /********************************************************************/ void application_tr() //le noyau appelle cette fonction { int i,j,k; R1=creer_semaphore(); R2=creer_semaphore(); add_semaphore(0,R1,2); add_semaphore(0,R2,4); add_semaphore(1,R1,5); add_semaphore(1,R2,2); //(la file 0, smaphore R1, temps de la SC:2ut)

//(la file 1, smaphore R1, temps de la SC:5ut)

i=creer_tache((THREAD)&thread1,4,5,100,0/*file 0 des smaphores */); if (i<0) print_rt("Erreur -%d: Cration de Tache0\n",-i); else print_rt("Tche %d priodique. Ressources utiliser R2 et R1\n",i); i=creer_tache((THREAD)&thread2,1,6,101,1); if (j<0) print_rt("Erreur -%d: Cration de Tache1\n",-j); else print_rt("Tche %d priodique. Ressources utiliser R1 et R2\n",j); k=faisabilite(); //faisabilit RM avec facteur de blocage if (k<0) print_rt("Faisabilit erreur: -%d\n",-k); else print_rt("Faisabilit ... OK\n"); print_rt("priorite de tache[%d]: %d Facteur de blocage Bi=%d\n",i,tache[i].priorite,tache[i].sched.Bi) ; print_rt("priorite de tache[%d]: %d Facteur de blocage Bi=%d\n",j,tache[j].priorite,tache[j].sched.Bi) ; activer_horloge(); while(1); } // activer l'horloge temps rel

Annexe. B

B.2. Exemple de tches priodiques Cest un exemple disant trivial mais important, qui permet de voir lexcution de trois tches priodiques en excution. Dans cet exemple encore, nous avons implment, ce, donn dans le premier chapitre (Exemple2 page 20). Les corps des threads associes aux tches priodiques crer, ont des boucles infinies, mais nous voulons nous accentuer sur la manire dont le scheduler fonctionne. Pour cela, nous allons utiliser la version dbogue du scheduler et de tche se trouvant respectivement dans : Noyau\Treel\Debug\schedule.cpp et Noyau\Treel\Debug\tache.cpp. Il suffit de lancer le fichier BAT (exemple priodiques) partir de la racine (Noyau\) pour quil compile automatiquement la version dbogue, en incluant le prsent exemple. Le code source (Noyau\exemples\perio\applic_tr.cpp) de cet exemple est le suivant :
#include <kernel.h> #include <proc.h> thread1() { while(1); } thread2() { while(1); } thread3() { while(1); } /*******************************************************************/ void application_tr() //fonction appele par le noyau { int i,j,k,l; i=creer_tache((THREAD)&thread1,0,3,20,0); if (i<0) print_rt("Erreur -%d: Cration de Thread1\n",-i); else print_rt("* Tche %d priodique. Priorit: %d\n",i,tache[i].priorite); j=creer_tache((THREAD)&thread2,0,2,5,0); if (i<0) print_rt("Erreur -%d: Cration de Thread2\n",-i); else print_rt("* Tche %d priodique. Priorit: %d\n",j,tache[j].priorite); k=creer_tache((THREAD)&thread3,0,2,10,0); if (k<0) print_rt("Erreur -%d: Cration de Thread3\n",-k); else print_rt("* Tche %d priodique. Priorit: %d\n",k,tache[k].priorite); l=faisabilite(); //faisabilit RM sans partage de ressources if (l<0) print_rt("Faisabilit erreur: -%d\n",-l); else print_rt("Faisabilit ... OK\n"); activer_horloge(); while(1); }

Annexe. B

B.3. Exemple de tche apriodique et priodiques Cet exemple va nous permettre dune part, de comprendre la manire de crer une tche temps rel apriodique, prise en charge par une tche priodique particulire dite serveur. Dautre part, mettre laccent sur la diffrence entre notre excutif temps rel, et les systmes classiques (non temps rel). La tche apriodique que nous allons crer va prendre en charge le priphrique clavier, puisque les signaux provenant de celui-ci sont apriodiques ou surviennent dune manire alatoire dans le temps. Son rle est alors de lire le caractre tap depuis le clavier, et de le mettre dans une zone tampon. Une tche priodique sera cre pour rcuprer les caractres dposs dans la zone tampon par la tche apriodique, et les afficher. Si le tampon est vide elle se mettra en attente. Une autre tche priodique va sexcuter en parallle aux tches prcdantes. Son rle sera de gnrer un signal carr sur le port LPT (port parallle) de priode double celle de la tche qui le gnre. A vrai dire, cet exemple est une exprience qui va essayer de mettre en vidence limportance de notre systme temps rel pour certaines applications critiques, en le comparant un autre exemple similaire mais implment sur un systme classique (Linux et Windows98 de Microsoft). Le but de lexprience est alors de voir le comportement du signal carr gnr par la tche priodique sur le port LPT dans le cas de notre systme, et de le comparer celui gnr dans un systme classique (Linux et Windows98 de Microsoft). Pour ce faire, il faudrait disposer dun oscilloscope (lidal quil soit numrique), et dun cble connect la deuxime broche du port parallle, qui correspond au bit D0 de donnes. Nous allons dcrire prsent le corps des tches que nous aurons implmenter sur notre excutif. B.3.1. Tche apriodique Cette tche comme nous lavons dj voqu, va soccuper de mettre les caractres taps depuis le clavier, dans une zone tampon. Pour lire un caractre depuis le clavier, dans le cas dun IBM PC, il faudrait dabord tester sil est possible de la faire, ceci indiqu par le bit 1 du port 64h. Si ce bit est 0, alors le caractre peut tre lu partir du port 60h. La tche apriodique thread_clavier va tester cette condition, puis le cas chant lire le caractre. Si la valeur de ce dernier est infrieure 85 (il sagit dun appui dune touche et non pas une relche, car pour ces deux tats, une interruption clavier est provoque), et que le buffer ou le tampon clavier nest pas dbord, alors il va falloir avant dinsrer le caractre dans le buffer, le convertir suivant une table map (kbdmap[ ]) qui va transformer le code du caractre en valeur correspondante au clavier franais.

Annexe. B

B.3.1.1. Signal apriodique Comme nous lavons abord dans le chapitre ralisation, la signaler_aperiodique(unsigned short int id_tache) ; fonction :

Est responsable de signaler ou de mettre dans la pile des apriodiques, lidentifiant id_tache de la tche apriodique correspondante. Nous avons dit que cette fonction doit tre appele au sein de la routine dinterruption correspondante la tche apriodique. Nous devons alors ajouter lappel de fonction signaler_aperiodique dans la routine dinterruption associe au clavier (void call_int51 ( ) dans le fichier Noyau\32\ints.cpp), cependant, la fonction signaler_aperiodique ncessite un paramtre qui reprsente lidentifiant de lapriodique. Or, nous ne disposons pas de cette valeur ; la solution est de dclarer une variable globale : id_aperiodique_clavier, et de lutiliser dans lappel de fonction signaler_aperiodique se trouvant comme nous lavons dit au sein de la routine dinterruption clavier. Le fait de crer la tche apriodique au sein de la fonction application_tr ( ), va nous dlivrer son identifiant avec lequel nous allons forcer la variable globale ainsi dclare (id_aperiodique_clavier).

B.3.2. Tche priodique daffichage Cette tche dont la thread est : thread_affichage va extraire les caractres dposs ventuellement par la tche apriodique, pour les afficher. Elle doit dabord tester sil y a un caractre dans le tampon clavier, autrement dit, tester si la valeur du pointeur bas de la file du tampon bot_buffer_clavier nest pas gale la valeur du pointeur haut de la file du tampon top_buffer_clavier, pour ensuite afficher le caractre se trouvant lemplacement bot_buffer_clavier par le biais de la fonction print_rt Autrement, elle doit attendre, et ce, tant que les pointeurs sont gaux. B.3.3. Tche priodique du signal carr Cette tche dont le corps est thread_signal, va mettre tantt 1 et tantt 0, les bits de donnes du port LPT. Sur lIBM PC, le port de donnes du port parallle est 378h. Une valeur sig initialise 0, va tre inverse et envoye chaque fois que la tche est lue, sur le port LPT avec la fonction dE/S outpb, que nous avons crit dans le fichier : Noyau\Utils\32\Utils.cpp Pour ne pas avoir une modification du signal ainsi envoy durant la dure dexcution de la tche, il va falloir maintenir le niveau du signal durant la capacit de la tche, en utilisant la fonction attendre_tache_delai pour ce faire. De cette manire, nous allons avoir un signal carr dune priode gale au double de celle de la tche priodique du signal carr. Autrement dit, le signal est invers une seule fois lors de llection de la tche, puis celle-ci se bloque (pendant sa capacit dexcution), jusqu la prochaine lection, pour inverser une autre fois le signal et ainsi de suite.

Annexe. B

B.3.4. Cration des tches La cration des tches, le test de faisabilit, ainsi que lactivation de lhorloge temps rel doit se faire au sein de la fonction application_tr( ), qui, rappelons-le, est appele par notre noyau temps rel. La tche apriodique est cre par la fonction creer_tache, avec comme priode 0, et une date de rveil qui ne sera pas prise en charge. Pour pouvoir ordonnancer lapriodique ainsi cre, il faudrait crer la tche serveur avec la fonction creer_serveur dont les paramtres sont : la date de rveil, la capacit dexcution et la priode. Les deux autres tche priodiques (affichage et signal carr) seront cres de la mme manire que celle vue dans les prcdents exemples.

B.3.5. Rsultats obtenus sur machine relle En posant la valeur 2ut comme priode de la tche priodique du signal carr, celle du serveur 10ut, et de laffichage 15ut ; nous avons pu effectivement obtenir un signal parfaitement carr (sur un oscilloscope analogique) dune priode de 4ms. En enfonant des touches sur le clavier, celles-ci sont bien affiches, sans pour autant perturber le signal carr. Ceci sexplique par le fait que la tche produisant le signal carr est la plus prioritaire dans le systme, et alors aucune tche ne la prempte. Notons aussi le fait de jouer sur la priode de la tche priodique daffichage, agit bien videmment sur le temps de rponse daffichage. La capacit de la fonction daffichage quant elle, contrle ou influence sur le nombre de caractres extraire et afficher dune traite. Maintenant si nous rendons la tche priodique du signal carr beaucoup plus importante que celles des autres tches (affichage et serveur), nous observerions sur loscilloscope, des perturbations ou une gigue (jitter) sur le signal carr gnr. Ceci veut dire que le signal soit, il est maintenu 1 ou 0, et ce, pendant que lautre tche (affichage ou serveur) qui a prempte celle qui dlivre le signal carr, est en excution. Cependant nous sommes certains daprs la vrification du test de faisabilit RM, que les prolongements des bits 1 / 0 dont nous avons parl, ne peuvent dpasser dans le temps leur priode (dlai critique), ou en dautre terme lchance. Celle-ci est dailleurs une caractristique majeure dun systme temps rel. En effectuant le test sur des systmes dexploitation classiques (Linux, Windows98 de Microsoft), nous constatons que le systme gnre bien au repos un signal carr avec la priode spcifie, mais ds que nous stressons le systme (touches claviers, souris ), dimportantes perturbations sont vues sur loscilloscope. La gigue sur le signal carr, dpasse de loin sa valeur critique ou sa priode. Il est clair que ces systmes ne sont pas alors des systmes temps rel, et ne peuvent tre utiliss pour contrler des procds contraintes temporelles.

Annexe. B

#include <kernel.h> #include <proc.h> #define LPT 0x378 extern u8 kbdmap[]; //contient la map du clavier

char buffer_clavier[256]; char *bot_buffer_clavier; char *top_buffer_clavier; extern u8 id_aperiodique_clavier; /******************************************************************/ thread_clavier() { u8 i=0; while((inpb(0x64) & 0x01) == 0); i=inpb(0x60); i--; if ((i<=85) && (top_buffer_clavier <= &buffer_clavier[256])) *(top_buffer_clavier++)=kbdmap[i*4]; /*insertion du caractre lu depuis la map clavier, dans le buffer clavier*/ else if (i<=85) { print_rt("Buffer clavier plein :%p\n",top_buffer_clavier); } } /******************************************************************/ thread_affichage() { char c; //extraction d'un caractre du tampon clavier while(1) { if (bot_buffer_clavier!=top_buffer_clavier) { goto label; } else bot_buffer_clavier=top_buffer_clavier=&buffer_clavier[0]; while(bot_buffer_clavier==top_buffer_clavier); /*attente d'une insertion d'un caractre*/ label: print_rt("%c",*bot_buffer_clavier++); } }

Annexe. B /**********************************************************************/ thread_signal() { u8 sig=0; while(1) { outpb(LPT,sig=~sig); suspendre_tache_delai(1000); /* mentient le niveau du signal jusqu'a l'epuisement de la capacite (1ms)*/ } } /***********************************************************************/ void application_tr() { int i; i=creer_tache((THREAD)&thread_clavier,0,1,0,0); if (i<0) print_rt("Erreur -%d: Cration de l'apriodique clavier.\n",-i); else { id_aperiodique_clavier=i; /* sera utilis dans la routine d'interruption pour signaler l'arrive de l'IT (voir call_int51 dans .\32\ints.cpp).*/ print_rt("* Tche [%d]: Apriodique associe au clavier (Ci=%dut)\n",i,tache[i].sched.ci); } i=creer_tache((THREAD)&thread_affichage,0,1,15,0); if (i<0) print_rt("Erreur -%d: Cration de la priodique affichage.\n",-i); else print_rt("* Tche [%d]: Priodique pour l'affichage (Ci=%dut Pi=%dut)\n",i,tache[i].sched.ci,tache[i].sched.pi); i=creer_tache((THREAD)&thread_signal,0,1,2,0); /*pour un signal carr sur LPT, la priode est de 2ut<=> 1.953ms*/ if (i<0) print_rt("Erreur -%d: Cration de la priodique pour le signal carr (LPT).\n",-i); else print_rt("* Tche [%d]: Priodique pour le signal carr (LPT). (Ci=%dut Pi=%dut)\n",i,tache[i].sched.ci,tache[i].sched.pi); i=creer_serveur(0,1,10); if (i<0) print_rt("Erreur -%d: Cration du serveur des apriodiques.\n",i); else print_rt("* Tche [%d]: Serveur d'apriodiques (Ci=%dut Pi=%dut)\n",i,tache[i].sched.ci,tache[i].sched.pi); i=faisabilite(); // test de faisabilit RM (ordonnanabilit) if (i<0) print_rt("Faisabilit erreur: -%d\n",-i); else print_rt("Faisabilit du systme... OK.\n"); activer_horloge(); while(1); }

Annexe. C

C. Emulateur du x86 dIntel (Bochs)


Programmer un systme dexploitation nest pas une mince tche faire. Des bugs peuvent survenir au cours dexcution, sans pour autant avoir la possibilit de voir la cause du crash ou de lanomalie. Dautant plus quil est pnible de relancer la machine aprs avoir recompil et charg sur disque le noyau du systme dexploitation, chaque fois que nous aurons rectifier ou essayer une nouvelle version de ce noyau. Heureusement loutil Bochs existe, et tourne sur plusieurs plates-formes (Linux, Win32), et permet dmuler une machine IBM PC base sur un processeur Intel 386/486. Avec Bochs, nous pouvons dsassembler le code du noyau, facilitant ainsi la maintenance, la dtection des bugs, mais aussi gagner un temps considrable lors du dveloppement. Bochs est alors une machine virtuelle ou en dautres termes un logiciel crit en C++ disposant de toutes les fonctionnalits que celles prsentes dans une machine relle. Cest ainsi que nous pouvons paramtrer dans le fichier de configuration de Bochs, la quantit de mmoire RAM, les MIPS CPU, Nous avons test avec le logiciel Bochs, plusieurs systmes dexploitation connus (Linux, Windows 98 ), lexcution est assez lente nanmoins cause du nombre important de calculs effectus par ce logiciel. Deux interfaces sont prsentes sous Bochs : - Interface de commandes ; - Interface graphique (GUI) pour visualiser les rsultats (ressemble lcran dune machine relle).

C.1. Interface de commandes de Bochs Cette interface est semblable un shell, travers laquelle nous pouvons lancer la simulation du noyau, faire des breakpoints, dsassembler la CPU virtuelle Nous allons donner ci-aprs quelques commandes ncessaires pour lancer lexcution et manipuler la CPU. Pour les autres commandes, taper la commande : help

c : permet de lancer la simulation. lb adresse_physique : permet de faire un breakpoint ladresse physique indique. CTRL+C : permet dinterrompre la simulation lance et retourne au dbogueur. xp adresse_physique : permet dafficher le contenu de ladresse physique. print-stack : permet dafficher la pile du processeur point par ESP/SP. info reg : permet dafficher (Dump) les registres gnraux de la CPU. info cpu : permet dafficher tous les registres de la CPU.

Annexe. C

C.2. Interface graphique (GUI) de Bochs Cette interface comme nous lavons soulign, reprsente lcran simul par Bochs. Cest ainsi que nous pouvons voir les rsultats du traitement effectu par Bochs. Il existe des commandes graphiques sur cette interface, permettant larrt de Bochs, le redmarrage, une capture de lcran Bochs dans un fichier Il faut noter que lors du lancement de la simulation, et si le programme simul autorise la capture de caractres partir du clavier, alors il est possible aprs avoir rendu la fentre de cette interface active, de taper les caractres partir du clavier de la machine relle. Exemple Voici un exemple de linterface graphique (GUI) de Bochs lance avec notre noyau temps rel, avec lexemple dapriodique donn lannexe B.

Annexe. C

C.3. Les fichiers associs Bochs Dans lannexe A (arborescence des fichiers), nous avons prsent dans le rpertoire Boch, les fichiers quil contient. Ces fichiers sont une configuration du logiciel Bochs, de son BIOS pour le dmarrage, de sa ROM VGA, ainsi quun fichier de sortie. Tous ces fichiers doivent tre spcifis Bochs, par le biais du fichier de configuration, qui, dans notre cas est boch.conf. Ce dernier contient toute la configuration de la machine, de lemplacement du fichier image (noyau lancer) et doit tre spcifi en paramtre avant le lancement de la simulation. C.4. Lancer Bochs aprs compilation du noyau Nous avons voqu dans lannexe A (Le make), quil y a une variable denvironnement du Make, nomme TEST, qui, suivant sa prsence, dcider sur le lancement de la simulation de notre noyau compil avec loutil Bochs. Si la variable TEST est dfinie, le noyau compil (Noyau\noyau.bin) sera lanc sur la machine Bochs, et ce, aprs avoir bien sr configur le fichier boch.conf pour supporter ou prendre en charge ce noyau.