Cours SINF Système informatique 1

Dimension: px
Commencer à balayer dès la page:

Download "Cours SINF1252 - Système informatique 1"

Transcription

1 Cours SINF Système informatique 1 Attention, aucune garantie sur ce document. La plupart du contenu provient des syllabus du cours (certains blocs copiés tels quels). Ce "travail" de "synthèse" du cours vous est offert sous la licence BEERWARE 1 : * * «LICENCE BEERWARE» (Révision 42): * Damien M. a créé ce fichier. Tant que vous conservez cet avertissement, vous * pouvez faire ce que vous voulez de ce truc. Néanmoins si on se rencontre un jour * et que vous pensez que ce truc vaut le coup, vous devrez m offrir une (bonne) * bière en retour. * Table des matières 1 Types de données Nombres entiers Nombres entiers signés Nombres réels Les tableaux Caractères et chaînes de caractères Caractères Chaîne de caractères Les pointeurs Les structures Compléments en langage C Les fonctions Déclaration vs Définition Passage des paramètres Manipulation de bits Décalage de bits typecast en C Les pointeurs Écriture de grands programme static extern Traitement des erreurs Gestion et organisation de la mémoire Déclarations et portées Constantes Organisation de la mémoire Le segment text Le segment des données initialisées Le segment des données non-initialisées Le tas (ou heap) Les arguments et variables d environnement La pile (ou stack) Organisation des ordinateurs La mémoire Étude de cas : Architecture IA Les instructions mov Les instructions arithmétiques et logiques Les instructions de comparaison Les instructions sauts Manipulation de la pile Les fonctions et procédures Idée (très) originale de Poul-Henning Kamp : phk/ 1

2 6 Les threads Les threads POSIX Variables volatile Variable spécifique à un thread Fonctions thread-safe Threads communicants Loi de Amdahl Communication entre threads Coordination entre threads Exclusion mutuelle - Dijkstra Le problème des philosophes et deadlock Les sémaphores Processus Les librairies Les appels système Création d un processus Fin d un processus Exécution d un programme Table des processus Communications entre processus Signaux Envoi de signaux Traitement de signaux Traitement de signaux asynchrones Temporisateurs Sémaphores Partage de fichiers Fichiers et répertoires Gestion des utilisateurs Systèmes de fichiers Permissions Répertoire courant Appels systèmes Utilisation des fichiers Les pipes Mémoire virtuelle La mémoire virtuelle La mémoire virtuelle Fonctionnement de la mémoire virtuelle Mémoire partagée Implémentation de fork Fichiers mappés en mémoire Utilisation des dispositifs de stockage Stratégie de remplacement de pages Interactions entre le processus et la mémoire execve et la mémoire virtuelle

3 1 Types de données 1.1 Nombres entiers Les nombres sont limités par le nombre de bits qui sont utilisés pour les représentés en mémoire. Il y deux types de nombres entiers : Les nombres entiers signés (int) et les nombres entiers non-signés (unsigned int). Par convention le bit le plus à gauche est appelé le bit de poids fort tandis que celui le plus à droite, est le bit de poids faible. Plusieurs représentations de séquence de bits existent : Représentation Base Plage Exemple Binaire Représente 1 bit 2 [0-1] 0b Octal Représente 3 bits 8 [0-7] 0x07b Hexadécimal Représente 4 bits (nibble) 16 [0-9A-F] 0173 Décimal 10 [0-9] 123 Attention : Lorsqu on écrit un nombre commençant par un 0, le compilateur C le prendra comme étant en notation octale! Donc 0123==123 renverra false, en effet, 0123 représente le nombre décimal 83. Afin de connaître la taille en mémoire d un type de donnée en C, il faut utiliser sizeof. sizeof renvoit le nombre d octet (=8 bits) Nombres entiers signés Plusieurs manière existe pour représenter un nombre entier signé. La première, consiste à utiliser le bit le plus à gauche afin de représenter le signe : n 2 ( 1) bn 1 b i 2 i En pratique, cette notation n est que très peut utiliser car elle rend l implémentation des circuits électroniques de calcul plus compliquée et qu elle permet de représentée la valeur zéro de deux manière différentes : et La représentation la plus courante est de sortir de la somme le bit de poids fort et de le multiplier par -1 : i=0 n 2 (b n 1 ) 2 n 1 + b i 2 i De cette manière, il n y a qu une représentation pour le 0 (lorsque tout les bits valent 0) ; par contre il existe toujours un nombre entier négatif qui n a pas d équivalent positif. Un nombre short par exemple est représenté sur 16 bits, il peut donc représenter les nombres compris entre 2 15 et , c est à dire les nombres entiers [ 32768, 32767]. Attention : Le langage C ne prévoit aucun mécanisme d exception qui permettrait au programmeur de détecter qu on dépasse l intervalle autorisé pour un type de variable. Il faut donc choisir le type de variable (short, int, long, long long,...) judicieusement en fonction de l application et être sûr qu on ne dépasse pas l intervalle. 1.2 Nombres réels Pour un nombre réels sur 32 bits (resp 64 bits) on a : seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm avec s le signe sur 1 bit, e l exposant sur 8 bits (resp 11) et m la fraction (ou mantise) sur 23 bits (resp 52) i=0 ( 1) s ( i=1m i 2 i ) 2 e Emax ) Il est intéressant de noter que une représentation en virgule flottante sur n bits ne permet jamais de représenter plus de 2 n nombres réels différents. les représentations en virgule flottante privilégient les nombres réels compris dans l intervalle [ 1, 1]. On retrouve autant de nombres réels représentables dans cet intervalle qu en dehors. 1.3 Les tableaux En C, les tableaux permettent d agréger des données d un même type. Exemple : 1 #d e f i n e N 10 2 i n t v e c t e u r [N ] ; 3 i n t matricec [N ] [ N ] ; 4 i n t matricer [N] [ 2 N ] ; Attention : il n est pas possible de récupérer la taille d un tableau à partir de la variable (ex Java : coord1.length). Il faut donc toujours passer cette information en plus du tableau (ex : main(int argc,...)). 3

4 1.4 Caractères et chaînes de caractères Caractères Les caractères peuvent être encodé de plusieurs selon plusieurs représentations : ASCII : 7 bits - mais représenté sur 8 bits. Par exemple "A" est 0b ISO-8859 : 8 bits Unicode : Permet de représenter tous les caractères connus de toutes les langues. Utilise plus que 8 bits par caractères. La fonction toupper prend un int comme argument et traite l information en fonction du type d encodage qui a été défini 2. Dans la suite du cours, nous supposerons qu un caractère est toujours représentable en utilisant le type char permettant de stocker un octet Chaîne de caractères En C, les chaînes de caractères sont représentées sous forme de tableau de caractères (char). Le dernier caractère d une chaîne de caractère en C est par convention le caractère \0. Il faut faire attention à ne jamais le "dépasser" car le C n a pas de mécanisme d exception et donc aller trop loin dans le tableau ne produira pas d exception du type ArrayOutOfBoundException mais un résultat imprévisible. 1.5 Les pointeurs Un pointeur est définit comme étant une variable content l adresse d une autre variable. 1 i n t i =1; // e n t i e r 2 i n t ptr_i ; // p o i n t e u r v e r s un e n t i e r 3 4 ptr_i=&i ; // i n i t i a l i s a t i o n du pointeur, a l a d r e s s e de i 5 ptr_i = ( ptr_i ) +1252; //Changement du contenu de l a memoire p o i n t e par ptr_i 1.6 Les structures C Les structures permettent de définir des données plus complexes. La langage C permet la définition de structures qui combinent différents types de données simples ou structurés. Les structures permettent de facilement regrouper des données qui sont logiquement reliées entre elles et doivent être manipulées en même temps. 1 // D e f i n i t i o n d une s t r u c t u r e 2 s t r u c t student { 3 i n t m a t r i c u l e ; 4 char prenom [ 2 0 ] ; 5 char nom [ 3 0 ] ; 6 } ; 7 // D e c l a r a t i o n + I n i t i a l i z a t i o n 8 s t r u c t student l i n u s = { 1, " Linus ", " Torvalds " } ; 9 s t r u c t student r i c h a r d = {. m a t r i c u l e = 2,. prenom = " Richard ",. nom = " Stallman " } ; 10 s t r u c t student e v i l ; 11 e v i l. noma = 3 ; 12 e v i l. prenom = " B i l l " ; 13 e v i l. nom = " Gates " ; typedef permet de redéfinir le nom des types de données. 1 // D e f i n i t i o n de nouveaux noms pour des types e x i s t a n t s 2 t y p e d e f i n t E n t i e r ; 3 t y p e d e f s t r u c t student Etudiant ; 4 // D e c l a r a t i o n de v a r i a b l e u t i l i s a n t c e s nouveaux noms 5 E n t i e r m a t r i c u l e = 4 ; 6 Etudiant mark = { m a t r i c u l e, " Mark ", " Shuttleworth " } ; Les données d une structure peuvent être accédée via l opérateur "." (point). Mais étant donnée que les pointeurs sont souvent utilisés lors de la manipulation de structures, une notation plus pratique que (*ptr).elem existe : ptr->elem. 1 //Avec l o p e r a t e u r. 2 p r i n t f ( " [%d ] %s %s \n ", mark. matricule, mark. nom, mark. prenom ) ; 3 //Avec l o p e r a t e u r > 4 Etudiant e = &e v i l ; 5 p r i n t f ( " [%d ] %s %s \n " e >matricule, e >nom, e >prenom ) ; 6 // qui e s t i d e n t i q u e a : 7 p r i n t f ( " [%d ] %s %s \n ", ( e ). matricule, ( e ). nom, ( e ). prenom ) ; 2. Avec setlocale, voir locale 4

5 2 Compléments en langage C 2.1 Les fonctions Déclaration vs Définition La déclaration d une fonction (= sa signature) indique au compilateur le type (en cas de variables) ou les arguments et le type de la valeur de retour (en cas de fonctions). Toutes fonctions ou variables doivent être déclarée avant d être utilisées. En règle général, on regroupe toutes les déclarations de fonctions à l intérieur d un fichier header dont le nom se termine par.h La définition d une fonction consiste en l implémentation de la fonction déclarée, ou dans le cas d une variable de son initialisation Passage des paramètres Le langage C utilise le passage par valeur des arguments. Lorsqu une fonction est exécutée, elle reçoit les valeurs de ces arguments. Ces valeurs sont stockées dans une zone mémoire qui est locale à la fonction. Toute modification faite sur la valeur d une variable à l intérieur d une fonction est donc locale à cette fonction. Attention néanmoins : Lorsqu on passe un pointeur en argument on copie la valeur du pointeur (l adresse d une zone mémoire). Le contenu de zone mémoire pointée par le pointeur n est pas copié, il est donc possible à la fonction de le modifier 3! Par contre si la fonction essaye de changer le pointeur lui même (pour qu il pointe vers une autre zone mémoire) ce changement n aura lieu que dans la fonction puisqu il s agit bien d une copie du pointeur! 2.2 Manipulation de bits Le langage C permet au programmeur de manipuler facilement les bits qui se trouves en mémoire. Pour cela, le langage C définit des expressions qui correspondent à la plupart des opérations de manipulation de bits que l on retrouve dans les langages d assemblage. Les premières opérations sont les opérations logiques, elles sont résumé par le tableau 1. A B négation conjonction logique disjonction logique ou exclusif NOT(A) A AND B A OR B A XOR B A A B A B A B Exemple en C : char a = 0b ; char b = 0b ; Opération 4 a a&b a b aˆb Résultat 0b b b b Table 1 Récapitulatif des opérations Il est également important de mentionner les lois formulées par De Morgan qui peuvent se résumer par les équations suivantes : (A B) = A B et (A B) = A B Une des propriété intéressante de l opération XOR est que (A B) B = A. Cette propriété est largement utilisée par les méthodes de chiffrement Décalage de bits Bit-shift à gauche n bits sont déplacés vers la gauche en ajoutant des 0 à droite. En C : a=n»b. Bit-shift à droite n bits sont déplacés vers la droite en ajoutant des 0 à gauche. En C : a=n«b. Ces opérations de décalage permettent différentes manipulations de bits Cette remarque s applique également aux tableaux, puisqu un tableau un en réalité un pointeur 4. Il faut faire attention à ne pas confondre les opérateurs binaires logique & et avec les expressions logique && et! 5. Pour un exemple, voir int2bin à la page 33 du syllabus [PDF] 5

6 2.3 typecast en C Le langage C supporte des conversions implicites et explicites entre les différents types de données. Ces conversions sont possibles entre les types primitifs et les pointeurs. C est régulièrement utilisé par exemple pour transformer un pointeur void * retourné par malloc en un pointeur du bon type. Attention : Contrairement au compilateur Java, le compilateur C n émet pas toujours de message de warning lors de l utilisation de typecast qui risque d engendrer une perte de précision. 1 // Exemple de t y p e c a s t 2 untype a =... ; 3 unautretype b = (unautretype) a ; 4 5 // Exemple c o n c r e t 6 Etudiant e ; 7 e = ( Etudiant ) malloc ( s i z e o f ( Etudiant ) ) ; 2.4 Les pointeurs En C, il est possible de définir des pointeurs vers n importe quel type d information qui est manipulé par un programme C. Il est ainsi possible d avoir des pointeurs vers des fonctions. Cela peut être utile par exemple pour avoir une application qui propose différentes fonctions pour afficher (ou non) les informations de débogage. Ou encore pour utiliser la fonction qsort qui permet de trier un tableau de n importe quel type d information. Sa signature est la suivante : void qsort(void *base, size_t nel, size_t width, int (*compar) (const void *, const void *)) Le quatrième argument est un pointeur vers la fonction qui permet de comparer deux élémets du tableau. Cette fonction retourne un entier négatif si son premier argument est inférieur au second et positif ou nul sinon. Il est également possible d avoir des pointeurs vers des pointeurs. En pratique, on retrouves des pointeurs vers des pointeurs lorsqu on doit manipuler des structures multidimensionnelles, mais aussi lorsqu il faut qu une fonction puisse modifier une adresse qu elle a reçue en argument Écriture de grands programme Lors de l écriture de grands programme, il est préférable de les découper en modules. Chaque module contient des fonctions qui traitent d un même type de problème et sont fortement couplées. Un module d un programme C est en général décomposé en deux parties : Le fichier header : Contient les définitions de certaines constantes et les signatures des fonctions exportées par ce module. Ce fichier est en quelque sorte un résumé du module, c est son interface externe. Il doit être inclus dans tout fichier qui utilise les fonctions du module 7. Ce fichier contient donc : Signatures des fonctions. (Uniquement les fonctions qui sont destinées à être utilisées par des modules extérieures) Constantes qui sont utilisées à l intérieur du module et doivent être visibles en dehors de celui-ci. Ces constantes peuvent être définie en utilisant des directives #define du préprocesseur. Variables globales qui doivent être accessible en dehors du module. Le fichier contenant le code du module. Pour inclure des fichiers headers : Soit il s agit d un module fournis par le système : #include <lemodule.h> Soit il s agit d un module du programme (dans le même répertoire ou dans un répertoire définit en utilisant la variable d environnement GCC_INCLUDE_DIR ou CPATH) : #include "lemodule.h" La procédure/ordre de compilation est expliqué dans le cours (page 90-91). 2.6 static Le qualificateur static peut être utilisé dans différents cas : Pour des variables définies en dehors d un bloc dans un module : Dans ce cas, cette variable n est accessible que par les fonctions du module. 6. Comme par exemple la fonction strtol de la librairie standard qui prend comme 2e argument un pointeur vers une pointeur (endptr) qui permet d indiquer un pointeur vers le premier caractère en erreur en cas d erreur de conversion (sinon il indiquera le caractère de fin de chaîne 0). 7. En pratique un fichier header ne peut être inclus qu une seule fois. Mais comme il se peut qu un fichier header fasse appel à un autre, on utilise la règle de bonne pratique suivante : On ajoute une condition au préprocesseur avec #ifndef _MON_MODULE_ suivit de #define _MON_MODULE_ en début de fichier header. On termine la condition avec #endif en fin de fichier. 6

7 Pour des variables définies à l intérieur d un bloc (par exemple dans une fonction) : Dans ce cas, cela indique que cette variable doit toujours se trouver à la même localisation en mémoire, quelque soit le moment où elle est appelée. Ces variables sont placées par le compilateur dans le bas de la mémoire, avec les variables globales 8. Un de leurs intérête est qu elles ne sont initialisées qu au lancement du programme et non pas à chaque invocation de la fonction dans laquelle elles sont définies. Pour des fonctions : Lorsqu une déclaration de fonction est précédée par le qualificateur static, cela indique que la fonction ne doit pas être visible en dehors du module dans lequel elle est définie. 2.7 extern Lorsqu une déclaration de variable globale est préfixée par extern, cela indique au compilateur que la variable est définie dans un autre module qui sera linké ultérieurement. Le compilateur réserve une place pour cette variable dans la table des symboles du fichier objet, mais cette place ne pourra être liée à la zone mémoire qui correspond à cette variable que lorsque l éditeur de liens combinera les différents fichiers objets entre eux. 2.8 Traitement des erreurs Pour certaines fonctions ou appels systèmes, il est parfois nécessaire de fournir à l utilisateur plus d information sur l erreur qui s est produite. La valeur de retour utilisée pour la plupart des fonctions de la librairie et appels système (souvent un int ou un pointeur), ne permet pas de fournir de l information précise sur l erreur qui s est produite. Les systèmes Unix utilisent la variable globale errno pour résoudre ce problème et permettre à une fonction de la librairie ou un appel système qui a échoué de donner plus de détails sur les raisons de l échec. Cette variable globale est définie dans errno.h qui doit être inclus par tout programme voulant tester ces codes d erreur. La librairie standard fournit également les fonctions perror et strerror qui facilitent l écriture de messages d erreur compréhensible pour l utilisateur. Attention : La valeur de errno n est modifié qu en cas d échec, elle ne permet donc pas de savoir si une fonction a réussi ou non! 3 Gestion et organisation de la mémoire 3.1 Déclarations et portées La portée d une variable peut être définie comme étant la partie du programme où la variable est accessible et où sa valeur peut être modifiée. En C, une variable a une portée globale lorsqu elle est définie en dehors de toute définition de fonction. Une telle variable est accessible dans toutes les fonctions présentes dans le fichier. Dans un fichier donné, il ne peut donc évidemment pas y avoir deux variables globales qui ont le même identifiant. Une variable définie dans un bloc a par contre une portée locale à ce bloc. La variable n existe pas avnt le début du bloc et n existe plus à la fin du bloc. Lorsqu un identifiant de variable locale est utilisé à plusieurs endroits dans un fichier, c est la définition la plus proche qui est utilisée. En pratique, les variables globales doivent être utilisées de façon parcimonieuse et il faut limiter leur utilisation aux données qui doivent être partagées par plusieurs fonctions à l intérieur d un programme. Lorsqu une variable globale a été définie, il est préférable de ne pas réutiliser son identifiant pour une variable locale. Les premières versions du langage C imposaient la définition de toutes les variables locales au début des blocs. Les standards récents [C99] autorisent la déclaration de variables juste avant leur première utilisation ( comme en Java) Constantes Les versions récentes de C [C99] permettent également de définir des variables dont la valeur sera constante durant toute l exécution du programme. Pour ce faire il faut utiliser le mot clé const devant la déclaration de la variable ( final en Java). Une autre façon de définir des constante est d utiliser la macro #define du préprocesseur qui permet de remplacer une chaîne de caractères par un nombre ou une autre chaîne de caractères. Mais les inconvénients par rapport à const sont : Avec const il est possible de définir n importe quel type de données en C, y compris des structures ou des pointeurs. (Tandis qu avec #define, on ne peut définir que des nombres ou des chaînes de caractères. Les variables déclarée avec const sont stockées en mémoire, il est donc possible d obtenir l adresse en mémoire (pour l examiner via un debugger par exemple). 8. Doit être utilisé avec beaucoup de précaution et bien documentées! 7

8 3.2 Organisation de la mémoire Lorsqu un programme s exécute sur un système Unix, la mémoire peut être vue comme étant divisée en 6 zones principales (figure 1) Le segment text La première zone est appelée le segment text. Elle est située dans la partie basse de la mémoire 9. C est dans cette zone que sont stockées toutes les instructions qui sont exécutées par le micro-processeur. Elle est généralement considérée par l OS comme étant uniquement accessible en lecture 10. C est dans le segment text q un retrouvera les instructions de langage machine correspondant aux fonctions de calcul et d affichage du programme. langage d assemblage Le segment des données initialisées La deuxième zone appelée segment des données initialisées contient l ensemble des données et chaînes de caractères qui sont utilisées dans le programme. Ce segment contient 2 types de données : l ensemble des variables globales qui sont explicitement initialisées par le programme ou initialisée à 0 par le compilateur. les constantes et chaînes de caractères utilisées par le programme Le segment des données non-initialisées Figure 1 Organisation d un programme Linux en mémoire La troisième zone appelée segment des données non-initialisées est réservée aux variables non initialisées. Cette zone en mémoire est initialisée à zéro par l OS au démarrage du programme. C est dans cette zone qu on y stockera les valeurs de la variable g et des tableaux array et msg de l exemple ci-dessous : 1 #d e f i n e MSG_LEN 10 2 i n t g ; // i n i t i a l i s e par l e c o m p i l a t e u r 3 i n t g _ i n i t =1252; 4 c o n s t i n t un=1; 5 i n t tab [ 3 ] = { 1, 2, 3 } ; 6 i n t array [ ] ; 7 char c o u r s []= " SINF1252 " ; 8 char msg [MSG_LEN] ; // i n i t i a l i s e par l e c o m p i l a t e u r 9 10 i n t main ( i n t argc, char argv [ ] ) { 11 i n t i ; 12 p r i n t f ( " g e s t a l a d r e s s e %p e t i n i t i a l i s e e a %d\n ",&g, g ) ; 13 p r i n t f ( " msg e s t a l a d r e s s e %p c o n t i e n t l e s c a r a c t e r e s : ", msg ) ; 14 f o r ( i =0; i <MSG_LEN; i ++) 15 p r i n t f ( "%x ", msg [ i ] ) ; 16 p r i n t f ( " \n " ) ; 17 p r i n t f ( " Cours e s t a l a d r e s s e %p e t c o n t i e n t : %s \n ",& cours, c o u r s ) ; 18 r e t u r n (EXIT_SUCCESS) ; 19 } Initialisation des variables En C, il faut être attentif a bien initialiser l ensemble des variables utilisées dans un programme car le compilateur C est très permissif (contrairement au compilateur Java). Le compilateur C n initialise pas les variables locales à zéro (pour un gain de performance), on ne peut donc pas faire d hypothèse sur la valeur d une variable non initialisée Le tas (ou heap) La quatrième zone de la mémoire est le tas (ou heap). Il s agit d une des deux zone dans laquelle un programme peut obtenir de la mémoire supplémentaire pour stocker de l information. L OS mémorise pour chaque processus en cours d exécution, la limite supérieure de son heap. Et permet à un processus de modifier la taille de son heap via les appels systèmes brk et sbrk. Ces deux appels systèmes sont rarement utilisé directement car ils se contentent uniquement de modifier la limite supérieure du heap sans fournir d API permettant d y allouer efficacement des blocs de mémoire Voir variable etext 10. Donc si un programme essaye de modifier son segment text il sera immédiatement interrompu par le système d exploitation 11. On peut néanmoins utiliser directement brk sous forme d un appel à sbrk(0) de façon à connaître la limite supérieure actuelle du heap 8

9 malloc et free En C, la plupart des processus allouent et libèrent de la mémoire en utilisant les fonctions malloc et free qui font partie de la librairie standard. La fonction malloc prend comme argument la taille (en bytes) de la zone mémoire à allouer. Cette taille doit être de type size_t, il est important de toujours utiliser sizeof lors du calcul de la taille d une zone mémoire à allouer. malloc retourne un pointeur du type (void *) qui peut être casté en un pointeur du bon type. La fonction free permet quant à elle de libérer la mémoire qui a été allouée par malloc. Elle prend comme argument le pointeur dont la valeur a été initialisée par malloc. La valeur du pointeur n est pas modifiée, mais après libération de la mémoire il n est évidemment plus permit d accéder aux données qui étaient stockées dans cette zone 12. malloc et free sont fréquemment utilisés dans des programmes qui manipulent des structures de données dont la taille varie dans le temps. C est le cas par exemple pour les différentes sortes de listes chaînées, les piles, les queues, les arbres,... Attention : Il ne faut pas compter sur les free implicite. Lorsqu un programme se termine, via return dans la fonction main ou par un appel explicite à exit, l OS libère tous les segments utilisés par le programme, le text, les données, le tas et la pile. Néanmoins, ne pas libérer la mémoire lorsqu elle n est plus utilisée est un problème courant qui est généralement baptisé memory leak. Ce problème est particulièrement gênant pour les processus tels que les serveurs Internet qui ne se terminent pas ou des processus s exécutant longtemps. Une petite erreur de programmation causant un memory leak peut après quelque temps consommer une grande partie de l espace mémoire inutilement. Ce n est pas acceptable! Il existe également d autres fonctions que malloc et free dans la librairie standard. Citons calloc qui permet d initialiser la mémoire à Les arguments et variables d environnement La zone situé dans le haut de la mémoire est une zone qui contient deux type de variables : Les arguments qui ont été passés via la ligne de commande. L OS met dans argc le nombre d arguments et place dans char *argv[] tous les arguments passés avec dans argv[0] le nom du programme qui est exécuté. Ensuite les variables d environnement. Les variables d environnements Ces variables sont généralement relatives à la configuration du système. Leurs valeurs sont définies par l administrateur système ou l utilisateur. De nombreuses variables d environnement sont utilisées dans les système Umix. Elles servent à modifier le comportement de certains programmes. Voici quelques variables utiles 14 Nom Description Définit par Exemple HOSTNAME SHELL USER HOME PRINTER PATH Nom de la machine sur laquelle le programme s exécute. Interpréteur de commande utilisé par défaut pour l utilisateur courant. Cet interpréteur est lancé par le système au démarrage d une session de l utilisateur. Il est stocké dans le fichier des mots de passe. Nom de l utilisateur courant. Sous Unix, chaque utilisateur est identifié par un numéro d utilisateur et un nom uniques. Répertoire d accueil de l utilisateur courant. Ce répertoire d accueil appartient à l utilisateur. C est dans ce répertoire qu il peut stocker tous ses fichiers. Nom de l imprimante par défaut qui est utilisé par lp Contient la liste ordonnée des répertoires que le système parcourt pour trouver un programme à exécuter. Cette liste contient généralement les répertoires dans lesquels le système stocke les exécutables standards ainsi que des répertoires relatifs à des programmes spécialisés 15. Admin hostname damien-laptop User passwd /bin/bash Admin passwd User 16 damien /home/damien /usr/local/sbin: /usr/local/bin: /usr/sbin: /usr/bin: /sbin: /bin: /usr/games 12. Bien que le compilateur C ne génère pas de code permettant de vérifier automatiquement qu un accès via un pointeur pointe ou non vers une zone mémoire qui est libre (pour des raisons de performance). 13. Il est aussi possible d initialiser la mémoire avec memset ou bzero 14. Il est possible de lister les définitions actuelles des variables d environnement via la commande printenv. Les interpréteurs de commande tels que bash permettent de facilement modifier les valeurs de ces variables. La plupart d entre elles sont initialisées par le système ou via les fichiers qui sont chargés automatiquement au démarrage de l interpréteur comme le fichier /etc/profile et le fichier.profile du répertoire utilisateur. 15. Par exemple /usr/lib/mozart/bin 16. par exemple en ajoutant PATH=$PATH : $HOME/local/bin :. dans le fichier.profile. Dans cet exemple le répertoire 9

10 La librairie standard contient plusieurs fonctions qui permettent de manipuler les variables d environnement d un processus. getenv permet de récupérer la valeur associée à une variable d environnement. Retourne un pointeur NULL si la variable n a pas été assignée. unsetenv permet de supprimer une variable de l environnement du programme courant. setenv permet de modifier la valeur d une variable d environnement. Cette fonction alloue de la mémoire pour stocker de nouvelles variable d environnement et peut donc échouer (c est à dire retourner un code différent de 0) s il n y a pas assez de mémoire disponible La pile (ou stack) La pile ou stack est la dernière zone de mémoire utilisée par un processus. Cette zone est extrêmement importante car c est dans cette zone que le processus va stocker l ensemble des variables locales mais également les valeurs de retour de toutes les fonctions qui sont appelées. Cette zone est gérée comme une pile (d où son nom) avec un fonctionnement de type LIFO (Last Input, First Output). À chaque fois qu une fonction est appelée elle est placée sur la pile ainsi que ses arguments. Les variables locales le sont également. Durant son exécution, une fonction accède donc à ses variables locales sur la pile sans interférer avec les variables locales de l exécution des autres fonctions 17. La pile joue un rôle essentiel lors de l exécution de programmes en C puisque toutes les variables locales, y compris celles de la fonction main y sont stockées. La pile sert également à stocker l adresse de retour des fonctions. Ce qui permet a une fonction de poursuivre correctement son exécution après avoir exécuter une autre fonction afin d en récupérer la valeur de retour. Le fonctionnement de la pile confirme la portée locale : Lorsqu une variable est définie comme argument ou localement à une fonction f, elle n est donc accessible que durant l exécution de la fonction f. De plus, comme le langage C utilise le passage par valeur, les valeurs des arguments d une fonction sont copiée sur la pile avant de démarrer l exécution de cette fonction. Il est important d en être conscient, par exemple si l on doit passer des structures importantes a une fonction. Le choix de passer un pointeur vers la structure peut donc être plus judicieux (mais permet à la fonction de modifier le contenu de la structure dont le pointeur est passé en argument) afin de gagner en performance et en utilisation de mémoire. Certaines variantes de Unix et certains compilateurs permettent l allocation de mémoire sur la pile via la fonction alloca. Néanmoins cette façon d allouer de la mémoire sur la pile n est pas portable et il est préférable de n allouer de la mémoire que sur la tas en utilisant malloc. En vue du fonctionnement de la pile il faut être attentif à ne jamais retourner l adresse d une variable locale. Cet erreur est signalé lors de la compilation par gcc sous la forme d un warning : warning : function return address of local variable. 4 Organisation des ordinateurs Un des premiers principes fondateurs est le modèle d architecture de von Neumann 18 (Figure 3). La partie la plus intéressante de ce modèle organisé autour de 2 types de dispositifs : L unité centrale ou processeur qui peut être décomposée en 2 partie : L unité de commande : Permet de charger, décoder et exécuter les instructions du programme qui sont stockées en mémoire. L unité arithmétique et logique : Regroupe les circuits électroniques qui permettent d effectuer les opérations arithmétiques (addition, soustraction, division,...) et logiques. C est cette unité qui réalise les calculs proprement dits. La mémoire qui joue un double rôle : Stocke les données qui sont traitées par le programme ; Stocke les instructions qui composent ce programme. 4.1 La mémoire Figure 2 Modèle de von Neumann Première approche En première approximation, on peut considérer la mémoire comme étant un dispositif qui permet de stocker des données binaires. La mémoire est découpée en blocs de un octet. Chacun de ces blocs est identifié par une adresse, qui est elle aussi représentée sous la forme d un nombre binaire. Une mémoire que permet de stocker 2 k bytes de données utilisera au minimum k bits pour représenter l adresse d une zone mémoire 19. En pratique, les processeurs /local/bin sera ajouté ainsi que le répertoire courant symbolisé par le ".". 17. Il peut s agir de fonction différentes ou de la même fonction qui est en attente d un résultat, par exemple dans le cas de fonctions récursives. 18. Introduit avec le développement des premiers ordinateurs durant la seconde guerre mondiale mais reste tout à fait valide aujourd hui. 19. Par exemple, une mémoire pouvant stocker 64 millions de bytes doit utiliser au moins 26 bits d adresse 10

11 des ordinateurs de bureau utilisent 32 ou 64 bits 20. Ce nombre de bits utilisés pour représenter une adresse en mémoire limite la capacité totale de mémoire adressable par un processeur. Ainsi, un processeur qui utilise des adresses sur 32 bits n est pas capable physiquement d adresser plus de 4 GBytes de mémoire. Approche complexe En pratique, l organisation d un ordinateur actuel est plus complexe que le modèle de von Neumann. La figure?? présente de manière schématique l organisation actuelle d un ordinateur. Le processeur est directement connecté à la mémoire via un bus de communication rapide permettant des échanges de données et d instructions efficaces entre la mémoire et le processeur. En plus du proesseur et de la mémoire, un 3e dispositif, souvent appelé adaptateur de bus est connecté au bus processeur-mémoire. Cet adaptateur permet au processeur d accéder aux dispositifs de stockage ou aux dispositifs d entrées-sorties tels que le clavier, la souris ou les cartes réseau. En pratique, cela se réalise en connectant les différents dispositifs à un autre bus de communication (PCI, SCSI,...) et en utilisant un adaptateur de bus qui est capable de traduire les commandes venant du processeur. Figure 3 Architecture d un ordinateur actuel Mémoires SRAM, DRAM,... Les technologies les plus courantes pour la mémoire sont les SRAM et les DRAM. Type Description Avantages Inconvénients SRAM DRAM L information est stockée sous la forme d un courant électrique qui passe ou ne passe pas à un endroit donné. C est la présence ou l absence d une charge ( à quelques dizaine d électrons) dans un condensateur qui représente la valeur 0 ou 1. Temps d accès assez faible Possible d en construire de très grande taille : Jusqu à 1 GByte par chip. grande consommation électrique ce qui empêche de développer des mémoires de grandes capacités Performances nettement moins bonne que les SRAM. En pratique, une mémoire DRAM actuelle peut être vue comme étant équivalente à une grille. Les adresse peuvent donc être vues comme étant composée d un numéro de ligne et d un numéro de colonne. Ces deux opérations sont successives. Lorsque la mémoire a reçu la ligne et ensuite la colonne demandées, avant de pouvoir commencer le transfert de la donnée. Elles ont donc une latence élevée (par rapport au débit de transfert qui est élevée). Cela implique que dans une mémoire DRAM il est plus rapide de lire ou d écrire un bloc de 128 bits successifs que quatre blocs de 32 bits à des endroits différents en mémoire. Importance de la mémoire Le processeur interagit en permanence avec la mémoire, que ce soit pour charger des données à traiter ou pour charger les instructions 21. Les données échangées (données et instructions) sont représentées sous la forme de nombres binaires. Il est important de prendre conscience de que le processeur doit en permanence charger des données et des instructions depuis la mémoire pour pouvoir exécuter un programme. Ces échanges peuvent donc avoir un impact sur la vitesse d exécution comme nous le verrons plus tard Registre Outre des unitées de calcul, un processeur contient plusieurs registres. Un registre est une zone de mémoire très rapide se trouvant sur le processeur. Sur les processeurs courants, cette zone de mémoire permet de stocker un mot de 32 bits ou un long mot de 64 bits. 22. Chaque registre est identifié par un nom ou un numéro et les instructions du processeur permettent d accéder directement aux données se trouvant dans un registre particulier. Les registres sont les mémoires les plus rapides qui sont disponibles sur un ordinateur. Malheureusement, 20. D ancien processeurs utilisaient 16 ou 20 bits d adresse 21. Certains processeurs utilisent des instructions de taille fixe, par exemple chaque instruction est encodée sous la forme d un mot de 32 bits. D autres processeurs, comme ceux qui implémentent l architecture IA32, utilisent des instructions qui sont encodées sous la forme d un nombre variable de bytes. Mais cela n a au final assez peu d impact sur le développeur de programmes. 22. Les premiers processeurs disposaient d un registre unique appelé l accumulateur. Les processeurs actuels en ont généralement une dizaine ou quelques dizaines. 11

12 il sont en nombre très limité et il est impossible de faire fonctionner des programmes en utilisant uniquement des registres. Dilemme : Performance VS capacité / prix / faisabilité Il serait préférable de pouvoir construire un ordinateur équipé uniquement de SRAM, mais au niveau de la capacité et du prix c est impossible 23. Les ordinateurs actuels contiennent donc à la fois de la mémoire SRAM et de la mémoire DRAM. Avec les registres, les SRAM et les DRAM composent les 3 premiers niveaux de la hiérarchie de la mémoire. Il est utile de voir comment cette hiérarchie de mémoire est organisée en pratique en évaluant les différentes alternatives 24. 1e solution : Répartition d adresse entre SRAM et DRAM Une première solution pour combiner la SRAM et la DRAM serait de réserver par exemple les adresses basses à la SRAM et les adresses hautes à la DRAM. Avec cette solution, le programme stocké dans la SRAM pourrait s exécuter nettement plus rapidement que le programme stocké en DRAM. Il faudrait alors imaginer que l OS fournissent des appels système permettant aux applications de demander à déplacer certaines parties du programme et des données en SRAM. Ce genre de solution obligerait chaque application à pouvoir déterminer quelles sont les données et les instructions à exécuter en mémoire SRAM pour obtenir de meilleur performance. Théoriquement c est envisageable mais en pratique ça n a que très peu de chance de fonctionner. 2e solution : La mémoire cache Une deuxième solution est d utiliser le principe de la mémoire cache. Une mémoire cache est une mémoire de faible capacité mais rapide qui est capable de stocker des données provenant de mémoire de plus grande capacité mais plus lente. Cette mémoire cache sert d interface entre le processeur et la mémoire principale. Toutes demandes d accès à la mémoire principale passent par la mémoire cache comme illustré ci-dessous : Mémoire cache Ce système de mémoire cache est largement utilisé dans les systèmes informatiques afin d améliorer les performances. En pratique les mémoires cache utilisent le principe de localité. Il existe deux types de localité : La localité temporelle : Si un processeur accède à la mémoire à l adresse A à un instant t, il est fort probable qu il y accédera encore dans les instants qui suivent 25. La localité spatiale : Si un programme a accédé à l adresse A à l instant t, il est fort probable qu il accédera aux adresses proches de A comme A + 4 ou A 4 dans les instants qui suivent 26. Les mémoires caches exploitent ces principes de localité en stockant de façon transparente les instructions et les données les plus récemment utilisées. D un point de vue physique, on peut voir le processeur comme étant connecté à la (ou les) mémoire(s) cache qui est elle-même connecté à la mémoire RAM. Les opérations de lecture en mémoire se déroulent généralement comme suit : 1. Le processeur a besoin de lire une donnée se trouvant a une adresse A. Il fournit donc cette adresse A à la mémoire cache. 2a. Si la donnée correspondante à A est présente en mémoire cache, celle-ci répond directement au processeur. 2b. Sinon, la mémoire cache interroge la mémoire RAM, se met à jour et ensuite fournit la donnée demandée au processeur. Figure 4 Hiérarchie de la mémoire 23. sauf quelques cas rares d applications spécifiques qui nécessitent de hautes performances et se contentent d une capacité limitée 24. En 1980 ce n était pas vraiment utile car la mémoire était nettement plus rapide que le processeur. Mais à partir de 1990 on commence à voir cette tendance s inverser et les mémoires deviennent un frein par rapport aux processeurs dont les performances se sont fortement améliorés. Voir slides pour les graphes. 25. Exemple : Lors de l exécution de boucles qui exécutent à de nombreuses reprises les mêmes instructions 26. Exemple : Lorsqu un programme traite un vecteur stocké en mémoire 12

13 Ce mode de fonctionnement permet de profiter de la localité temporelle. Pour profiter de la localité spatiale, la plupart des caches se mettent à jour en chargeant directement une ligne de cache qui peut compter jusqu à quelques dizaines d adresses en mémoire 27. Opération d écriture Pour les opérations d écriture, la situation est plus compliquée. Si le processeur écrit l information x à l adresse A en mémoire, il faudrait idéalement que cette valeur soit écrite simultanément en mémoire cache et en mémoire RAM de façon à s assurer que la mémoire RAM contient toujours des données à jour. Pour ce faire, analysons les stratégie : La stratégie d écriture la plus simple est baptisée write through. Avec cette stratégie, toute demande d écriture venant du processeur donne lieu à une écriture en mémoire cache et une écriture en mémoire RAM. Cela garantit qu à tout moment la mémoire cache et la mémoire RAM contiennent la même information. Malheureusement cette technique n est pas performante et n est donc pas acceptable! L alternative est d utiliser la technique du write back. Avec cette technique, toute écriture est faite en mémoire cache directement. Ce qui permet d obtenir de très bonne performance pour les opérations d écritures. La donnée n est ré-écrite en mémoire RAM que lorsqu elle doit être retirée de la mémoire cache. Cette ré-écriture est faite automatiquement par la mémoire cache. Pour la plupart des programmes, la gestion des opérations d écriture est transparente. Il faut cependant être attentif à la technique d écriture utilisée lorsque plusieurs dispositifs peuvent accéder directement à la mémoire RAM sans passer par le processeur Étude de cas : Architecture IA32 Cette architecture recouvere un grand nombre de variantes qui ont leur spécificités propre. L architecture IA32 est supportée par différents types de processeurs. Certains utilisent des registres et des bus de données de 32 bits. D autres, plus récents utilisent des registres de 64 bits. Il y a des différences importantes entre ces deux architectures. Comme les processeurs récents supportent à la fois les modes 32 bits et 64 bits, nous nous limiterons à l architecture 32 bits ici. Un élément important d un processeur tel que ceux de l architecture IA32 sont ses registres. Un processeur IA32 dispose de huit registres génériques. Ceux-ci sont baptisés EAX, EBX, ECX, EDX, EBP, ESI, EDI et ESP. Ces registres peuvent stocker des données sous forme binaire. Dans l architecture IA32, ils ont une taille de 32 bits. Cela implique que chaque registre peut contenir un nombre ou une adresse puisque les entiers (int en C) et les adresse (pointeurs * en C) sont tous les deux encodés sur 32 bits dans l architecture IA32. Cette capacité à stocker des données ou des adresses à l intérieur d un même registre est un des points clés de la flexibilité des microprocesseurs. EBP et ESP sont utilisés dans la gestion de la pile 29. Tout processeur contient un registre spécial qui stocke à tout moment l adresse de l instruction courante en mémoire. Ce registre est souvent dénommé le compteur de programme ou program counter (PC). Dans l architecture IA32, il s agit du registre EIP qui stocke l Instruction Pointer qui joue ce rôle. Ce registre ne peut être utilisé pour effectuer des opérations arithmétiques. Il peut cependant être modifié par les instructions de saut et joue un rôle essentiel dans l implémentation des instruction de contrôle. Outre ces registres génériques, les processeurs de la famille IA32 contiennent aussi des registres spécialisés pour manipuler les nombres en virgule flottante (float et double) 30. Les processeurs IA32 contiennent également des drapeaux regroupés dans le registre eflags. Ceux-ci sont utilisés pour implémenter différents tests et comparaisons. Les processeurs qui implémentent les spécifications IA32 supportent les types de données repris dans la table 2. Voyons maintenant les quelques instructions de l architecture IA32 qui permettent de manipuler des nombres entiers. Type Taille (bytes) Suffixe assembleur char 1 b short 2 w int 4 l long int 4 l void * 4 l Table 2 Types de données supportés par les processeurs IA Ce qui permet de profiter des mémoires DRAM qui aujourd hui sont souvent optimisées pour fournir des débits de transfert élevés pour de longs blocs consécutifs en mémoires. 28. C est le cas notamment des cartes réseaux ou de certains contrôleurs de disque dur. Pour des raisons de performances, ces dispositifs peuvent copier des données directement de la mémoire RAM vers le réseau ou un disque dur. Si une écriture de type write back est utilisée, le système d exploitation doit veiller à ce que les données qui ont été écrites par le processeur en cache aient bien été écrites également en mémoire RAM avant d autoriser la carte réseau ou le contrôleur de disque à effectuer un transfert. 29. Voir aussi la section 5.5 à la page Mais ça c est hors matière de ce cours 13

14 5.1 Les instructions mov Les instructions de la famille 31 mov permettent de déplacer des données entre registres ou depuis la mémoire vers un registre ou d un registre vers une zone mémoire. Syntaxe générale : 1 mov src, d e s t ; deplacement de s r c v e r s d e s t Il existe une instruction de la famille mov pour chaque type de donnée pouvant être déplacée : movb, movw et movl qui permettent de déplacer respectivement : 1 byte, un mot de 16 bits, et un mot de 32 bits (voir table 2). En pratique, il y a plusieurs façons de spécifier chaque argument d une instruction mov 32. Les différents mode sont : Le mode registre : Pour spécifier que la source et/ou la destination est un registre. Le nom du registre est alors préfixé par %. Le mode d adressage immédiat : Ne peut être utilisé que pour l argument source. Il permet de placer une constante dans un registre, par exemple pour initialiser sa valeur. Il se reconnaît à l utilisation du symbole $ comme préfixe de la constante. Le mode d adressage absolu : Dans ce mode, l un des arguments de l instruction mov est une adresse en mémoire. Le mode d adressage indirect : Au lieu de spécifier directement une adresse, on spécifie un registre dont la valeur est une adresse en mémoire ( utilisation des pointeurs en langage C). Il se reconnaît à l utilisation des parenthèses autour du nom du registre source ou destination. Le mode avec une base et un déplacement. Ce mode peut être vu comme une extension du mode indirect. Il permet de lire en mémoire à une adresse qui et obtenue en additionnant un entier positif ou négatif, à une adresse stockée dans un registre. Ce mode d adressage joue un rôle important dans le fonctionnement de la pile. 1 ; EXEMPLE MODE REGISTRE 2 movl %eax, %ebx ; deplacement de %eax v e r s %ebx 3 movl %ecx, %ecx ; aucun e f f e t 4 5 ; EXEMPLE MODE IMMEDIAT 6 movl $0, %eax ; i n i t i a l i s a t i o n de %eax a 0 7 movl $1252, %ecx ; i n i t i a l i s a t i o n de %ecx a ; EXEMPLE MODE ABSOLU 10 movl 0x04, %eax ; p l a c e l a v a l e u r contenue a l a d r e s s e 0 x04 en memoire dans %eax 11 movl $1252, %ecx ; i n i t i a l i s a t i o n de %ecx a movl %ecx, 0x08 ; remplace l e contenu de l a memoire a l a d r e s s e 0 x08 par ; EXEMPLE MODE INDIRECT 15 movl $0x08, %eax ; p l a c e l a v a l e u r 0 x08 dans %eax 16 movl (%eax ), %ecx ; p l a c e l a v a l e u r s e trouvant a l a d r e s s e qui e s t dans 17 ; %eax dans l e r e g i s t r e %ecx 18 movl 0x10, %eax ; p l a c e l a v a l e u r s e trouvant a l a d r e s s e 0 x10 dans %eax 19 movl %ecx, (%eax ) ; p l a c e l e contenu de %ecx a l a d r e s s e qui e s t contenue 20 ; dans %eax (0 x10 ) ; EXEMPLE MODE AVEC UNE BASE ET UN DEPLACEMENT 23 movl $0x08,%eax ; p l a c e l a v a l e u r 0 x08 dans %eax 24 movl 0(%eax ), %ecx ; p l a c e l a v a l e u r s e trouvant a l a d r e s s e 0 x08 dans l e 25 ; r e g i s t r e %ecx 26 movl 4(%eax ), %ecx ; p l a c e l a v a l e u r s e trouvant a l a d r e s s e 0x0C (=0x08+4) dans 27 ; l e r e g i s t r e %ecx 28 movl 8(%eax ), %ecx ; p l a c e l a v a l e u r s e trouvant a l a d r e s s e 0 x00 (=0x08 8) dans 29 ; l e r e g i s t r e %ecx L architecture IA32 supporte encore d autres modes d adressage (non vu dans le cours). Une autre instruction permettant de déplacer de l information est l instruction leal (load effective address). Cette instruction place dans le registre destination l adresse de son argument source plutot que sa valeur. Par exemple : leal 4(%esp) %edx placera dans le registre %edx l adresse de son argument source, c est-à-dire l adresse contenue dans %esp Les instructions arithmétiques et logiques La 2e famille d instructions importante sur un processeur sont les instructions qui permettent d effectuer les opérations arithmétiques et logiques. Les instructions les plus simples sont celle qui prennent un seul argument : 31. On parle de famille d instructions car il existe de nombreuses instructions de dpélacement en mémoire. Les plus simples sont suffixées par un caractère qui indique le type de données transféré. Exemple : movb permet le transfert d un byte tandis que movl permet le transfert d un mot de 32 bits. 32. Certains auteurs parlent alors de mode d adressage pour représenter ces différents types d arguments même s il ne s agit pas toujours d adresses. 14

15 inc : incrémente d une unité la valeur stockée dans le registre/l adresse fournie en argument et sauvegarde le résultat de l incrémentation au même endroit. Cette instruction peut être utilisée pour implémenter des compteurs de boucles. dec : même principe que inc mais pour décrémenter. not : applique l opération logique NOT à son argument et stocke le résultat au même endroit. De même que pour mov, il existe une variante de chaque instruction ci-dessus pour chaque type de données : incb, incw, incl,... (voir de nouveau la table 2). L architecture IA32 supporte également des instructions arithmétiques et logiques prenant deux arguments : add : Permet d additionner deux nombres entiers. Prend comme arguments une source et une destination et place dans la destination la somme de ses deux arguments. sub : Permet de soustraire le premier argument du second. Stocke le résultat dans le second. mul : Permet de multiplier des nombres entiers non-signés. (imul permet la multiplication de nombres signés) div : Permet la division de nombres entiers non-signés. shl (reps. shr : Permet de réaliser un décalage logique vers la gauche (resp. droite). xor : Calcul le ou exclusif entre ses deux arguments et sauvegarde le résultat dans le second. and : Calcul la conjonction logique entre ses deux arguments et sauvegarde le résultat dans le second. 5.3 Les instructions de comparaison Les comparaisons sont nécessaires pour implémenter des tests tels que if (condition) {... } else {... }. Sur les processeurs IA32, les comparaisons utilisent des drapeaux qui sont mis à jour par le processeur après l exécution de certaines instructions. Ceux-ci sont regroupés dans le registre eflags. Les principaux drapeaux sont : ZF (Zero Flag) : Indique si le résultat de la dernière opération était zéro SF (Sign Flag) : Indique si le résultat de la dernière instruction était négatif. CF (Carry Flag) : Indique si le résultat de la dernière instruction arithmétique non signée nécessitait plus de 32 bits pour être stocké. OF (Overflow Flag) : Indique si le résultat de la dernière instruction arithmétique signée a provoqué un dépassement de capacité. Nous utiliserons principalement les drapeaux ZF et SF dans ce "chapitre". Ces drapeaux peuvent être fixés par les instructions arithmétiques standard, mais aussi par cmp : Effectue l équivalent d une soustraction et met à jour les drapeaux CF et SF mais sans sauvegarder son résultat dans un registre. test : Effectue une conjonction logique en mettant à jour les drapeaux mais sans sauvegarder son résultat. Ces instructions de comparaison peuvent être utilisées avec les instructions set qui permettent de fixer la valeur d un registre en fonction des valeurs de certains drapeaux du registre eflags. Chaque instruction set prend comme argument un registre. Pour des raisons historiques, ces instructions modifient uniquement les bits de poids faible du registre indiqué et non le registre complet. sete : Met le registre argument à la valeur du drapeau ZF. Permet d implémenter une égalité sets : Met le registre argument à la valeur du drapeau SF. setg : Place dans le registre argument la valeur SF & ZF (tout en prenant compte les dépassements éventuels avec OF). Permet d implémenter la condition >. setl : Place dans le registre argument la valeur SF (tout en prenant compte les dépassements éventuels avec OF). Permet d implémenter la condition <=. 5.4 Les instructions sauts Les instructions de saut sont des instructions de base pour tous les processeurs. Elles permettent de modifier la valeur du compteur de programme %epi de façon à modifier l ordre d exécution des instructions. Elles sont nécessaires pour implémenter les tests, les boucles et les appels de fonction. Les premiers langages de programmation et les langages tels que le BASIC ou FORTRAN disposent d une construction similaire avec l instruction goto. Cependant, l utilisation de l instruction goto dans des programmes de haut niveau rend souvent le code difficile à lire et de nombreux langages de programmation n ont plus de goto 33. Lors de l exécution d un goto, le programme saute directement à l exécution de l instruction qui suit le label indiqué. En assembleur, les instructions de saut sont inévitables. L instruction de saut la plus simple est jmp. Elle prend généralement comme argument une étiquette. Dans ce cas, l exécution du programme après l instruction jmp se poursuivra par l exécution de l instruction qui se trouve à l adresse correspondant à l étiquette fournie en argument. Il est également possible d utiliser l instruction jmp avec un registre comme argument. Ainsi, l instruction jmp *%eax indique que l exécution du programme doit se poursuivre par l exécution de l instruction se trouvant à l adresse qui est contenue dans le registre %eax. 33. Le C permet encore l utilisation de goto (contrairement à Java) mais son utilisation est fortement déconseillée! 15

16 Il existe plusieurs variantes conditionnelles de l instruction jmp. Ces variantes sont exécutées uniquement si la condition correspondante est vérifiée ; les plus fréquentes sont : je : saut si égal (teste ZF). jne : inverse de je. js : saut si négatif (teste SF) jns : inverse de js. jg : saut si strictement supérieur (teste SF et ZF et prend en compte un overflow éventuel) jl : inverse de jg (strictement inférieur) jge : saut si supérieur ou égal (teste SF et prend en compte un overflow éventuel) jle : inverse de jge. Ces variantes sont utilisées pour implémenter des expressions if(condition){... } else {...} en C ou pour implémenter des boucle while par exemple. 5.5 Manipulation de la pile Les instructions mov permettent de déplacer de l information à n importe quel endroit de la mémoire. À côté de ces instructions de déplacement, il y a des instructions qui sont spécialisées dans la manipulation de la pile. La pile, qui dans un processus Unix est stockée dans les adresses hautes est essentielle au bon fonctionnement des programmes. Par convention dans l architecture IA32, l adresse du sommet de la pile est toujours stockée dans le registre %esp. pushl %reg : Place le contenu du registre %reg au sommet de la pile et décrémente dans le registre %esp l adresse du sommet de la pile de 4 unités. popl %reg : Retire le mot de 32 bits se trouvant au sommet de la pile, le sauvegarde dans le registre %reg et incrémente dans le registre %reg l adresse du sommet de la pile de 4 unités. (En pratique ces instructions de manipulation de pile pourraient être écrite un utilisant subl, movl et addl, voir p74). 5.6 Les fonctions et procédures Les fonctions et les procédures sont essentielles dans tout langage de programmation. Une procédure est une fonction qui ne retourne pas de résultat. Une procédure est un ensemble d instructions qui peuvent être appelées depuis n importe quel endroit du programme. Généralement, une procédure est appelée depuis plusieurs endroits différents d un programme. Considérons d abord une procédure en C ne prenant aucun argument (void uneprocedure()) : Le processeur doit transférer l exécution du code à la première instruction de la procédure appelée. Cela se fait en associant une étiquette à chaque procédure qui correspond à l adresse de la première instruction de cette procédure. Il est également nécessaire que la procédure puisse connaître l adresse de l instruction qui doit être exécutée à la fin de son exécution. Dans l architecture IA32, cela se fait en utilisant la pile. Vu l importance des appels de procédure et de fonctions, l architecture IA32 contient 2 instructions dédicacées pour implémenter ces appels. call : Instruction de saut qui transfère l exécution à l adresse de l étiquette passée en argument et en plus elle sauvegarde au sommet de la pile l adresse de l instruction qui la suit. Elle est équivalent à une instruction push suivit d une instruction jmp. ret : Instruction de saut qui suppose que l adresse de retour se trouve au sommet de la pile, retire cette adresse de la pile et fait un saut à cette adresse. Elle est équivalent à une instruction pop suivit d une instruction jmp. Dans l architecture IA32, le registre %esp contient en permanence le sommet de la pile, il est donc utilisé par call et ret. Considérons maintenant une procédure qui prend un argument. Pour qu une telle procédure puisse utiliser son argument, il faut que la procédure appelante puisse placer sa valeur à un endroit où la procédure appelée peut facilement y accéder. Dans l architecture IA32, c est la pile qui joue ce rôle et permet le passage des arguments. En C, les arguments sont passés par valeur et ce sera donc la valeur des arguments qui sera placée sur la pile. La fonction appelante sauvegarde également d autres registres sur la pile avant l appel de la fonction. Ces sauvegardes sont nécessaires car la fonction appelante ne sait pas quels registres seront modifiés par la fonction qu elle appelle. Par convention, dans l architecture IA32, ce sont les registres %eax, %edx et %ecx qui sont sous la responsabilité de la procédure appelante. Une procédure appelée peut modifier sans limite les valeurs de ces registres. D autre part les registres %ebx, %edi et %esi sont sous la responsabilité de la procédure appelée et doivent être sauvé par celle-ci si elle désire les utiliser/modifier. Une fonction - contrairement aux procédure - retourne un résultat. Pour ce faire il faut que la procédure appelante puisse savoir où aller chercher ce résultat après l exécution de l instruction ret. La valeur de retour d une fonction est stockée par convention dans le registre %eax. En vue du fonctionnement des appels de fonction en assembleur, on comprend aisément que l utilisation de fonctions récursives en C à un coût important au niveau de la gestion de la pile. Ces appels récursifs doivent 16

17 donc être réservés à des fonctions où l appel récursif apporte une plus value claire et ne peux pas être réalisé par une fonction itérative. 6 Les threads (Voir évolution des performances des processeurs dans le cours page 95-98) La notion de thread d exécution est très importante dans un système informatique. Elle permet de comprendre comment un ordinateur équipé d un seul microprocesseur peut exécuter plusieurs programme simultanément mais aussi comment des programmes peuvent profiter des nouveaux processeurs (multi-cœurs ou multi-threadé) capables d exécuter plusieurs threads simultanément. Pour rappel, pour qu un processeur puisse exécuter une séquence d instruction, il faut non seulement qu il implémente chaque instruction mais également qu il puisse accéder : à la mémoire contenant les instructions à exécuter à la mémoire contenant les données manipulées par cette séquence d instruction : C est-à-dire la zone contenant les variables globales le tas la pile aux registres, et plus particulièrement : aux registres de données pour stocker les résultats de chacune des instructions. au registre %esp directement ou indirectement via les instructions push et pop de manipulation de la pile au registre %eix qui contient l adresse de l instruction en cours d exécution au registre eflags qui contient l ensemble des drapeaux. Un processeur multithreadé a la capacité d exécuter plusieurs programmes simultanément, pour ce faire il disposera de copies des registres. Chacun de ces bloc de registres pourra être utilisé pour exécuter ces programmes simultanément à raison d un thread d exécution par bloc de registres. Chaque thread d exécution va correspondre à une séquence différente d instructions qui va modifier son propre bloc de registres. Cette capacité d exécuter plusieurs threads d exécution simultanément n est pas limitée à un thread d exécution par programme puisqu au final, un thread d exécution n est finalement qu une séquence d instructions qui utilisent un bloc de registres. En pratique pour qu un programme puisse démarrer un nouveau thread d exécution sur un nouveau bloc de registre, cela nécessite la coopération avec l OS. Le mécanisme le plus courant pour ce faire est connu sous le nom de threads POSIX. 6.1 Les threads POSIX Les threads POSIX sont supportés par la plupart des variantes Unix et sont souvent implémentés dans une librairie (pthreads sous linux). Les fonctions importantes de cette librairie sont : int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg); Permet de créer un nouveau thread d exécution 34. int pthread_join(pthread_t thread, void **value_ptr); Permet de récupérer le résultat d un thread d exécution. L appel de pthread_join ne se terminera que lorsque le thread spécifié se terminera. void pthread_exit(void *retval); Le thread qui exécute cette fonction se termine et retourne la valeur retval au thread parent. (Également possible avec un return) int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); Permet de modifier la taille de la pile d un thread POSIX (Utile si on sait qu un thread devra allouer un grand tableau auquel il sera le seul à avoir accès) Variables volatile Normalement, dans un programme C, lorsqu une variable est définie, ses accès sont contrôlés entièrement par le compilateur. Si une variable est utilisée dans plusieurs calculs successifs, afin d obtenir de bonne performance, il peut être utile de stocker sa valeur dans un registre durant le temps des calculs. Mais dans le cas où cette valeur pourrait être modifié par d autres threads simultanément il peut être utile d indiquer qu il faut recharger sa valeur avant chaque calcul, cela se fait en utilisant le qualificatif volatile qui indique au compilateur qu il doit recharger la variable de la mémoire chaque fois qu elle est utilisée. (à utiliser avec précaution, voir partie sur les mutex etc.) 34. Il est important de veiller à ce que le quatrième argument passé à pthread_create existe toujours (et n ait pas été modifiée) au moment de l exécution effective de la fonction qui démarre le thread lancé. 17

18 6.1.2 Variable spécifique à un thread Pour ce faire, il existe 2 solutions : Utiliser le qualificatif thread devant une déclaration de variable (supporté par gcc avec la librairie threads POSIX). Utiliser les fonctions fournies par la librairie threads POSIX suivantes : pthread_key_create, pthread_key_set, pthread_setspecific, pthread_getspecific et pthread_key_delete. La deuxième solution est plus compliquée à utilisée mais illustre ce qu il se passe en pratique lorsque le qualificatif thread est utilisé. 6.2 Fonctions thread-safe Certaines fonctions (même de la librairie standard) sont susceptible d utiliser des variables globales dans leur exécution, et utilisent l hypothèse qu elles sont appelées par un programme séquentiel ce qui peut poser des problèmes. Lorsque l on développe une fonction qui peut être réutilisée, il est important de s assurer que cette fonction peut être exécutée par plusieurs threads simultanément sans que cela ne pose de problèmes à l exécution. C est pourquoi lorsque l on intègre des fonctions provenant de la librairie standard ou d une autre librairie dans un programme découpé en threads, il est important de vérifier que les fonctions utilisées sont bien thread-safe. La page de manuel man 7 pthreads liste les fonctions qui ne le sont pas. 7 Threads communicants Lorsqu un programme est décomposé en plusieurs threads, ceux-ci doivent en général communiquer entre eux. Le programme principal et le thread qu il a créé partagent 3 zones de mémoires : le segment text (contient l ensemble des instructions) le segment de données (contient toutes les données statiques, initialisées ou non) le heap Par contre, le programme principal et le thread qu il vient de créer ont chacun leur propre contexte et leur propre pile. 7.1 Loi de Amdahl Gene Amdahl considère qu un programme P peut être découpé en deux partie : Une partie purement séquentielle. Il s agit par exemple de l initialisation de l algorithme utilisé, de la collecte des résultats,... une partie qui est parallélisable. Il s agit en général du cœur de l algorithme. Figure 5 Organisation de la mémoire après la création d un thread POSIX Plus les opérations réalisées à l intérieur d un programme sont indépendantes entre elles, plus le programme est parallélisable et inversement. Pour Amdahl, si le temps d exécution d un programme séquentiel est T et qu une fraction f de ce programme est parallélisable, alors le gain qui peut être obtenu de la parallélisation en N threads est : T T.((1 f) + f N 1 = (1 f) + f N (loi de Amdahl) Cette loi fixe une limite théorique difficile à atteindre et suppose que la parallélisation est parfaite c est à dire que la création et la terminaison des threads n ont aucun coût en performance. 7.2 Communication entre threads Le première façon pour un processus de communiquer des infos avec un thread qu il a lancé est d utiliser les arguments de la fonction de démarrage du thread et la valeur retournée par ce thread. Mais c est un canal de communication très limité qui ne permet pas d échange d information pendant l exécution du thread. Un processus peut partager facilement de l information avec ses threads ou même entre plusieurs threads car tout les threads ont accès aux mêmes variables globales et au même heap. Malheureusement la modification d une variable globale ou d une zone mémoire (allouée par malloc) peut être source de problèmes si plusieurs threads accède à la même donnée en même temps. Ce problème d accès à une même donnée est connu sous le nom de problème de la section critique ou exclusion mutuelle. La section critique peut être définie comme étant une séquence d instructions qui ne peuvent jamais être exécutées par plusieurs threads simultanément. En pratique on retrouvera une section critique chaque fois 18

19 que deux threads peuvent modifier ou lire la valeur d une même zone de la mémoire. Afin d éviter ce problème il faut utiliser la coordination entre threads. 7.3 Coordination entre threads Exclusion mutuelle - Dijkstra Le problème de l exclusion mutuelle à été initialement proposé par Dijkstra (en 1965). Il peut être reformulé de la façon suivante pour un programme décomposé en threads : Considérons un programme à N threads. Chaque threads est exécuté cycliquement et possède une section critique et une section non-critique. La durée d exécution de chaque partie n est pas connue et peut être différentes pour chaque thread. Le problème de l exclusion mutuelle consiste à trouver un algorithme qui permet de garantir qu il n y aura jamais deux threads qui simultanément exécuteront les instructions de leur section critique. Cela revient à dire qu il n y aura pas de violation de la section critique. Cette propriété est une propriété de sureté (safety). Dans un programme découpé en threads, une propriété de sureté est une propriété qui doit être vérifie à tout instant de l exécution du programme. Conditions à satisfaire pour résoudre le problème de l exclusion mutuelle 1. Tout les threads doivent être considéré de la même façon, on ne peut faire aucune hypothèse sur la priorité relative des différents threads. 2. On ne peut faire aucune hypothèse sur la vitesse relative ou absolue d exécution des différents threads. 3. Doit permettre à un thread de s arrêter en dehors de sa section critique sans que cela n invalide la contrainte d exclusion mutuelle. 4. Aucun thread qui souhaite entamer sa section critique ne doit être empêché indéfiniment d y accéder. La 4e contraintes est un exemple de propriété de vivacité (liveness). Une propriété de vivacité est une propriété qui ne peut pas être éternellement invalidée. Exclusion mutuelle sur monoprocesseurs Sur un ordinateur monoprocesseur, un OS multitâche tel que Unix exécute régulièrement des changement de contexte entre threads. Le contexte d un thread est composé de l ensemble des contenus des registres qui sont nécessaires à son exécution (y compris le contenu des registres spéciaux tels que %esp, %eip et %eflags). Ces registres définissnt l état du thread du point de vue du processeur. Pour passer d un thread T 1 à un thread T 2 l OS doit initier un changement de contexte. Pour ce faire il copie le contenu des registres utilisés par T 1 vers une zone mémoire lui appartenant puis transfère depuis une autre zone mémoire lui appartenant le contexte de T 2. Sur un système Unix, il y a 2 types d événements qui peuvent provoquer un changement de contexte. Le hardware génère une interruption. Un thread exécute un appel système bloquant. Interruption : Une interruption est un signal électronique qui est généré par un dispositifs connectés au microprocesseur. De nombreux dispositifs d entrées-sorties comme les cartes réseau ou les contrôleurs de disque peuvent générer une interruption lorsqu une information a été lue ou reçue et doit être traitée par le processeur. En outre, chaque ordinateur dispose d une horloge temps réel qui génère des interruptions à une fréquence déterminée par l OS (entre quelques dizaines et quelques milliers de Hz). Ces interruptions nécessitent un traitement rapide de la part de l OS : C est pourquoi le processeur vérifie, à la fin de l exécution de chaque instruction si un signal d interruption est présent 35.Si c est le cas, le processeur sauvegarde en mémoire le contexte du thread en cours d exécution et lance une routine de traitement d interruption faisant partie du système d exploitation. Appel système : Un thread exécute un appel système chaque fois qu il doit intéragir avec l OS. Ces appels peuvent être exécutés directement ou via une fonction de la librairie 36. Appel système non-bloquant est un appel système que l OS peut exécuter immédiatement. Ce type d appel retourne en général une valeur qui fait partie de l OS lui-même (par exemple gettimeofday). Appel système bloquant est un appel système dont le résultat ne peut pas toujours être fourni immédiatement (par exemple : lecture d information en provenance de l entrée standard). Dans ce cas le thread est mis en attente et aucune instruction de ce thread n est exécuté tant que le résultat n est pas connu. Le contexte du thread est mis en attente dans une zone mémoire gérée par l OS. Il sera redémarré automatiquement lorsque la donnée attendue sera disponible. 35. Le cours se limite à un seul type de signa d interruption 36. La section 2 du manuel décrits les appels systèmes, la section 3 décrit les fonctions de la librairie. 19

20 La figure 6 représente les différents état d un thread. Lorsqu un thread est crée (avec pthread_create), il est placé dans l état Ready. Les transitions entre les différents états d un thread sont gérées par l OS. Lorsque plusieurs threads d exécution sont simultanément actifs, l OS doit arbitrer les demandes d utilisation du CPU de chaque thread. Cet arbitrage est réalisé par l ordonnanceur (ou scheduler). Le scheduler est un ensemble d algorithmes qui sont utilisés par l OS pour sélectionner le ou les threads qui peuvent utiliser un processeur à un moment donné. Citons quelques principes de base de fonctionnement de quelques Figure 6 États d un thread d exécution schedulers : le scheduler round-robin : Ce scheduler maintient en permanence une liste circulaire de l ensemble des threads qui se trouvent dans l état Ready et un pointeur vers l élément courant de cette liste. En général ce type de scheduler limite le temps passé sur un processeur afin d éviter qu un thread ne le monopolise. Un scheduler round-robin est équitable, si N thread sont actifs en permanence, ils recevront chacun 1 N de temps CPU disponible. le scheduler à priorités : Une priorité est associée à chaque thread. Lorsque le scheduler doit sélectionner un thread à exécuter, il commence d abord par parcourir les threads ayant une haute priorité. En pratique le scheduler maintient une liste circulaire par niveau de priorité et s il y a plusieurs thread pour un niveau de priorité, il utilisera le principe du round-robin pour le niveau en question. Sous Unix, il s agit d un scheduler à priorité avec un round-robin à chaque niveau de priorité, mais la priorité varie dynamiquement en fonction du temps et des opérations d entrées sorties effectuées de façon à favoriser les threads interactifs. Note : Il est possible à un thread d indiquer explicitement qu il peut être remplacé par un autre thread en utilisant pthread_yield (par exemple utile si on a un thread qui calcul des statistique et ne doit pas ralentir le fonctionnement des autres threads). Problème de l exclusion mutuelle, le retour! Sur une machine monoprocesseur une violation de la section critique ne serait possible qui s il y a une interruption lorsqu on est dans celle-ci. Une solution pour résoudre le problème serait donc de désactiver les interruptions avant la section critique puis de les réactiver après la fin de celle-ci. Ce serait possible mais Ça perturbe le fonctionnement de l OS : sans interruptions, la plupart des opérations d entrées-sorties et l horloge sont inutilisable. (Donc cette désactivation doit être très courte) Il s agit d une opération privilégiée sur un microprocesseur, il faudrait donc imaginer un appel système qui permettrait à un thread de faire la demande auprès de l OS. Si un thread désactiverait les interruptions sans les réactivées après quelques instants, cela rendrait la machine complètement inutilisable puisque sans interruption plus aucune opération d entrée-sortie n est possible. Conclusion : Ce n est pas un mécanisme utilisable 37! L algorithme de Peterson Cette solution permet à plusieurs threads de coordonner leur exécution de façon à éviter une violation de section critique en utilisant uniquement des variables accessibles à tous les threads. La solution est applicable à N thread mais nous nous limiterons à 2 threads. 1 #d e f i n e A 0 2 #d e f i n e B 1 3 i n t f l a g [ ] ; 4 f l a g [A]= f a l s e ; 5 f l a g [B]= f a l s e ; 6 // thread A 7 void threada ( void ) { 8 f l a g [A]= t r u e ; 9 turn=b; 10 w h i l e ( ( f l a g [B]==true )&&(turn==b) ) { / loop / } 11 s e c t i o n _ c r i t i q u e ( ) ; 12 f l a g [A]= f a l s e ; 13 // } 15 // Thread B 16 void threadb ( void ) { 37. Bien que ce soit parfois utilisé par certains OS qui l utilisent à l intérieur de l OS même. 20

21 17 f l a g [B]= t r u e ; 18 turn=a; 19 w h i l e ( ( f l a g [A]==true )&&(turn==a) ) 20 { / loop / } 21 s e c t i o n _ c r i t i q u e ( ) ; 22 f l a g [B]= f a l s e ; 23 // } Pour arriver à cet algorithme, les pages 114 à 117 du cours explique les différents raisonnements et problèmes qui y sont liés. Il faut être attentif au livelock et aux conditions énoncées précédemment pour résoudre l exclusion mutuelle. Un livelock est une situation dans laquelle plusieurs threads exécutent une séquence d instructions (par exemple une boucle while) sans qu aucun thread ne puisse réaliser de progrès. Un livelock est un problème gênant puisque lorsqu il survient les threads concernés continuent à utiliser le processeur mais n exécutent aucune instruction utile. Utilisation d instruction atomique Sur les ordinateurs actuels, il est difficile d utiliser l algorithme de Peterson tel que décrit plus haut car Les compilateurs optimise le code et peuvent supprimer les instructions qui peuvent sembler inutiles. Sur un ordinateur multi-processeur, chaque processeur peut réordonner les accès à la mémoire automatiquement afin d en optimiser les performances. (Et donc la lecture et l écriture en mémoire ne se fait pas toujours dans le même ordre que celui prévu initialement) Pour résoudre ce problème, les architectes de microprocesseurs ont proposé l utilisation d opérations atomiques. Une opération atomique est une opération qui lorsqu elle est exécutée sur un processeur ne peut pas être interrompue par l arrivée d une interruption. De plus, l exécution d une instruction atomique par un ou plusieurs processeur implique une coordination des processeurs pour l accès à la zone mémoire référencée dans l instruction. Via un mécanisme qui sort du cadre de ce cours, tous les accès à la mémoire faits par les instruction atomique sont réalisés séquentiellement. Considérons l instruction xchg supportée par les processeur IA32. Cette instruction permet d échanger, de façon atomique, le contenu d un registre avec une zone de la mémoire. Elle prend deux arguments : un registre et une adresse en mémoire. Elle est équivalente à trois instruction mov successive. Avec cette instruction atomique, il est possible de résoudre le problème de l exclusion mutuelle en utilisant une zone mémoire (lock) qui prend la valeur 1 ou 0. Lorsqu un thread veux exécuter sa section critique, il place la valeur 1 dans un de ses registre, échange ce registre avec la zone mémoire lock en utilisant xchg. Si la valeur de son registre en 0, c est qu il peut rentrer dans sa section critique, sinon c est qu un autre thread est dans sa section critique. Pour quitter la section critique il suffit ensuite de placer la valeur 0 en utilisant de nouveau xchg. Le code ci-dessous montre un exemple : 1 l o c k : ; e t i q u e t t e, v a r i a b l e 2. l o n g 0 ; i n i t i a l i s e e a e n t e r : 5 movl $1, %eax ; %eax=1 6 xchgl %eax, ( l o c k ) ; i n s t r u c t i o n atomique, echange ( l o c k ) e t %eax 7 ; a p r e s execution, %eax c o n t i e n t l a donnee qui e t a i t 8 ; dans l o c k e t l o c k l a v a l e u r 1 9 t e s t l %eax, %eax ; met l e f l a g ZF a v r a i s i %eax c o n t i e n t 0 10 j n z e n t e r ; r e t o u r a e n t e r : s i ZF e s t v r a i 11 r e t l e a v e : 14 mov $0, %eax ; %eax=0 15 xchgl %eax, ( l o c k ) ; i n s t r u c t i o n atomique 16 r e t Coordination par Mutex L algorithme de Peterson et l utilisation d instructions atomiques sont des mécanismes de base permettant de résoudre le problème de l exclusion mutuelle. Ils sont utilisés par des fonctions de la librairie POSIX threads. Et il est préférable de ne pas les utiliser directement pour des raisons de portabilité et de spécificités matérielles. Il faut donc utiliser les fonctions de la librairie POSIX threads. Les mutex Un mutex 38 est une structure de données qui permet de controler l accès à une ressource. Un mutex qui controle une ressource peut se trouver dans 2 états : libre (ou unlocked) 38. Abréviation de mutual exclusion 21

22 réservée (ou locked) Un mutex est toujours associé à une ressource. Cette ressource peut être une variable globale, une structure de données plus complexe, une base de données, un fichier,... Les mutex s utilisent par l intermédiaire de 2 fonctions : lock (pthread_mutex_lock) : Pour obtenir le verrou. Attend que la ressource se libère si elle est bloquée unlock (pthread_mutex_unlock) : Pour libérer le verrou (à la fin de la section critique). Si un thread est en attente, laisse le verrou mais autorise le (un seul) thread en attente à passer son lock. En C, un mutex est représenté par une structure de donnée pthread_mutex_t qui est définie dans pthread.h et qu il faut initialiser avec pthread_mutex_init et détruire avec pthread_mutex_destroy afin de libérer les ressources qui y sont associées. Montrons que cette solution de mutex répond bien au problème de l exclusion mutuelle. La propriété de sûreté est bien respecté puisqu aucun thread ne pourra entrer dans sa section critique si un autre s y trouve déjà (et 2 threads ne peuvent y rentrer en même temps). La propriété de vivacité est respecté si chaque thread exécute pthread_mutex_unlock dès qu il sort de sa section critique, c est donc une règle à toujours respecter! Pour qu un thread ne puisse jamais entrer en section critique, il faudrait qu il y aie en permanence plusieurs threads en attente et que notre thread ne soit jamais sélectionné par le système lorsque le thread précédent termine sa section critique Le problème des philosophes et deadlock Le problème des philosophe est résumé sur la figure 7. Chacun veut saisir la baguette de droite et de gauche qui sont chacune partagée avec (respectivement) son voisin de gauche et de droite. Le problème est que si tout le monde commence par prendre la baguette de gauche, il n y a plus de baguette de droite disponible (puisqu elle est à gauche de votre voisin de droite) et donc on se trouve dans une impasse. Il s agit d un deadlock. Un programme est en situation de deadlock lorsque tous ses threads d exécution sont bloqués et qu aucun d entre eux ne peut être débloqué sans exécuter d instructions d un des threads bloqués. La seule façon de sortir d un programme dans une situation de deadlock, est de l arrêter complètement et de le redémarrer. C est donc un problème grave! Attention : Les tests successifs ne permettent pas toujours de détecter les deadlock, il se peut qui ne se produise qu après un temps assez long. Figure 7 Problème des philosophes Une solution au problème des philosophes serait d ordonnée les baguettes (leurs assigner un numéro par exemple), et de faire en sorte que les philosophes les prennent toujours dans le même ordre comme présenté ci-dessous. Cette solution fonctionne néanmoins il faut être conscient qu avec cette solution il est possible qu un seul philosophe ne mange alors que tout les autres attendent, ce qui est une perte de performance énorme lorsqu il y a beaucoup de philosophe! 1 void p h i l o s o p h e ( void arg ) 2 { 3 i n t i d =( i n t ) arg ; 4 i n t l e f t = i d ; 5 i n t r i g h t = ( l e f t + 1) % PHILOSOPHES; 6 w h i l e ( t r u e ) { 7 // p h i l o s o p h e pense 8 i f ( l e f t <r i g h t ) { 9 pthread_mutex_lock(& baguette [ l e f t ] ) ; 10 pthread_mutex_lock(& baguette [ r i g h t ] ) ; 11 } 12 e l s e { 13 pthread_mutex_lock(& baguette [ r i g h t ] ) ; 14 pthread_mutex_lock(& baguette [ l e f t ] ) ; 15 } 16 mange ( i d ) ; 17 pthread_mutex_unlock(& baguette [ l e f t ] ) ; 18 pthread_mutex_unlock(& baguette [ r i g h t ] ) ; 19 } 20 r e t u r n (NULL) ; 21 } Ce problème des philosophe est à l origine de la règle de bonne pratique suivante : Pour éviter les deadlocks, il est nécessaire d ordonnancer tous les mutex utilisés par le programme dans un ordre struct. Lorsqu un thread doit réserver plusieurs mutex en même temps, il doit toujours effectuer ses appels à pthread_mutex_lock dans l ordre choisi pour les mutex. (Sinon deadlock possible) Les sémaphores Il s agit d une autre solution au problème de la coordination entre threads. Un sémaphore est une structure de données qui est maintenue par l OS et contient : 22

23 Un entier qui stocke la valeur, 0, du sémaphore Une queue qui contient les pointeurs vers les threads qui sont bloqués en attente sur le sémaphore. L implémentation d un sémaphore contient 4 fonctions principale : Une fonction d initialisation du sémaphore (int sem_init(sem_t *sem, int pshared, unsigned int value);). Une fonction permettant de détruire le sémaphore et libérer les ressources associées (int sem_destroy(sem_t *sem);). Une fonction post qui permet d incrémenter la valeur du sémaphore ou de débloquer un thread en attente (s il y en a un). (int sem_post(sem_t *sem);). Une fonction wait qui permet de tester la valeur du sémaphore, si elle est > 0, décrémente le sémaphore et continue, sinon bloque le thread et attend qu un autre thread fasse un post. (int sem_wait(sem_t *sem);). Dans le cadre de ce cours ne nous limitons au sémaphore POSIX. Pour pouvoir les utiliser il faut importer semaphore.h qui contient les différentes signatures (dont celle reprisent dans la liste ci-dessus) et la structure de données de type sem_t. Exclusion mutuelle Les sémaphores permettent de résoudre le problème de l exclusion mutuelle. En fait lorsque le sémaphore est initialisé à 1, on peut l utiliser de manière semblable à un mutex. Néanmoins il y a des différences importantes : Un sémaphore est conçu pour être manipulé par différents threads et il est très possible qu un thread exécute sem_wait et qu un autre exécute sem_post. Pour les mutex, certaines implémentations supposent que c est le même thread qui exécute le lock et le unlock. Lorsque ces opérations doivent être effectuées dans des threads différents,e il est donc préférable d utiliser des sémaphores à la place des mutex. Problème du rendez-vous Ce problème est rencontré lorsqu une application découpé en N thread doit attendre la fin de l exécution d une première phase dans les N threads avant de pouvoir passer à la suite. Chaque thread peut être résumé par une 1e phase, suivit d un endroit de "rendez-vous" pour tous les threads et d une deuxième phase. La solution est la suivante : 1 premiere_phase ( ) ; 2 3 pthread_mutex_lock(&mutex ) ; // s e c t i o n c r i t i q u e pour count 4 count++; 5 i f ( count==n) { // s i tous l e s t h r e a d s sont a r r i v e s 6 sem_post(& rendezvous ) ; 7 } 8 pthread_mutex_unlock(&mutex ) ; // f i n de s e c t i o n c r i t i q u e 9 sem_wait(& rendezvous ) ; // a t t e n t e a l a " b a r r i e r e " 10 sem_post(& rendezvous ) ; // l i b e r a t i o n d un a u t r e thread en a t t e n t e seconde_phase ( ) ; Cette solution permet de résoudre le problème du rendez-vous avec un nombre fixe de threads 39. Problème des producteurs-consommateurs Soit une application découpé en deux types de threads (dont le nombre n est pas connu ni fixe à priori) : les producteurs : Produisent des données et placent le résultat dans une zone mémoire accessible aux consommateurs. les consommateurs : Utilisent les données produitent par les producteurs. Ces deux types de threads communiquent en utilisant un buffer qui a une capacité limité à N slots comme sur la figure 8 Le buffer étant partagé, il est nécessaire d utiliser un mutex pour protégé son accès. Un producteur Figure 8 Problème des producteurs-consommateurs 39. Certains implémentations de la librairie threads POSIX implémentent une barrière similaire à la solution ci-dessus. Une barrière est une structure de données de type pthread_barrier_t. Elle s initialise en utilisant la fonction pthread_barrier_init qui prend 3 arguments : un pointeur vers une barrière, des attributs optionnels et le nombre de threads qui doivent avoir atteint la barrière pour que celle-ci s ouvre. La fonction pthread_barrier_destroy permet de détruire une barrière. Enfin, la fonction pthread_barrier_wait qui prend comme argument un pointeur vers une barrière. 23

24 ne doit être bloqué que si tout le buffer est rempli et inversement un consommateur ne doit être bloqué que si tout le buffer est vide. Le problème peut être résolu avec 2 sémaphores comme le montre les extraits de codes ci-dessous // Dans l a f o n c t i o n p r i n c i p a l e : I n i t i a l i s a t i o n 2 #d e f i n e N 10 // nbre de s l o t s du b u f f e r 3 pthread_mutex_t mutex ; sem_t empty ; sem_t f u l l ; 4 5 pthread_mutex_init(&mutex, NULL) ; 6 sem_init(&empty, 0, N) ; // empty compte l e nbre de s l o t v i d e => N = b u f f e r v i d e 7 sem_init(& f u l l, 0, 0) ; // f u l l compte l e nbre de s l o t rempli => 0 = b u f f e r v i d e // Le Producteur 10 void producer ( void ) { 11 i n t item ; 12 w h i l e ( t r u e ) { 13 item=produce ( item ) ; 14 sem_wait(&empty ) ; // a t t e n t e d un s l o t l i b r e 15 pthread_mutex_lock(&mutex ) ; // s e c t i o n c r i t i q u e 16 i n s e r t _ i t e m ( ) ; 17 pthread_mutex_unlock(&mutex ) ; // f i n de s e c t i o n c r i t i q u e 18 sem_post(& f u l l ) ; // i l y a un s l o t r e mpli en p l u s 19 } 20 } // Le Consommateur 23 void consumer ( void ) { 24 i n t item ; 25 w h i l e ( t r u e ) { 26 sem_wait(& f u l l ) ; // a t t e n t e d un s l o t r empli 27 pthread_mutex_lock(&mutex ) ; // s e c t i o n c r i t i q u e 28 item=remove ( item ) ; 29 pthread_mutex_unlock(&mutex ) ; 30 sem_post(&empty ) ; // i l y a un s l o t l i b r e en p l u s 31 } 32 } Problème des readers-writers Soit de nouveau une application découpé en deux types de threads (dont le nombre n est pas connu ni fixe à priori) : les lecteurs (readers) qui lisent des données partagées mais ne les modifie pas. les écrivains (writers) qui modifient des données partagées. Plusieurs readers peuvent lire en même temps, mais lorsqu un writers modifie les données, il ne peut ni avoir d autre writers ni de readers qui utilisent les données. Lorsqu on cherche une solution à ce problème il faut faire attention à ne pas donner priorité aux readers (ce qui serait plus simple). Une solution au problème est présentée dans les extraits de codes ci-dessous / I n i t i a l i s a t i o n / 2 pthread_mutex_t mutex_readcount ; // p r o t e g e readcount 3 pthread_mutex_t mutex_writecount ; // p r o t e g e w r i t e c o u n t 4 pthread_mutex_t z ; // un s e u l r e a d e r en a t t e n t e 5 sem_t wsem ; // a c c e s e x c l u s i f a l a db 6 sem_t rsem ; // pour b l o q u e r des r e a d e r s 7 i n t readcount =0; 8 i n t w r i t e c o u n t =0; 9 sem_init(&wsem, 0, 1) ; 10 sem_init(&rsem, 0, 1) ; / Writer / 13 w h i l e ( t r u e ) { 14 think_up_data ( ) ; 15 pthread_mutex_lock(&mutex_writecount ) ; // s e c t i o n c r i t i q u e w r i t e c o u n t 16 w r i t e c o u n t=w r i t e c o u n t +1; 17 i f ( w r i t e c o u n t==1) { // s i c e s t l e premier w r i t e r qui a r r i v e 18 sem_wait(&rsem ) ; 19 } 20 pthread_mutex_unlock(&mutex_writecount ) ; // f i n de l a s e c t i o n c r i t i q u e w r i t e c o u n t 21 sem_wait(&wsem) ; // s e c t i o n c r i t i q u e, un s e u l w r i t e r a l a f o i s 22 write_ database ( ) ; 23 sem_post(&wsem) ; // f i n de l a s e c t i o n c r i t i q u e 24 pthread_mutex_lock(&mutex_writecount ) ; // s e c t i o n c r i t i q u e w r i t e c o u n t 25 w r i t e c o u n t=writecount 1; 26 i f ( w r i t e c o u n t==0) { // depart du d e r n i e r w r i t e r 27 sem_post(&rsem ) ; 40. Certaines implémentations de la librairie threads POSIX contiennent des Read-Write locks qui s appuie sur des sémaphore pour résoudre le problème des readers-writers... 24

25 28 } 29 pthread_mutex_unlock(&mutex_writecount ) ; // f i n de l a s e c t i o n c r i t i q u e w r i t e c o u n t 30 } / Reader / 33 w h i l e ( t r u e ) { 34 pthread_mutex_lock(&z ) ; // 1 e e x c l u s i o n mutuelle, un s e u l r e a d e r en a t t e n t e sur rsem 35 sem_wait(&rsem ) ; pthread_mutex_lock(&mutex_readcount ) ; // e x c l u s i o n mutuelle, r e a d e r c o u n t 38 readcount=readcount +1; 39 i f ( readcount==1) { // s i a r r i v e e du premier r e a d e r 40 sem_wait(&wsem) ; 41 } 42 pthread_mutex_unlock(&mutex_readcount ) ; // f i n e x c l u s i o n mutuelle, r e a d e r c o u n t 43 sem_post(&rsem ) ; // l i b e r a t i o n du prochain r e a d e r 44 pthread_mutex_unlock(&z ) ; // f i n 1 e e x c l u s i o n mutuelle 45 read_database ( ) ; 46 pthread_mutex_lock(&mutex_readcount ) ; // e x c l u s i o n mutuelle, readcount 47 readcount=readcount 1; 48 i f ( readcount==0) { // s i depart du d e r n i e r r e a d e r 49 sem_post(&wsem) ; 50 } 51 pthread_mutex_unlock(&mutex_readcount ) ; // f i n e x c l u s i o n mutuelle, readcount 52 use_data_read ( ) ; 53 } 8 Processus Un processus peut être défini comme étant une instance de programme qui est en train d être exécuté sur un ou plusieurs processeurs sous le contrôle d un système d exploitation. Un processus comprend donc un ensemble d instructions pour le processeur, les données qui sont stockées en mémoire et un ou plusieurs (si plusieurs threads) contextes. En outre, l OS maintient un certain nombre de structure de données qui sont nécessaires au bon fonctionnement du processus. Ces structures de données sont créées au démarrage du processus, mises à jour durant la vie du processus puis supprimées lorsque le processus s arrête. 8.1 Les librairies Lorsqu un programme s exécute à l intérieur d un processus, il exécute des instructions de différentes "origines" : Les instructions écrites par le programmeur, provenant d un ou de plusieurs module et regroupée dans un exécutable. Les instructions des librairies standard du système. Si on analyse la compilation avec gcc, on constatera que le code des librairies standard ne sont pas inclus mais que seul les appels aux fonctions y sont indiqués. Cela explique la taille réduite des exécutables sous Linux et de nombreuses variantes Unix. Un programme peut utiliser deux types de librairies : une librairie statique (static library) est une librairie de fonctions qui est intégrée directement avec le programme. Elle fait entièrement partie de l exécutable. Avantage : Portabilité. Désavantage : Poids une librairie partagée (shared library) est un ensemble de fonctions qui peuvent être appelées par un programme mais sont stockées dans un seul fichier sur le disque. Ce fichier unique est utilisé automatiquement par tous les programmes qui utilisent des fonctions de la librairie. Avantage : Poids, pas de copies inutiles. Il est parfois intéressant de créer une librairie qui peut être liée de façon statique, par exemple pour une exécution sur un autre ordinateur. Pour ce faire il faut compiler les fichiers objet correspondant aux différents modules de la librairie (avec gcc). Ensuite il faut regrouper les différents modules dans une archive qui constituera la librairie. Par convention, toutes les librairies ont un nom qui commence par lib et se termine par l extension.a. Sous Linux,cette opération est réalisée par l utilitaire ar 41. L archive contenant la librairie peut être liée en utilisant le linker à n importe quel programme qui en utilise une ou plusieurs fonctions. Avec gcc ça donne par exemple ça : gcc static -g -o executable libname.a exemple.o. L argument static force le compilateur à inclure le code de la librairie dans l exécutable. Lorsqu un programme est compilé de façon à utiliser une librairie dynamique, c est l OS qui analyse le programme lors de son chargement et intègre automatiquement les fonctions des librairies qui sont nécessaires 41. Voir page de manuel. En bref : ar r libname.a module.o permet l ajout d un module objet. ar d libname.a module.o permet la suppression d un module objet d une librairie et ar tv libname.a permet de lister le contenu de la librairie 25

26 à son exécution. L entête de l exécutable contient de l information générée par le compilateur qui permet de localiser les librairies dynamiques qui doivent être intégrées Les appels système Figure 9 Appels systèmes Outre l utilisation de fonctions de librairies, les programmes doivent interagir avec l OS. Un OS tel qu Unix contient des utilitaires tels que ls, grep,... et un noyau ou kernel. Le kernel contient les fonctions de base du système d exploitation qui lui permet à la fois d interagir avec le matériel et de gérer les processus en mémoire. Parmi les fonctions de bases, il y en a un petit nombre (de quelques dizaines à quelques centaines) qui sont utilisable par les processus lancés par les utilisateurs. Ce sont les appels système. Un appel système est une fonction du kernel qui peut être appelée par n importe quel processus. Pour un appel système on a : 1. Appeler le kernel. L adresse de retour est automatiquement sauvegardée sur la pile lors de l instruction qui fait appel au kernel (comme avec calll). 2. Quel appel système? Le numéro de l appel système est placé dans le registre %eax, cela permet à la routine de l OS de savoir de quel appel système il s agit 3. Passer les arguments Sous Linux, les arguments d un appel système sont placés par convention dans des registres. Sur IA32, le 1e argument est placé dans le registre %ebx, le 2e dans %ecx,... Ce qui permet au kernel de facilement récupérer les arguments d un appel système en lisant le contenu des registres. 4. Exécuter appel système 5. Retourner le résultat À la fin de l appel système, le résultat est placé dans %eax. Et errno est mis à jour en cas d échec. 6. Retour au processus appelant Les processeurs actuels fonctionnent au minimum avec deux modes : le mode utilisateur où quelques instructions spécifiques de manipulation du matériel et certaines adresses mémoires ne sont pas utilisable. le mode protégé ou toutes les instructions du processeur et toutes les adresses mémoires sont utilisables Le noyau de l OS s exécute en mode protégé tandis que les processus utilisateurs s exécutent en mode utilisateur. Ces derniers ne peuvent donc pas directement exécuter les instructions permettant une interaction avec des dispositifs matériel ; pour cela il faut passer par l OS. Lorsqu un utilisateur démarre, le processeur est placé en mode protégé et le kernel se charge. Il initialise différentes structures de données et lance init qui est le 1e processus du système. Dès que init a été lancé, le processeur passe en mode utilisateur et exécute les instructions de ce processus. Après cette phase de démarrage, les instructions du kernel seront exécutées lorsque une interruption matérielle surviendra ou qu un processus utilisateur exécutera un appel système. L interruption matérielle place automatiquement le processeur en mode protégé et le kernel exécute la routine de traitement d interruption correspondant à l interruption qui est apparue. Un appel système démarre par l exécution d une instruction spéciale (parfois appelée interruption 42. L utilitaire ldd permet de lister les librairies partagées d un exécutable 26

Programmation C. Apprendre à développer des programmes simples dans le langage C

Programmation C. Apprendre à développer des programmes simples dans le langage C Programmation C Apprendre à développer des programmes simples dans le langage C Notes de cours sont disponibles sur http://astro.u-strasbg.fr/scyon/stusm (attention les majuscules sont importantes) Modalités

Plus en détail

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP COURS PROGRAMMATION INITIATION AU LANGAGE C SUR MICROCONTROLEUR PIC page 1 / 7 INITIATION AU LANGAGE C SUR PIC DE MICROSHIP I. Historique du langage C 1972 : naissance du C dans les laboratoires BELL par

Plus en détail

Architecture des ordinateurs

Architecture des ordinateurs Architecture des ordinateurs Cours 4 5 novembre 2012 Archi 1/22 Micro-architecture Archi 2/22 Intro Comment assembler les différents circuits vus dans les cours précédents pour fabriquer un processeur?

Plus en détail

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3. 1. Structure d un programme C Un programme est un ensemble de fonctions. La fonction "main" constitue le point d entrée pour l exécution. Un exemple simple : #include int main() { printf ( this

Plus en détail

Logiciel de base. Première année ENSIMAG

Logiciel de base. Première année ENSIMAG Logiciel de base Première année ENSIMAG 1 Procédures, paramètres, pile En assembleur une fonction est une étiquette, c'est l'adresse de sa première instruction Lors de l'appel d'une fonction, la pile sert

Plus en détail

UE Programmation Impérative Licence 2ème Année 2014 2015

UE Programmation Impérative Licence 2ème Année 2014 2015 UE Programmation Impérative Licence 2 ème Année 2014 2015 Informations pratiques Équipe Pédagogique Florence Cloppet Neilze Dorta Nicolas Loménie prenom.nom@mi.parisdescartes.fr 2 Programmation Impérative

Plus en détail

Bases de programmation. Cours 5. Structurer les données

Bases de programmation. Cours 5. Structurer les données Bases de programmation. Cours 5. Structurer les données Pierre Boudes 1 er décembre 2014 This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License. Types char et

Plus en détail

La mémoire. Un ordinateur. L'octet. Le bit

La mémoire. Un ordinateur. L'octet. Le bit Introduction à l informatique et à la programmation Un ordinateur Un ordinateur est une machine à calculer composée de : un processeur (ou unité centrale) qui effectue les calculs une mémoire qui conserve

Plus en détail

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51 DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51 PLAN DU COURS Introduction au langage C Notions de compilation Variables, types, constantes, tableaux, opérateurs Entrées sorties de base Structures de

Plus en détail

IV- Comment fonctionne un ordinateur?

IV- Comment fonctionne un ordinateur? 1 IV- Comment fonctionne un ordinateur? L ordinateur est une alliance du hardware (le matériel) et du software (les logiciels). Jusqu à présent, nous avons surtout vu l aspect «matériel», avec les interactions

Plus en détail

Conventions d écriture et outils de mise au point

Conventions d écriture et outils de mise au point Logiciel de base Première année par alternance Responsable : Christophe Rippert Christophe.Rippert@Grenoble-INP.fr Introduction Conventions d écriture et outils de mise au point On va utiliser dans cette

Plus en détail

Cours Programmation Système

Cours Programmation Système Cours Programmation Système Filière SMI Semestre S6 El Mostafa DAOUDI Département de Mathématiques et d Informatique, Faculté des Sciences Université Mohammed Premier Oujda m.daoudi@fso.ump.ma Février

Plus en détail

IN 102 - Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

IN 102 - Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C IN 102 - Cours 1 Qu on le veuille ou non, les systèmes informatisés sont désormais omniprésents. Même si ne vous destinez pas à l informatique, vous avez de très grandes chances d y être confrontés en

Plus en détail

Cours d initiation à la programmation en C++ Johann Cuenin

Cours d initiation à la programmation en C++ Johann Cuenin Cours d initiation à la programmation en C++ Johann Cuenin 11 octobre 2014 2 Table des matières 1 Introduction 5 2 Bases de la programmation en C++ 7 3 Les types composés 9 3.1 Les tableaux.............................

Plus en détail

Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application

Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application Université de Provence Licence Math-Info Première Année V. Phan Luong Algorithmique et Programmation en Python Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application 1 Ordinateur Un

Plus en détail

Cours Informatique 1. Monsieur SADOUNI Salheddine

Cours Informatique 1. Monsieur SADOUNI Salheddine Cours Informatique 1 Chapitre 2 les Systèmes Informatique Monsieur SADOUNI Salheddine Un Système Informatique lesystème Informatique est composé de deux parties : -le Matériel : constitué de l unité centrale

Plus en détail

Informatique Générale

Informatique Générale Informatique Générale Guillaume Hutzler Laboratoire IBISC (Informatique Biologie Intégrative et Systèmes Complexes) guillaume.hutzler@ibisc.univ-evry.fr Cours Dokeos 625 http://www.ens.univ-evry.fr/modx/dokeos.html

Plus en détail

Programmation assembleur : aperçu

Programmation assembleur : aperçu Assembleur : Younès EL AMRANI. 1 Programmation assembleur : aperçu Programmation en assembleur : NASM Module M14 Semestre 4 Printemps 2010 Equipe pédagogique : Younès El Amrani, Abdelhakim El Imrani, Faissal

Plus en détail

Licence Sciences et Technologies Examen janvier 2010

Licence Sciences et Technologies Examen janvier 2010 Université de Provence Introduction à l Informatique Licence Sciences et Technologies Examen janvier 2010 Année 2009-10 Aucun document n est autorisé Les exercices peuvent être traités dans le désordre.

Plus en détail

Rappels d architecture

Rappels d architecture Assembleur Rappels d architecture Un ordinateur se compose principalement d un processeur, de mémoire. On y attache ensuite des périphériques, mais ils sont optionnels. données : disque dur, etc entrée

Plus en détail

Programmation système I Les entrées/sorties

Programmation système I Les entrées/sorties Programmation système I Les entrées/sorties DUT 1 re année Université de Marne La vallée Les entrées-sorties : E/O Entrées/Sorties : Opérations d échanges d informations dans un système informatique. Les

Plus en détail

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

INTRODUCTION A JAVA. Fichier en langage machine Exécutable INTRODUCTION A JAVA JAVA est un langage orienté-objet pur. Il ressemble beaucoup à C++ au niveau de la syntaxe. En revanche, ces deux langages sont très différents dans leur structure (organisation du

Plus en détail

Structure d un programme

Structure d un programme Architecture des ordinateurs Cours 6 Structure d un programme 3 décembre 2012 Archi 1/30 Programme en Assembleur Archi 2/30 Sections de données programme en assembleur = fichier texte (extension.asm) organisé

Plus en détail

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java Info0101 Intro. à l'algorithmique et à la programmation Cours 3 Le langage Java Pierre Delisle, Cyril Rabat et Christophe Jaillet Université de Reims Champagne-Ardenne Département de Mathématiques et Informatique

Plus en détail

1 Architecture du cœur ARM Cortex M3. Le cœur ARM Cortex M3 sera présenté en classe à partir des éléments suivants :

1 Architecture du cœur ARM Cortex M3. Le cœur ARM Cortex M3 sera présenté en classe à partir des éléments suivants : GIF-3002 SMI et Architecture du microprocesseur Ce cours discute de l impact du design du microprocesseur sur le système entier. Il présente d abord l architecture du cœur ARM Cortex M3. Ensuite, le cours

Plus en détail

DU BINAIRE AU MICROPROCESSEUR - D ANGELIS CIRCUITS CONFIGURABLES NOTION DE PROGRAMMATION

DU BINAIRE AU MICROPROCESSEUR - D ANGELIS CIRCUITS CONFIGURABLES NOTION DE PROGRAMMATION 145 NOTION DE PROGRAMMATION 1/ Complétons notre microprocesseur Nous avons, dans les leçons précédentes décrit un microprocesseur théorique, cependant il s inspire du 6800, premier microprocesseur conçu

Plus en détail

Architecture des ordinateurs TD1 - Portes logiques et premiers circuits

Architecture des ordinateurs TD1 - Portes logiques et premiers circuits Architecture des ordinateurs TD1 - Portes logiques et premiers circuits 1 Rappel : un peu de logique Exercice 1.1 Remplir la table de vérité suivante : a b a + b ab a + b ab a b 0 0 0 1 1 0 1 1 Exercice

Plus en détail

Introduction au langage C

Introduction au langage C Introduction au langage C Cours 1: Opérations de base et premier programme Alexis Lechervy Alexis Lechervy (UNICAEN) Introduction au langage C 1 / 23 Les premiers pas Sommaire 1 Les premiers pas 2 Les

Plus en détail

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux. UEO11 COURS/TD 1 Contenu du semestre Cours et TDs sont intégrés L objectif de ce cours équivalent a 6h de cours, 10h de TD et 8h de TP est le suivant : - initiation à l algorithmique - notions de bases

Plus en détail

Quelques éléments de compilation en C et makefiles

Quelques éléments de compilation en C et makefiles Quelques éléments de compilation en C et makefiles Guillaume Feuillade 1 Compiler un programme C Le principe de la compilation consiste à passer d un ensemble de fichiers de code à un programme exécutable

Plus en détail

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation impérative et structures de données simples Introduction au langage C Sandrine Blazy - 1ère année 24 octobre 2007 Cours d Algorithmique-Programmation

Plus en détail

Structure fonctionnelle d un SGBD

Structure fonctionnelle d un SGBD Fichiers et Disques Structure fonctionnelle d un SGBD Requetes Optimiseur de requetes Operateurs relationnels Methodes d acces Gestion de tampon Gestion de disque BD 1 Fichiers et Disques Lecture : Transfert

Plus en détail

Une version javascript sera disponible directement dans le cours prochainement.

Une version javascript sera disponible directement dans le cours prochainement. Author : Cédric Vanconingsloo Ce cours est principalement axé sur la compréhension du fonctionnement d'un ordinateur et l'étude du seul langage qu'il connaisse, le binaire. De ce fait, le cours est relativement

Plus en détail

Architecture de l ordinateur

Architecture de l ordinateur Architecture de l ordinateur Emmanuel Lazard Université Paris-Dauphine mars 2011 Computers are my forte! BRAZIL (Terry Gilliam, 1985) Ce document a initialement été publié sous forme de livre : Emmanuel

Plus en détail

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski cegielski@u-pec.fr

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski cegielski@u-pec.fr Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski cegielski@u-pec.fr Mars 2002 Pour Irène et Marie Legal Notice Copyright c 2002 Patrick Cégielski Université

Plus en détail

as Architecture des Systèmes d Information

as Architecture des Systèmes d Information Plan Plan Programmation - Introduction - Nicolas Malandain March 14, 2005 Introduction à Java 1 Introduction Présentation Caractéristiques Le langage Java 2 Types et Variables Types simples Types complexes

Plus en détail

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE QCM Remarque : - A une question correspond au moins 1 réponse juste - Cocher la ou les bonnes réponses Barème : - Une bonne réponse = +1 - Pas de réponse = 0

Plus en détail

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre 2009. Enrica.Duchi@liafa.jussieu.fr

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre 2009. Enrica.Duchi@liafa.jussieu.fr . Cours intensif Java 1er cours: de C à Java Septembre 2009 Enrica DUCHI LIAFA, Paris 7 Enrica.Duchi@liafa.jussieu.fr LANGAGES DE PROGRAMMATION Pour exécuter un algorithme sur un ordinateur il faut le

Plus en détail

ASR1 TD7 : Un microprocesseur RISC 16 bits

ASR1 TD7 : Un microprocesseur RISC 16 bits {Â Ö Ñ º ØÖ Ý,È ØÖ ºÄÓ Ù,Æ ÓÐ ºÎ ÝÖ Ø¹ ÖÚ ÐÐÓÒ} Ò ¹ÐÝÓÒº Ö ØØÔ»»Ô Ö Óº Ò ¹ÐÝÓÒº Ö» Ö Ñ º ØÖ Ý»¼ Ö½» ASR1 TD7 : Un microprocesseur RISC 16 bits 13, 20 et 27 novembre 2006 Présentation générale On choisit

Plus en détail

Représentation d un entier en base b

Représentation d un entier en base b Représentation d un entier en base b 13 octobre 2012 1 Prérequis Les bases de la programmation en langage sont supposées avoir été travaillées L écriture en base b d un entier est ainsi défini à partir

Plus en détail

Introduction à la Programmation Parallèle: MPI

Introduction à la Programmation Parallèle: MPI Introduction à la Programmation Parallèle: MPI Frédéric Gava et Gaétan Hains L.A.C.L Laboratoire d Algorithmique, Complexité et Logique Cours du M2 SSI option PSSR Plan 1 Modèle de programmation 2 3 4

Plus en détail

Arithmétique binaire. Chapitre. 5.1 Notions. 5.1.1 Bit. 5.1.2 Mot

Arithmétique binaire. Chapitre. 5.1 Notions. 5.1.1 Bit. 5.1.2 Mot Chapitre 5 Arithmétique binaire L es codes sont manipulés au quotidien sans qu on s en rende compte, et leur compréhension est quasi instinctive. Le seul fait de lire fait appel au codage alphabétique,

Plus en détail

UE C avancé cours 1: introduction et révisions

UE C avancé cours 1: introduction et révisions Introduction Types Structures de contrôle Exemple UE C avancé cours 1: introduction et révisions Jean-Lou Desbarbieux et Stéphane Doncieux UMPC 2004/2005 Introduction Types Structures de contrôle Exemple

Plus en détail

Initiation. àl algorithmique et à la programmation. en C

Initiation. àl algorithmique et à la programmation. en C Initiation àl algorithmique et à la programmation en C Initiation àl algorithmique et à la programmation en C Cours avec 129 exercices corrigés Illustration de couverture : alwyncooper - istock.com Dunod,

Plus en détail

Le langage C. Séance n 4

Le langage C. Séance n 4 Université Paris-Sud 11 Institut de Formation des Ingénieurs Remise à niveau INFORMATIQUE Année 2007-2008 Travaux pratiques d informatique Le langage C Séance n 4 But : Vous devez maîtriser à la fin de

Plus en détail

Licence ST Université Claude Bernard Lyon I LIF1 : Algorithmique et Programmation C Bases du langage C 1 Conclusion de la dernière fois Introduction de l algorithmique générale pour permettre de traiter

Plus en détail

Rappels Entrées -Sorties

Rappels Entrées -Sorties Fonctions printf et scanf Syntaxe: écriture, organisation Comportement Données hétérogènes? Gestion des erreurs des utilisateurs 17/11/2013 Cours du Langage C ibr_guelzim@yahoo.fr ibrahimguelzim.atspace.co.uk

Plus en détail

Programmation impérative

Programmation impérative Programmation impérative Cours 4 : Manipulation des fichiers en C Catalin Dima Organisation des fichiers Qqs caractéristiques des fichiers : Nom (+ extension). Chemin d accès absolu = suite des noms des

Plus en détail

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs Brefs rappels sur la pile et le tas (Stack / Heap) et les pointeurs (exemples en C) v1.11 - Olivier Carles 1 Pile et Tas Mémoire allouée de manière statique Mémoire Allouée Dynamiquement variables locales

Plus en détail

Argument-fetching dataflow machine de G.R. Gao et J.B. Dennis (McGill, 1988) = machine dataflow sans flux de données

Argument-fetching dataflow machine de G.R. Gao et J.B. Dennis (McGill, 1988) = machine dataflow sans flux de données EARTH et Threaded-C: Éléments clés du manuel de références de Threaded-C Bref historique de EARTH et Threaded-C Ancêtres de l architecture EARTH: Slide 1 Machine à flux de données statique de J.B. Dennis

Plus en détail

Codage d information. Codage d information : -Définition-

Codage d information. Codage d information : -Définition- Introduction Plan Systèmes de numération et Représentation des nombres Systèmes de numération Système de numération décimale Représentation dans une base b Représentation binaire, Octale et Hexadécimale

Plus en détail

Manuel de System Monitor

Manuel de System Monitor Chris Schlaeger John Tapsell Chris Schlaeger Tobias Koenig Traduction française : Yves Dessertine Traduction française : Philippe Guilbert Traduction française : Robin Guitton Relecture de la documentation

Plus en détail

Base de l'informatique. Généralité et Architecture Le système d'exploitation Les logiciels Le réseau et l'extérieur (WEB)

Base de l'informatique. Généralité et Architecture Le système d'exploitation Les logiciels Le réseau et l'extérieur (WEB) Base de l'informatique Généralité et Architecture Le système d'exploitation Les logiciels Le réseau et l'extérieur (WEB) Généralité Comment fonctionne un ordinateur? Nous définirons 3 couches Le matériel

Plus en détail

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing 3/4/27 Programmation Avancée Multimédia Multithreading Benoît Piranda Équipe SISAR Université de Marne La Vallée Besoin Programmes à traitements simultanés Réseau Réseau Afficher une animation en temps

Plus en détail

Cours 1: Java et les objets

Cours 1: Java et les objets Ressources Les interface homme-machine et le langage Java DUT première année Henri Garreta, Faculté des Sciences (Luminy) Cyril Pain-Barre & Sébastien Nedjar, IUT d Aix-Marseille (Aix) Cours 1: infodoc.iut.univ-aix.fr/~ihm/

Plus en détail

Programmation en C. École Nationale Supérieure de Techniques Avancées. Pierre-Alain Fouque et David Pointcheval

Programmation en C. École Nationale Supérieure de Techniques Avancées. Pierre-Alain Fouque et David Pointcheval École Nationale Supérieure de Techniques Avancées Programmation en C Pierre-Alain Fouque et David Pointcheval E-mail : Pierre-Alain.Fouque@ens.fr Web : http://www.di.ens.fr/~fouque/ Table des matières

Plus en détail

Cours 1 : Qu est-ce que la programmation?

Cours 1 : Qu est-ce que la programmation? 1/65 Introduction à la programmation Cours 1 : Qu est-ce que la programmation? Yann Régis-Gianas yrg@pps.univ-paris-diderot.fr Université Paris Diderot Paris 7 2/65 1. Sortez un appareil qui peut se rendre

Plus en détail

Architecture des ordinateurs Introduction à l informatique

Architecture des ordinateurs Introduction à l informatique Architecture des ordinateurs Introduction à l informatique 17 septembre 2004 1 2 3 4 5 6 Les interrupteurs... 0V 5V Ce sont des composants électroniques qui laissent pser un courant principal lorsque la

Plus en détail

Programmation système de commandes en C

Programmation système de commandes en C Programmation système de commandes en C Cours de Programmation système Tuyêt Trâm DANG NGOC Université de Cergy-Pontoise 2012 2013 Tuyêt Trâm DANG NGOC Programmation système de commandes

Plus en détail

La technologie Java Card TM

La technologie Java Card TM Présentation interne au CESTI La technologie Java Card TM sauveron@labri.u-bordeaux.fr http://dept-info.labri.u-bordeaux.fr/~sauveron 8 novembre 2002 Plan Qu est ce que Java Card? Historique Les avantages

Plus en détail

Algorithme. Table des matières

Algorithme. Table des matières 1 Algorithme Table des matières 1 Codage 2 1.1 Système binaire.............................. 2 1.2 La numérotation de position en base décimale............ 2 1.3 La numérotation de position en base binaire..............

Plus en détail

Métriques de performance pour les algorithmes et programmes parallèles

Métriques de performance pour les algorithmes et programmes parallèles Métriques de performance pour les algorithmes et programmes parallèles 11 18 nov. 2002 Cette section est basée tout d abord sur la référence suivante (manuel suggéré mais non obligatoire) : R. Miller and

Plus en détail

Plan du cours. Historique du langage http://www.oracle.com/technetwork/java/index.html. Nouveautés de Java 7

Plan du cours. Historique du langage http://www.oracle.com/technetwork/java/index.html. Nouveautés de Java 7 Université Lumière Lyon 2 Faculté de Sciences Economiques et Gestion KHARKIV National University of Economic Introduction au Langage Java Master Informatique 1 ère année Julien Velcin http://mediamining.univ-lyon2.fr/velcin

Plus en détail

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C Haute Ecole d Ingénierie et de Gestion Du Canton du Vaud MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C Programmation en mode simulation 1. DOCUMENTS DE RÉFÉRENCE...

Plus en détail

Architecture matérielle des systèmes informatiques

Architecture matérielle des systèmes informatiques Architecture matérielle des systèmes informatiques IDEC, Renens. Version novembre 2003. Avertissement : ce support de cours n est pas destiné à l autoformation et doit impérativement être complété par

Plus en détail

Algorithmique et Programmation, IMA

Algorithmique et Programmation, IMA Algorithmique et Programmation, IMA Cours 2 : C Premier Niveau / Algorithmique Université Lille 1 - Polytech Lille Notations, identificateurs Variables et Types de base Expressions Constantes Instructions

Plus en détail

LES TYPES DE DONNÉES DU LANGAGE PASCAL

LES TYPES DE DONNÉES DU LANGAGE PASCAL LES TYPES DE DONNÉES DU LANGAGE PASCAL 75 LES TYPES DE DONNÉES DU LANGAGE PASCAL CHAPITRE 4 OBJECTIFS PRÉSENTER LES NOTIONS D ÉTIQUETTE, DE CONS- TANTE ET DE IABLE DANS LE CONTEXTE DU LAN- GAGE PASCAL.

Plus en détail

Langages et Concepts de Programmation Introduction à la programmation en langage C

Langages et Concepts de Programmation Introduction à la programmation en langage C Langages et Concepts de Programmation Introduction à la programmation en langage C Cours 1A 2013-2014 Jean-Jacques Girardot, Marc Roelens girardot@emse.fr, roelens@emse.fr Septembre 2013 École Nationale

Plus en détail

V- Manipulations de nombres en binaire

V- Manipulations de nombres en binaire 1 V- Manipulations de nombres en binaire L ordinateur est constitué de milliards de transistors qui travaillent comme des interrupteurs électriques, soit ouverts soit fermés. Soit la ligne est activée,

Plus en détail

Architecture des ordinateurs

Architecture des ordinateurs Architecture des ordinateurs Cours 7 17 décembre 2012 Archi 1/1 Fonctions, suite et fin Archi 2/1 Rappel Forme générale d un sous-programme (fonction) : etiquette sousprogramme: push ebp ; empile la valeur

Plus en détail

Chapitre I Notions de base et outils de travail

Chapitre I Notions de base et outils de travail Chapitre I Notions de base et outils de travail Objectifs Connaître les principes fondateurs et l historique du langage Java S informer des principales caractéristiques du langage Java Connaître l environnement

Plus en détail

Chapitre 1 : La gestion dynamique de la mémoire

Chapitre 1 : La gestion dynamique de la mémoire Chapitre 1 : La gestion dynamique de la mémoire En langage C un programme comporte trois types de données : Statiques; Automatiques ; Dynamiques. Les données statiques occupent un emplacement parfaitement

Plus en détail

Représentation des Nombres

Représentation des Nombres Chapitre 5 Représentation des Nombres 5. Representation des entiers 5.. Principe des représentations en base b Base L entier écrit 344 correspond a 3 mille + 4 cent + dix + 4. Plus généralement a n a n...

Plus en détail

Introduction à MATLAB R

Introduction à MATLAB R Introduction à MATLAB R Romain Tavenard 10 septembre 2009 MATLAB R est un environnement de calcul numérique propriétaire orienté vers le calcul matriciel. Il se compose d un langage de programmation, d

Plus en détail

Logiciel de Base. I. Représentation des nombres

Logiciel de Base. I. Représentation des nombres Logiciel de Base (A1-06/07) Léon Mugwaneza ESIL/Dépt. Informatique (bureau A118) mugwaneza@univmed.fr I. Représentation des nombres Codage et représentation de l'information Information externe formats

Plus en détail

Partie 1. Professeur : Haouati Abdelali. CPGE Lycée Omar Ibn Lkhattab - Meknès www.haouati.com haouaticpge@gmail.com

Partie 1. Professeur : Haouati Abdelali. CPGE Lycée Omar Ibn Lkhattab - Meknès www.haouati.com haouaticpge@gmail.com Partie 1 Professeur : Haouati Abdelali CPGE Lycée Omar Ibn Lkhattab - Meknès www.haouati.com haouaticpge@gmail.com Partie I : Généralités et algorithmique de base 1. Environnement matériel et logiciel

Plus en détail

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu. Seance 2: Complétion du code de jeu. (durée max: 2h) Mot clé const et pointeurs: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu. Implémentez jeu_recupere_piece

Plus en détail

I00 Éléments d architecture

I00 Éléments d architecture I00 I Exemples d ordinateur Pour les informaticiens, différentes machines de la vie courante sont des ordinateurs : par exemple les ordinateurs portables, les ordinateurs fixes, mais aussi les supercalculateurs,

Plus en détail

Systèmes d exploitation

Systèmes d exploitation Systèmes d exploitation Virtualisation, Sécurité et Gestion des périphériques Gérard Padiou Département Informatique et Mathématiques appliquées ENSEEIHT Novembre 2009 Gérard Padiou Systèmes d exploitation

Plus en détail

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if Pierre Boudes 28 septembre 2011 This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike

Plus en détail

GPA770 Microélectronique appliquée Exercices série A

GPA770 Microélectronique appliquée Exercices série A GPA770 Microélectronique appliquée Exercices série A 1. Effectuez les calculs suivants sur des nombres binaires en complément à avec une représentation de 8 bits. Est-ce qu il y a débordement en complément

Plus en détail

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars 2014. http://homepages.laas.fr/matthieu/cours/java/java.pdf

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars 2014. http://homepages.laas.fr/matthieu/cours/java/java.pdf Introduction à Java Matthieu Herrb CNRS-LAAS http://homepages.laas.fr/matthieu/cours/java/java.pdf Mars 2014 Plan 1 Concepts 2 Éléments du langage 3 Classes et objets 4 Packages 2/28 Histoire et motivations

Plus en détail

Conversion d un entier. Méthode par soustraction

Conversion d un entier. Méthode par soustraction Conversion entre bases Pour passer d un nombre en base b à un nombre en base 10, on utilise l écriture polynomiale décrite précédemment. Pour passer d un nombre en base 10 à un nombre en base b, on peut

Plus en détail

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Structure d un programme et Compilation Notions de classe et d objet Syntaxe Cours1 Structure d un programme et Compilation Notions de classe et d objet Syntaxe POO 1 Programmation Orientée Objet Un ensemble d objet qui communiquent Pourquoi POO Conception abstraction sur les types

Plus en détail

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores INTRODUCTION AUX SYSTEMES D EXPLOITATION TD2 Exclusion mutuelle / Sémaphores Exclusion mutuelle / Sémaphores - 0.1 - S O M M A I R E 1. GENERALITES SUR LES SEMAPHORES... 1 1.1. PRESENTATION... 1 1.2. UN

Plus en détail

4. Utilisation d un SGBD : le langage SQL. 5. Normalisation

4. Utilisation d un SGBD : le langage SQL. 5. Normalisation Base de données S. Lèbre slebre@unistra.fr Université de Strasbourg, département d informatique. Présentation du module Contenu général Notion de bases de données Fondements / Conception Utilisation :

Plus en détail

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation : Algorithmique et programmation : STRUCTURES DE DONNÉES A. Structure et enregistrement 1) Définition et rôle des structures de données en programmation 1.1) Définition : En informatique, une structure de

Plus en détail

Chap III : Les tableaux

Chap III : Les tableaux Chap III : Les tableaux Dans cette partie, on va étudier quelques structures de données de base tels que : Les tableaux (vecteur et matrice) Les chaînes de caractères LA STRUCTURE DE TABLEAU Introduction

Plus en détail

Cours d Algorithmique et de Langage C 2005 - v 3.0

Cours d Algorithmique et de Langage C 2005 - v 3.0 Cours d Algorithmique et de Langage C 2005 - v 3.0 Bob CORDEAU cordeau@onera.fr Mesures Physiques IUT d Orsay 15 mai 2006 Avant-propos Avant-propos Ce cours en libre accès repose sur trois partis pris

Plus en détail

Sur un ordinateur portable ou un All-in-One tactile, la plupart des éléments mentionnés précédemment sont regroupés. 10) 11)

Sur un ordinateur portable ou un All-in-One tactile, la plupart des éléments mentionnés précédemment sont regroupés. 10) 11) 1/ Généralités : Un ordinateur est un ensemble non exhaustif d éléments qui sert à traiter des informations (documents de bureautique, méls, sons, vidéos, programmes ) sous forme numérique. Il est en général

Plus en détail

Partie 7 : Gestion de la mémoire

Partie 7 : Gestion de la mémoire INF3600+INF2610 Automne 2006 Partie 7 : Gestion de la mémoire Exercice 1 : Considérez un système disposant de 16 MO de mémoire physique réservée aux processus utilisateur. La mémoire est composée de cases

Plus en détail

Programmation en langage C

Programmation en langage C Programmation en langage C Anne CANTEAUT INRIA - projet CODES B.P. 105 78153 Le Chesnay Cedex Anne.Canteaut@inria.fr http://www-rocq.inria.fr/codes/anne.canteaut/cours C 2 Table des matières 3 Table des

Plus en détail

CQP 112 Introduc/on à la programma/on. Thème 2 : Architecture d un système informa/que. Département d informa/que

CQP 112 Introduc/on à la programma/on. Thème 2 : Architecture d un système informa/que. Département d informa/que CQP 112 Introduc/on à la programma/on Thème 2 : Architecture d un système informa/que Département d informa/que CQP 112 : Introduc/on à la programma/on Plan 1. Historique des ordinateurs 2. Composants

Plus en détail

Assembleur. Faculté I&C, André Maurer, Claude Petitpierre

Assembleur. Faculté I&C, André Maurer, Claude Petitpierre Assembleur Faculté I&C, André Maurer, Claude Petitpierre INTRODUCTION Logiciel utilisé Faculté I&C, André Maurer, Claude Petitpierre MEMOIRE Mémoire Faculté I&C, André Maurer, Claude Petitpierre Mémoire

Plus en détail

Conception de circuits numériques et architecture des ordinateurs

Conception de circuits numériques et architecture des ordinateurs Conception de circuits numériques et architecture des ordinateurs Frédéric Pétrot Année universitaire 2014-2015 Structure du cours C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 Codage des nombres en base 2, logique

Plus en détail

3IS - Système d'exploitation linux - Programmation système

3IS - Système d'exploitation linux - Programmation système 3IS - Système d'exploitation linux - Programmation système 2010 David Picard Contributions de : Arnaud Revel, Mickaël Maillard picard@ensea.fr Environnement Les programmes peuvent être exécutés dans des

Plus en détail

Exécutif temps réel Pierre-Yves Duval (cppm)

Exécutif temps réel Pierre-Yves Duval (cppm) 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

Plus en détail

Compression de Données - Algorithme de Huffman Document de Conception

Compression de Données - Algorithme de Huffman Document de Conception ROLLET Samuel SALLE Jennifer Compression de Données - Algorithme de Huffman Document de Conception Projet d'algorithmique et Structure des Données 1 SOMMAIRE 1. Domaine d application....4 1.1 Objectifs

Plus en détail

Cours 1 : La compilation

Cours 1 : La compilation /38 Interprétation des programmes Cours 1 : La compilation Yann Régis-Gianas yrg@pps.univ-paris-diderot.fr PPS - Université Denis Diderot Paris 7 2/38 Qu est-ce que la compilation? Vous avez tous déjà

Plus en détail

Travaux pratiques. Compression en codage de Huffman. 1.3. Organisation d un projet de programmation

Travaux pratiques. Compression en codage de Huffman. 1.3. Organisation d un projet de programmation Université de Savoie Module ETRS711 Travaux pratiques Compression en codage de Huffman 1. Organisation du projet 1.1. Objectifs Le but de ce projet est d'écrire un programme permettant de compresser des

Plus en détail