Exécutif temps réel
Transcription
Exécutif temps réel
Exécutif temps réel Pierre-Yves Duval (cppm) Ecole d’informatique temps réel - La Londes les Maures 7-11 Octobre 2002 Plan Exécutif Tâches Evénements et synchronisation Partage de ressources Communications entre taches Gestion de la mémoire Gestion du temps Interruptions Fichiers temps réel POSIX et le temps réel 1 Rôle d’un exécutif Principal : - ordonnancer les exécutions des tâches mais aussi: - protéger l’accès aux ressources partagées - recevoir et transmettre les signaux de synchronisations Composé d’agences spécialisées dans un type de fonction - gestion des tâches - gestion des événements matériels et logiciels (de synchronisation) - gestion communications entre tâches - gestion du temps - gestion des ressources partagées - gestion de la mémoire - gestion des exceptions Structure d’un exécutif Tâches applicatives Appels de service activation horloge lanceur ordonnanceur communication agence événements agence tâches agence Exécutif temps agence ressources agence interruptions Monde matériel 2 Exécutif ou noyau temps réel C’est d’abord un système d’exploitation. La principale différence entre un OS généraliste et un OS temps réel est le comportement très déterministe. Ensuite on trouvera quelques différences dans l’API (voir POSIX à la fin): -politique d’ordonnancement plus élaborée -gestion plus précise de plus de réveils (timers) à la résolution plus fine -plus d’ouverture sur le hardware sous-jacent en particulier les connexions aux IT matérielles -plus de modularité dans la construction du noyau Tâche Agent actif d’une application avec 4 attributs: -contexte d’exécution registres du processeur, pile exécution, ressources détenues - priorité -état d’exécution -état de protection (préemptible ou pas) 3 Tâche Dans les OS d’aujourd’hui les tâches sont implantées comme des fils d’exécution (thread). L’ordonnanceur de l’OS gère les threads/tâches. La notion de processus définie un espace d’adressage protégé dans lequel s’exécute au moins une tâche (le main thread) qui est activé quand le processus est lancé. Le processus se termine quand la dernière tâche qu’il contient se termine. Dans certains OS simples il n’y a pas d’espace mémoire protégé, il y a identité entre les termes: processus = thread = tâche Etats d’exécution SCEPTRE Inexistant Supprimer Créer Supprimer Hors Services Lancer Arrêter Arrêter Créer Actif Supprimer Continuer Sélection Prêt Opération d’attente En Cours Préemption En Attente Arrivée événement 4 Synchronisation par événements synchrones Phases temporelles de l’occurrence d’un événement: apparition production prise en compte consommation Code d’IT jusqu’à l’appel du service de signalisation Délai de réveil tâche destinataire Traitements avant effacement Les événements sont dits synchrones si l’application consommatrice va les lire de façon explicite. Synchronisation par événements synchrones Types d’événements: Fugace: Si aucune tâche est en attente à son occurrence il est perdu Mémorisé: L’occurrence est mémorisée mais aucune autre ne sera prise en compte avant sa consommation A compte: Mémorisé avec incrémentation du compteur à chaque occurrence et décrémentation chaque consommation 5 Synchronisation par événements synchrones Services génériques événements Créer (événement) Supprimer(événement) Attendre_occurrence( événement ) Signaler_occurrence( événement ) IT Lire data Copie mémoire Signaler(evt) Créer (evt) Boucle Attendre(evt) Traiter data Fin boucle Synchronisation par événements synchrones: exemple /* variable condition POSIX utilisable avec rtlinux */ /*-----------------------------------------------------------*/ pthread_cond_t cond; void coureur(){ int ret; ret = pthread_cond_timedwait(&cond, …, délai ); courrir(); } void arbitre(){ int ret; decompte(); ret = pthread_cond_signal(&cond); } main(){ int ret; ret = pthread_cond_init(&cond, NULL); ret = pthread_create( …, coureur, …); ret = pthread_create( …, arbitre, …); attente_fin(); } 6 Signalisation asynchrone Une tâche est associée à un signal et elle sera automatiquement activée quand l’événement associé au signal arrivera. La tâche est appelée pilote (handler) du signal. La tâche n’a donc pas besoin de se mettre en attente du signal. Exemple: signaux UNIX (lent), attachement à une IT matérielle Services génériques signaux asynchrone: Créer( signal )/ Détruire( signal ) Connecter( pilote, signal ) Envoyer( signal ) Il peut exister des masques qui permettent d’empêcher temporairement la réception de signaux (avec perte, mémorisation ou comptage) Signalisation asynchrone: exemple /* signal POSIX simple */ /*---------------------------*/ int stopbit; void signalled(){ stopbit = 1; } main(){ stopbit = 0; signal( SIGINT, signalled); while( !stopbit) { … faire un travail qui sera arrêté par CtrlC …} terminer_proprement(); } 7 Partage de ressources Problème: - gérer un nombre limité de ressources ( de 1 à n ) entre plusieurs tâches - assurer la modification cohérente de données partagées Objet: Sémaphore binaire (mutex) un utilisateur à la fois Sémaphore à compte pour n utilisateurs maxi Autres possibilités déconseillées en temps réel: masquage des IT ou interdiction de préemption Partage de ressources Services génériques sémaphores: Créer(sem)/Détruire(sem) Prendre_ressource(sem) parfois appelée P() Libérer_ressource(sem) parfois appelée V() sem Créer(sem) Boucle … Prendre(sem) Insérer(elem,liste) Libérer(sem) … Fin boucle Détruire(sem) liste Boucle … Prendre(sem) exploiter(liste) … sortir(elem,liste) Libérer(sem) Fin boucle 8 Partage de ressources: exemple /* sémaphore à compte POSIX */ /*------------------------------------*/ sem_t sem; void consommateur(){ ret = sem_wait(&sem); manipuler_ressource(); sem_post(&sem); } main(){ sem_init(&sem, …, nombre_utilisateurs); for ( i=0; i<10; i++) { pthread_create( …, consommateur, …); } attente_fin(); sem_destroy(&sem); } Communication entre tâches Boite aux lettres Service de base permettant les échanges asynchrones de données entre des tâches concurrentes et non synchronisées Services génériques (c’est un buffer) Créer(boite)/Supprimer(boite) Déposer(mesg) Lire(mesg) Test(mesg) Exemple: FIFOs, tubes UNIX, queues de messages (POSIX ou system V) (étendues au réseau QNX), mailbox 9 Communication entre tâches Boite au lettres: Queue de message POSIX Tâche réceptrice dans processus 2 #define MQ "/monrep/mesgq" mqd_t qfd; struct mq_attr qattr; char message_lu[20]; /* nb max msg en queue */ qattr.mq_maxmsg = 32; /* taille maxi d’un message */ qattr.mq_msgsize = 20; void recepteur(){ qfd = mq_open (MQ, … , &qattr); mq_receive (qfd, message_lu, sizeof (message_lu),…); print(" %s " , message_lu); mq_close(MQ); } Tâche émettrice dans processus 1 #define MQ "/monrep/mesgq" mqd_t qfd; struct mq_attr qattr; /* nb max msg en queue */ qattr.mq_maxmsg = 32; /* taille maxi d’un message */ qattr.mq_msgsize = 20; void émetteur(){ qfd = mq_open (MQ, … , &qattr); mq_send (qfd, "tout va bien", … ); mq_close(MQ); mq_unlink(MQ); } Communication entre tâches Socket: programmation répartie Objet de communication applicatif (BSD UNIX) qui permet un échange point à point de type boite aux lettres entre deux tâches sur deux sites différents (sorte de queue de messages). Ces points sont reliés aux couches réseaux de l’OS qui assurent le transfert (TCP ou UDP pour Internet). Intérêt: Base de la programmation distribuée - indépendante de l’OS - utilisables en local avec des sockets du domaine UNIX. 10 Communication entre tâches Tableau noir Publication de données dans un espace accessible en lecture par tous les consommateurs. Exemples: mémoire partagée entre processus (shared memory), données globales entre thread d’un même processus Services génériques: Créer/Détruire Afficher/Lire Communication entre tâches Rendez-vous Modèle de communication très synchrone ou producteur et consommateur doivent être présents lors de l’échange de donnée. Exemple: support d’exécution du langage ADA Services génériques: Appeler_entrée demande de rendez-vous Accepter_entrée déclaration de la capacité à recevoir des demandes de rendez-vous Terminer_entrée 11 Gestion de la mémoire Selon les possibilité du hardware sous jacent on peut avoir 3 type de gestion de la mémoire. -espace plat ou toute la mémoire est visible et accessible par n’importe quelle tâche -séparation entre les espace système/noyaux et les tâches applicatives -mémoire virtuelle séparée et protégée associée à chaque processus L’allocation de la mémoire peut être statique (à la création) ou dynamique (automatique) en fonction des besoins Gestion du temps La précision dépend du support matériel - horloge temps réel - réveils (timer) disponibles sur la carte. L’horloge génère un signal périodique qui sert de pulsation à l’activité de l’exécutif et maintien la date de la machine Les tâches utilisatrices peuvent: -obtenir la date -se synchroniser sur une durée -se synchroniser sur une heure absolue -limiter un blocage sur un délai de garde (timeout) 12 Gestion du temps Services génériques: Initialiser_date Lire_date/Lire_heure Attendre_date(date) Signaler_a_date(date) Attendre_délai(delai) suspend la tâche jusqu’à la date signaler un événement à une date suspendre la tâche pendant un délai Créer_réveil/Supprimer_réveil réveil=timer Arrêter_réveil Signaler_top_horloge permet d’envoyer un signal périodique Certain OS offrent des possibilités pour une tâche de se déclarer comme périodique et de se faire activer avec une période donnée. Gestion des interruptions Prend en compte les sollicitations matérielles du monde extérieur. Une routine d’interruption (ISR) doit être aussi courte que possible: - pendant son exécution la source d’IT est masquée (mais imbrication d’IT de niveaux de priorités différents possible) - ce n’est pas un mode d’exécution « normal » Le temps de latence d’IT est le délai entre arrivée de l’interruption et le début de l’exécution du code applicatif associé c’est une caractéristique importante qui différencie un system TR d’un système généraliste. 13 Gestion des interruptions: exemple /* rtlinux capter le signal d’horloge temps réel */ /*------------------------------------------------------*/ #define RTC_IRQ 8 void intr_handler(int sig){ faire_truc(); rtl_hard_enable_irq(RTC_IRQ); } int init_module(void){ struct sigaction act; act.sa_handler = intr_handler; sigaction( RTC_IRQ, &act, NULL); programmer_horloge( fréquence ); rtl_hard_enable_irq(RTC_IRQ); return(0); } Gestion des fichiers Certains services permettent d’optimiser l’accès aux fichiers - plus rapides - plus déterministes pour des applications temps réel. Ce sont: - fichiers projetés en mémoire (évitent les I/O pendant l’usage) - les fichiers stream ou temps réel (permettent écrire de façon continues sur des pistes physiquement contiguës d’un disque) - les écritures/lectures asynchrones 14 POSIX Depuis 1984 à l’IEEE P1003.1 interface de programmation pour UNIX de base gestion des processus (fork, exec, kill …) fichiers et terminaux (open, fopen , fgetc, dup ,fcntl ,mkdir …) information runtime (getpid, cuerid, uname …) signaux de base (signal, raise, sigaction … ) gestion mémoire (malloc, memcpy, free …) gestion du temps ( time, clock …) exécution (setjmp, longjmp …) communication (pipe, mkfifo (named pipes), setbuf stream, …) POSIX temps réel P1003.1b (ex POSIX.4) extensions temps réel ordonnancement sémaphores queues de messages signaux temps réel (nouveaux, queue, paramètres horloge haute résolution entrées sorties synchrones/asynchrones mémoire partagée P1003.1c (ex POSIX.4a) extensions multithreadées thread mutex variables conditions P1003.1d (ex POSIX.4b) gestion des IT 15 OS temps réel du marché Tornado,VxW orks Blue C atLinux and LynxO s Q N X N eutrino H ard H atLinux Lineo,Em bedix Et beaucoup d’autres … dont certaines solutions pour compléter Windows NT ou Linux avec des fonctions « temps réel stricte ». OS temps réel du marché 16