Exécutif Temps réel
Limitation des système classiques Rappels Mise en œuvre lourde des communications entre processus Problème de prédictibilité avec les optimisations matérielles et logicielle Gestion grossière du temps L'ordonnancement favorise l'équité
Platform fork()pthread_create() realusersysrealusersys IBM 375 MHz POWER IBM 1.5 GHz POWER IBM 1.9 GHz POWER5 p INTEL 2.4 GHz Xeon INTEL 1.4 GHz Itanium fork_vs_thread.txtork_vs_thread.txt
Utilisation des tâches Le concept de processus indépendant rend complexe le processus de communication Utilisation des tâches Les tâches partagent le même espace mémoire Définitions Un noyau temps réel assure la gestion des tâches et de la mémoire Un exécutif assure les services nécessaires à l'utilisation des entrées/sorties, réseau et fichiers Ces services sont modulaires, ils sont donc configurables en fonction des architectures cibles. Un système d'exploitation temps réel repose sur un exécutif temps réel
Notion des états d'une taches Prête Exécutée Bloquée Endormie Créée Existante Existante non initialisée Suppression Initialisation Attente blocante Préemption Election Attente d'une durée Réveil Arrivée evt
Outils de communication Les tâches interagissent en se synchronisant et en communiquant Les sémaphores, les moniteurs et les variables conditionnelles permettent d'implémenter les outils nécessaires
Les sémaphores Un sémaphore est une variable n-aire. pour n=2 deux états sont possibles : pris pas pris On parle de Mutex (Mutual exclusion) lorsqu'il est utilisé pour assurer l'exclusion mutuelle pour n>2 si le sémaphore est pris la valeur = 0 sinon des instances sont libres
Caractérisation d'un compteur avec plafond Sémaphore Valeur n>=0 Valeur max des tâches l'utilisant File d'attente {tâches, nb instances}
Moniteur Proposé par Hoare 1973 l'idée est d'encapsuler une ressource, et de ne permettre son utilisation qu'au travers des primitives qui elles-mêmes sont protégées contre la réentrance. La réentrance d'une primitive a lieu lorsqu'un processus exécute le code d'une primitive, et qu'il est interrompu par un processus exécutant lui aussi la primitive.
Exemple Variable : X Incrémenter Décrémenter Lire P1 P2 Variable : X ?
Variable : X Incrémenter Décrémenter LireExemple X invisible de l'extérieur X invisible de l'extérieur Incrémenter Décrémenter Lire Le moniteur possède des variables internes accessibles uniquement par des primitives non réentrantes.
Exemple de code Moniteur moniteur_ressource ressource=0; Procedure add ressource++; Procedure sub ressource--; End_moniteur A cause de la non-réentrance, il est impossible que deux tâches aient accès simultanément à ressource via add ou sub. L'exclusion mutuelle est donc garantie par la non-réentrance. Appel de fonction : moniteur_ressource.add Il reste à bloquer les processus de façon efficace.
Blocage : cas du producteur/consommateur Moniteur prod_cons taille T:tampon(taille) nb_pris=0 Procédure produire(e:element) while (nb_pris=taille) do wait // dort mis dans l'état prêt mettre e dans T nb_pris++ signal } // reveil Procédure consommer(&e:element) while (nb_pris=0) do wait nb_pris enlever et retourner un element de T signal } } Appel avec prod_cons.consommer ou prod_cons.produire
Variable conditionnelle Les variables conditionnelles sont des outils de base conjointement utilisés avec des sémaphores d'exclusion mutuelle pour la construction de moniteurs de Hoare. En effet, la primitive wait d'un moniteur de Hoare consiste à libérer et à placer la tâche dans l'état bloquée de façon atomique. Cette portion de code doit être atomique ce que permet les variables conditionnelles.