Partage d’informations Les processus peuvent partager des informations de diverses manières : • L’échange d’informations via des fichiers. • Les informations écrites par un processus peuvent être lues par un autre. Le principe est valable même pour des processus qui ne s’exécutent pas simultanément. • Le partage d’emplacements mémoire. C’est essentiellement de cette manière que communiquent les threads qui sont des "sous processus" qui partagent un même espace d’adressage. • Les pipes, les redirections d’E/S ou un système de messagerie pour processus prévu par le système d’exploitation. Ressources d’un système informatique Dans un système d’information, il y a deux types de ressources : • Ressources partageables : Les ressources qui peuvent être utilisées par plusieurs processus sans provoquer d’interférences : le processeur, les fichiers en lecture seule et les zones de mémoire qui ne contiennent que des procédures ou des données protégées contre toute modification. • Ressources non partageables : Les ressources qui ne peuvent être utilisées que par un seul processus à la fois ; – soit parce qu’il est matériellement impossible de partager cette ressource, – soit parce qu’elle contient des données susceptibles d’être modifiées. – Le résultat est imprévisible si pendant qu’un processus lit une donnée, un autre la modifie. Synchronisation de processus • Un système d'exploitation dispose de ressources (imprimantes, disques, mémoire, fichiers, base de données, ...), que les processus peuvent vouloir partager. • Ils sont alors en situation de concurrence (race) vis-à-vis des ressources. Exemple de conflit d’accès • Prenons l’exemple de l’enregistrement de travaux d’impression dans un spooler d’Andrew Tanenbaum. • L’imprimante est une ressource qui ne peut pas être utilisée simultanément par plusieurs processus. Les travaux d’impression doivent donc être enregistrés dans un répertoire de spool en attendant d’être imprimés. Exemple de conflit d’accès • Les processus qui veulent imprimer ont accès à deux variables partagées In et Out associées au spooler : – In le numéro à attribuer au prochain fichier qui entre dans le spooler – Out le numéro du prochain fichier à imprimer. • Un processus qui décide de placer un fichier dans le répertoire de spool, doit lire la variable In, se servir de cette valeur pour inscrire à l’endroit voulu le fichier à imprimer, puis modifier la variable In pour lui faire indiquer l’emplacement libre suivant. Exemple de conflit d’accès Exemple de conflit d’accès • Imaginons que deux processus (A et B) entreprennent presque simultanément d’envoyer un document à l’impression. • Si le processus A est interrompu pendant l’exécution de la section critique pour qu’entretemps l’ordonnanceur passe la main au processus B, la variable In sera relue par B et réutilisée une deuxième fois consécutivement avant d’avoir été incrémentée par le processus A. • Les deux processus vont donc inscrire le fichier à imprimer au même emplacement du spool et, bien que l’état du répertoire de spooler semble cohérent, un des deux fichiers ne sera jamais imprimé. Exemple de conflit d’accès
Pour éviter ces conflits d’accès, il faut empêcher la lecture ou
l’écriture de données partagées à plus d’un processus à la fois. La solution est l’exclusion mutuelle pour les accès concurrents. • Il faut synchroniser les actions sur les ressources partagées. • Le code exécuté par un processus a des parties qui ont besoin d’accéder aux ressources partagées : ce sont les sections critiques • Dans l’exemple ci-dessus, les instructions qui se situent entre le moment où on lit la variable partagée In et le moment où cette variable est modifiée forment une section critique. • La synchronisation des processus concerne les processus parallèles qui utilisent des ressources ou données non partageables. Section critique • C’est la partie de programme dans laquelle se font des accès à une ressource partagée • Dans la plupart des cas, l'accès à cette section critique devra se faire en exclusion mutuelle, ce qui implique de rendre indivisible ou atomique la séquence d'instructions composant la section critique. • Exemple : accès à une base de données. – Plusieurs processus peuvent la lire simultanément, mais quand un processus la met à jour, tous les autres accès doivent être interdits. Conditions d'accès à une section critique • exclusion mutuelle pour l’accès à la section critique : deux processus ne peuvent être ensemble en section critique, • pas d'interblocage : un processus bloqué en dehors de sa section critique ne doit pas empêcher un autre d'entrer dans la sienne, • pas d'attente infinie pour entrer dans la section critique : Si deux processus attendent l'entrée dans leurs sections critiques respectives, le choix doit se faire en un temps fini Conditions d'accès à une section critique • accès équitable : tous les processus doivent avoir la même chance d'entrer en section critique, pas d'hypothèses sur les vitesses relatives des processus (indépendance vis à vis du matériel). Outils de synchronisation • Matériels : – emploi d'une instruction de type Test and Set qui teste l'état d'une case mémoire commune aux deux processus et change sa valeur, – inhibition des interruptions (possible seulement dans le cas d'un processus se déroulant en mode privilégié). • Logiciels : – Wait & Signal – sémaphores (outils logiciels mis à la disposition des utilisateurs par le système d'exploitation), – algorithmes de synchronisation. Propriétés des outils de synchronisation • sûreté (safety) : deux processus ne doivent pas se trouver ensemble en section critique. Il faudra assurer l’exclusion mutuelle. • vivacité (liveness), impose des contraintes de : – progression : il faudra éviter l’inter-blocage, – équité : pas de famine, – attente bornée. – Toute demande sera satisfaite, ou encore : tout processus qui veut entrer en section critique devra pouvoir le faire • Les algorithmes de synchronisation sont des compromis entre sûreté et vivacité. TestAndSet (TAS) • TAS : une instruction du langage machine • TAS est insécable. Lorsque le processeur commence l'exécution d'une instruction du langage machine, il va jusqu'au bout même si une interruption arrive. • TAS permet de synchroniser des activités en environnement multiprocesseur. TestAndSet (TAS) • Cette instruction exécute une succession ininterruptible de deux opérations : tester & verrouiller. Ou Test & set • L’instruction TAS fait référence à une variable partagée. Appelons la Lock. • Lorsque cette variable est à 0, n’importe quel processus peut, via l’instruction TAS, la mettre à 1 « Set Lock » puis entrer dans la section critique. TestAndSet (TAS) Les inconvénients du TestAndSet • l'attente active (busy waiting) : un processus qui trouve la variable de synchronisation à 1 continuera à la tester jusqu'à ce qu'elle passe à 0. Il reste donc actif, alors qu'il pourrait être suspendu et rangé dans une file d'attente. • le fait qu'on ne sait pas qui va prendre la main. Ce problème est lié au précédent. En effet, puisqu'il n'y a pas de gestion de la file des processus en attente sur le passage de la variable à 0, le premier qui obtient une réponse satisfaisante au test entre dans sa section critique. Ce n'est pas forcément celui qui attendait depuis le plus longtemps. Inhibition des interruptions • Nous savons que dans un système monoprocesseur c’est un ordonnanceur qui tour à tour passe la main à chaque processus pour donner une impression de parallélisme. • Il est possible d’éviter l’intervention de l’ordonnanceur dans une section critique en s’interdisant d’exécuter des instructions susceptibles de provoquer le déroutement et en désactivant momentanément les interruptions. Inhibition des interruptions • Un processus peut empêcher le SE de s’exécuter – en n’éméttant pas d’instruction d’appel au superviseur, – en exécutant aucune instruction susceptible de provoquer un déroutement ou – en désactivant les interruptions. • L’exclusion mutuelle peut être réalisée à travers la mise en œuvre de primitives du SE afin qu’elles désactivent et activent les interruptions. L’accès à la section critique peut être contrôlée en appelant ces primitives Inhibition des interruptions DisactiverInterruption() //section critique ActiverInterruption() • Le processus qui entre dans la section critique monopolise ainsi le processeur en excluant tout autre processus. • Ce mécanisme est facile à mettre en œuvre • Mais il ne fonctionne que sur un SE mono-cpu • Perte de certaines interruptions • Risque de famine Wait & Signal • Les SE fournissent des primitives Wait & Signal leur permettant de mettre en œuvre la solution de TestAndSet avec des attentes non actives • Un objet ProcessQueue avec les opérations Insert et remove – Insert place un objet au bout de la file et change l’état du processus en bloqué – Remove sélectionne le processus qui se trouve dans la file depuis longtemps et change son état de bloqué en prêt. Wait & Signal Struct waitSignalVar { boolean lock Processqueue queue } Void wait(WaitSignalVar var) {if(TestAndSet(var.lock) var.queue.Insert(); }
Void signal(WaitSignalVar var)
{ var.queue.Remove(); var.lock=false; } Sémaphore • Le sémaphore est en quelque sorte un distributeur de jetons d’accès à la ressource. • Le nombre de jetons pouvant être distribués dépend du nombre de processus qui peuvent accéder en même temps à la ressource. • Le nombre de jetons est fixe. Il est initialisé lors de la création du sémaphore. • Chaque processus, pour avoir le droit d’accéder à la ressource, doit emprunter un jeton qu’il rend après utilisation. • Le sémaphore est donc une variable entière dont la valeur positive est fixée lors de sa création et qui n’admet par la suite que deux opérations P(s) et V(s) du néerlandais (Proberen = essayer et Verhogen = incrémenter). • Synonymes de P / V: Down() / Up() Wait() / Signal() Sémaphore • Un sémaphore S associé à une ressource R est un objet composé : – d'un compteur S.compt qui indique le nombre d'éléments disponibles ou le nombre de processus possible sur R, – d'une file d'attente S.FA où sont chaînés les processus en attente sur la ressource R. • Un sémaphore binaire ou mutex est un sémaphore dont le compteur ne peut prendre que deux valeurs positives possibles : en générale 1 et 0. Opérations sur un sémaphore • Ce sont des opérations atomiques • Init(S, val) qui initialise le nombre d’éléments de ressource val : S.compt = val et S.FA = vide. • P (Passeren) pour demander un élément de la ressource. – L’opération P(s) décrémente la valeur du niveau de sémaphore si elle est supérieure à 0 (s’il y a des jetons disponibles). Quand la décrémentation est impossible le processus est bloqué et attend dans la file d’attente V (Vrijgeven). – V(S) libère un élément de la ressource. On incrémente S.compt. Si S.compt ≤ 0 alors on sort un processus de S.FA, il passe dans la file des prêts et on peut lui allouer un élément de ressource. Verrou • Le verrou (lock) est un mécanisme destiné à mettre en œuvre l’exclusion mutuelle. • C’est un objet système auquel sont associées deux opérations systèmes, verrouiller et déverrouiller. – Verrouiller est l’opération qui permet à un processus d’acquérir la ressource si elle est disponible. Dans le cas contraire, le processus passe dans l’état bloqué en attendant la ressource. – Déverrouiller est l’opération système par laquelle le processus libère la ressource qu’il monopolisait. • Ces opérations aussi appelées primitives système sont des opérations indivisibles. Le système d’exploitation garantit qu’elles ne pourraient être interrompues par d’autres processus. Algorithmes de synchronisation • Algorithme de Dekker • Algorithme de Peterson • Algorithme du boulanger • Limitations : – On suppose que les opérations de lecture, d’écriture et de test d’un mot en mémoire sont atomiques. Algorithme de Dekker • Proposé par Theodorus Dekker. • Un algorithme d'exclusion mutuelle permettant la synchronisation de deux processus partageant une zone de mémoire. • basé sur une approche par attente active et est divisé en deux parties, à savoir le protocole d'entrée dans la section critique et le protocole de sortie • Chaque processus est identifié par un numéro unique. Ces identificateurs doivent être contigus. • Le nombre maximum de thread doit être connu à l'avance. • Cet algorithme nous affranchit de tout risque de famine, mais cela est coûteux, Algorithme de Peterson • Publié par Gary Peterson en 1981. • Un algorithme d'exclusion mutuelle pour la programmation concurrente. • Cet algorithme est basé sur une approche par attente active. • Il est constitué de deux parties : le protocole d'entrée dans la section critique et le protocole de sortie. Quelques problèmes classiques de synchronisation • Producteur et consommateur • Banquier • Écrivain et lecteur Producteur et consommateur • Un producteur et un consommateur se partage la ressource « tampon » • Un producteur dépose des messages dans un tampon ; • un consommateur retire ces messages du tampon. • Le producteur et le consommateur doivent synchroniser leurs actions. • Les deux doivent être en situation de coopération. Producteur et consommateur • 2 sémaphores sont utilisés : – S1 indique les ressources disponibles pour le producteur (nombre de cases vides), – S2 indique les ressources disponibles pour le consommateur (nombre de cases pleines). Producteur et consommateur • Producteur • Consommateur P(S1) P(S2) … … lire (case(i)) écrire (case(i)) i:=suiv_cons(i) i:=suiv_prod(i) … …. V(S1) V(S2) Fin
Metasploit pour débutant : le guide du débutant pour bypasser les antivirus, contourner les pare-feu et exploiter des machines avec le puissant framework Metasploit.