slides_memoire.pdf
Document Details
Related
- PCSII Depression/Anxiety/Strong Emotions 2024 Document
- A Concise History of the World: A New World of Connections (1500-1800)
- Human Bio Test PDF
- University of Santo Tomas Pre-Laboratory Discussion of LA No. 1 PDF
- Vertebrate Pest Management PDF
- Lg 5 International Environmental Laws, Treaties, Protocols, and Conventions
Full Transcript
Gestion de la mémoire d’un processus Exemple du langage C Gestion de la mémoire d’un processus 1 / 53 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Converg...
Gestion de la mémoire d’un processus Exemple du langage C Gestion de la mémoire d’un processus 1 / 53 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 2 / 53 Credits Ce cours de Marc de Falco Gestion de la mémoire d’un processus 3 / 53 Credits Ce cours de Marc de Falco Wikipedia Gestion de la mémoire d’un processus 3 / 53 Credits Ce cours de Marc de Falco Wikipedia Cette mise au point de Stackoverflow Gestion de la mémoire d’un processus 3 / 53 Credits Ce cours de Marc de Falco Wikipedia Cette mise au point de Stackoverflow Cette présentation YouTube de Gwendal le Vaillant Gestion de la mémoire d’un processus 3 / 53 Rappels sur la portée et la durée de vie 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 4 / 53 Rappels sur la portée et la durée de vie Portée La portée d’un identificateur i d’un programme P est la zone du texte de P dans laquelle on peut faire référence à i sans erreur à la compilation. Gestion de la mémoire d’un processus 5 / 53 Rappels sur la portée et la durée de vie Portée La portée d’un identificateur i d’un programme P est la zone du texte de P dans laquelle on peut faire référence à i sans erreur à la compilation. Exemple 1 int a = 1; 2 3 int f ( int x) 4 { 5 int y = x + a; 6 return y; 7 } 8 9 int g() 10 { 11 int z = 3; 12 return z + f(z) ; 13 } 14 Gestion de la mémoire d’un processus 5 / 53 Rappels sur la portée et la durée de vie Portée des identificateurs Dans l’exemple précédent : identificateur portée a 1-13 x 3-7 y 5-7 f 4-13 g 9-13 z 11-13 Gestion de la mémoire d’un processus 6 / 53 Rappels sur la portée et la durée de vie Portée des identificateurs Dans l’exemple précédent : identificateur portée a 1-13 x 3-7 y 5-7 f 4-13 g 9-13 z 11-13 Un identificateur peut être utilisé dès la ligne de sa déclaration : int x = x est en théorie possible mais pas recommandé. Gestion de la mémoire d’un processus 6 / 53 Rappels sur la portée et la durée de vie Portée des identificateurs Dans l’exemple précédent : identificateur portée a 1-13 x 3-7 y 5-7 f 4-13 g 9-13 z 11-13 Un identificateur peut être utilisé dès la ligne de sa déclaration : int x = x est en théorie possible mais pas recommandé. La portée des identificateurs ne désignant pas des fonctions inclut la ligne de déclaration (donc la portée de x démarre à L3). Gestion de la mémoire d’un processus 6 / 53 Rappels sur la portée et la durée de vie Portée des identificateurs Dans l’exemple précédent : identificateur portée a 1-13 x 3-7 y 5-7 f 4-13 g 9-13 z 11-13 Un identificateur peut être utilisé dès la ligne de sa déclaration : int x = x est en théorie possible mais pas recommandé. La portée des identificateurs ne désignant pas des fonctions inclut la ligne de déclaration (donc la portée de x démarre à L3). Pour les identificateurs de fonctions, le corps de la fonction est dans la portée pour permettre la récursion. Gestion de la mémoire d’un processus 6 / 53 Rappels sur la portée et la durée de vie Portée des identificateurs Dans l’exemple précédent : identificateur portée a 1-13 x 3-7 y 5-7 f 4-13 g 9-13 z 11-13 Un identificateur peut être utilisé dès la ligne de sa déclaration : int x = x est en théorie possible mais pas recommandé. La portée des identificateurs ne désignant pas des fonctions inclut la ligne de déclaration (donc la portée de x démarre à L3). Pour les identificateurs de fonctions, le corps de la fonction est dans la portée pour permettre la récursion. Portées des variables globales : toutes les lignes après la déclaration. Gestion de la mémoire d’un processus 6 / 53 Rappels sur la portée et la durée de vie Portée Variables locales de même nom Deux variables locales ont même nom : 1 int f () 2 { 3 int i = 3; 4 return i ; 5 } 6 7 int g() 8 { 9 int i = 5; 10 return i +1; 11 } 12 Gestion de la mémoire d’un processus 7 / 53 Rappels sur la portée et la durée de vie Portée Variables locales de même nom Deux variables locales ont même nom : 1 int f () 2 { 3 int i = 3; 4 return i ; 5 } 6 7 int g() 8 { 9 int i = 5; 10 return i +1; 11 } 12 Deux variables peuvent avoir le même nom mais dans ce cas elles doivent avoirs des portées différentes. Gestion de la mémoire d’un processus 7 / 53 Rappels sur la portée et la durée de vie Portée Variables locales de même nom Deux variables locales ont même nom : 1 int f () 2 { 3 int i = 3; 4 return i ; 5 } 6 7 int g() 8 { 9 int i = 5; 10 return i +1; 11 } 12 Deux variables peuvent avoir le même nom mais dans ce cas elles doivent avoirs des portées différentes. L’identificateur i a pour portée les lignes 3-5 et 9-11 mais il désigne deux variables qui ont des portées disjointes f.i et g.i. Gestion de la mémoire d’un processus 7 / 53 Rappels sur la portée et la durée de vie Portées imbriquées Soit la situation suivante : 1 { 2 int i =3; 3 { 4 int i =5; 5 printf (”%d”, i); // affiche 5 6 } 7 printf (”%d”,i); // affiche 3 8 } 9 Gestion de la mémoire d’un processus 8 / 53 Rappels sur la portée et la durée de vie Portées imbriquées Soit la situation suivante : 1 { 2 int i =3; 3 { 4 int i =5; 5 printf (”%d”, i); // affiche 5 6 } 7 printf (”%d”,i); // affiche 3 8 } 9 La portée de la première variable i contient celle de la seconde. Gestion de la mémoire d’un processus 8 / 53 Rappels sur la portée et la durée de vie Portées imbriquées Soit la situation suivante : 1 { 2 int i =3; 3 { 4 int i =5; 5 printf (”%d”, i); // affiche 5 6 } 7 printf (”%d”,i); // affiche 3 8 } 9 La portée de la première variable i contient celle de la seconde. Lors du premier printf, seule la seconde variable (celle valant 5) est visible, la première existe toujours (elle occupe un espace mémoire) mais elle n’est pas accessible. Gestion de la mémoire d’un processus 8 / 53 Rappels sur la portée et la durée de vie Portées imbriquées Soit la situation suivante : 1 { 2 int i =3; 3 { 4 int i =5; 5 printf (”%d”, i); // affiche 5 6 } 7 printf (”%d”,i); // affiche 3 8 } 9 La portée de la première variable i contient celle de la seconde. Lors du premier printf, seule la seconde variable (celle valant 5) est visible, la première existe toujours (elle occupe un espace mémoire) mais elle n’est pas accessible. Après la ligne 6, la seconde variable est détruite (elle n’occupe plus d’espace mémoire) et il ne reste plus que la première. Gestion de la mémoire d’un processus 8 / 53 Rappels sur la portée et la durée de vie Durée de vie La durée de vie d’une variable est la période de l’exécution du programme durant laquelle la variable est présente en mémoire. C’est une notion souvent (mais pas toujours) équivalente à celle de portée. Gestion de la mémoire d’un processus 9 / 53 Rappels sur la portée et la durée de vie Durée de vie La durée de vie d’une variable est la période de l’exécution du programme durant laquelle la variable est présente en mémoire. C’est une notion souvent (mais pas toujours) équivalente à celle de portée. Pour une variable globale, la durée de vie est l’intégralité du programme. Gestion de la mémoire d’un processus 9 / 53 Rappels sur la portée et la durée de vie Durée de vie La durée de vie d’une variable est la période de l’exécution du programme durant laquelle la variable est présente en mémoire. C’est une notion souvent (mais pas toujours) équivalente à celle de portée. Pour une variable globale, la durée de vie est l’intégralité du programme. La durée de vie d’une variable locale non statique est la portée de l’identificateur qui lui est associé. L’emplacement mémoire des données de cette variable est alloué au début sa portée et libéré à la fin automatiquement. Gestion de la mémoire d’un processus 9 / 53 Rappels sur la portée et la durée de vie Durée de vie La durée de vie d’une variable est la période de l’exécution du programme durant laquelle la variable est présente en mémoire. C’est une notion souvent (mais pas toujours) équivalente à celle de portée. Pour une variable globale, la durée de vie est l’intégralité du programme. La durée de vie d’une variable locale non statique est la portée de l’identificateur qui lui est associé. L’emplacement mémoire des données de cette variable est alloué au début sa portée et libéré à la fin automatiquement. Les variables locales (déclarées comme static ) ont une durée de vie supérieure à leur portée. Gestion de la mémoire d’un processus 9 / 53 Rappels sur la portée et la durée de vie Durée de vie La durée de vie d’une variable est la période de l’exécution du programme durant laquelle la variable est présente en mémoire. C’est une notion souvent (mais pas toujours) équivalente à celle de portée. Pour une variable globale, la durée de vie est l’intégralité du programme. La durée de vie d’une variable locale non statique est la portée de l’identificateur qui lui est associé. L’emplacement mémoire des données de cette variable est alloué au début sa portée et libéré à la fin automatiquement. Les variables locales (déclarées comme static ) ont une durée de vie supérieure à leur portée. Les variables locales allouées dynamiquement (par malloc) peuvent exister en dehors du bloc où elles ont été déclarées : leur durée de vie peut être supérieure à leur portée (si elles ne sont pas libérées dans le bloc où a lieu l’allocation). Gestion de la mémoire d’un processus 9 / 53 Organisation de la mémoire 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 10 / 53 Organisation de la mémoire Généralités 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 11 / 53 Organisation de la mémoire Généralités Les zones de la mémoire virtuelle d’un processus Chaque fois qu’un programme C est exécuté, de la mémoire est allouée dans la RAM pour l’exécution. Cette mémoire est utilisée pour stocker le code machine, les variables du programme, les constantes etc... Gestion de la mémoire d’un processus 12 / 53 Organisation de la mémoire Généralités Les zones de la mémoire virtuelle d’un processus Chaque fois qu’un programme C est exécuté, de la mémoire est allouée dans la RAM pour l’exécution. Cette mémoire est utilisée pour stocker le code machine, les variables du programme, les constantes etc... Les différents types de variables : locales, globales, statiques sont enregistrées dans différentes zones (ou segments de mémoire) de la mémoire virtuelle du processus (i.e. programme en cours d’exécution). Gestion de la mémoire d’un processus 12 / 53 Organisation de la mémoire Généralités Les zones de la mémoire virtuelle d’un processus Chaque fois qu’un programme C est exécuté, de la mémoire est allouée dans la RAM pour l’exécution. Cette mémoire est utilisée pour stocker le code machine, les variables du programme, les constantes etc... Les différents types de variables : locales, globales, statiques sont enregistrées dans différentes zones (ou segments de mémoire) de la mémoire virtuelle du processus (i.e. programme en cours d’exécution). Les 4 segments de mémoire pour un programme sont : le segment de code (ou de texte), le segment de données (lui-même divisé en C en le segment des variables non initialisées, celui des variables initialisées, celui des constantes -en lecture seule-) le segment de pile et enfin le segment de tas. Gestion de la mémoire d’un processus 12 / 53 Organisation de la mémoire Généralités Retour sur la RAM La mémoire d’un ordinateur contient à la fois les programmes à exécuter (les différentes instructions) et les données que ces programme doivent manipuler. Gestion de la mémoire d’un processus 13 / 53 Organisation de la mémoire Généralités Retour sur la RAM La mémoire d’un ordinateur contient à la fois les programmes à exécuter (les différentes instructions) et les données que ces programme doivent manipuler. Les octets stockés dans la mémoire ne sont pas étiquetés comme étant du code ou des données. Gestion de la mémoire d’un processus 13 / 53 Organisation de la mémoire Généralités Retour sur la RAM La mémoire d’un ordinateur contient à la fois les programmes à exécuter (les différentes instructions) et les données que ces programme doivent manipuler. Les octets stockés dans la mémoire ne sont pas étiquetés comme étant du code ou des données. C’est le contexte qui détermine si on les considère comme du code (à exécuter) ou des données (à manipuler). Gestion de la mémoire d’un processus 13 / 53 Organisation de la mémoire Généralités Retour sur la RAM La mémoire d’un ordinateur contient à la fois les programmes à exécuter (les différentes instructions) et les données que ces programme doivent manipuler. Les octets stockés dans la mémoire ne sont pas étiquetés comme étant du code ou des données. C’est le contexte qui détermine si on les considère comme du code (à exécuter) ou des données (à manipuler). Grossièrement, la mémoire peut-être vue comme un tableau de cases mémoires élémentaires appelées mots mémoires. La taille de ces mots varie selon les machines de 8 )à 64 bits. Gestion de la mémoire d’un processus 13 / 53 Organisation de la mémoire Généralités Retour sur la RAM La mémoire d’un ordinateur contient à la fois les programmes à exécuter (les différentes instructions) et les données que ces programme doivent manipuler. Les octets stockés dans la mémoire ne sont pas étiquetés comme étant du code ou des données. C’est le contexte qui détermine si on les considère comme du code (à exécuter) ou des données (à manipuler). Grossièrement, la mémoire peut-être vue comme un tableau de cases mémoires élémentaires appelées mots mémoires. La taille de ces mots varie selon les machines de 8 )à 64 bits. Traditionnellement, on représente ce tableau mémoire verticalement avec les premières adresses de la mémoire en bas du schéma. Gestion de la mémoire d’un processus 13 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Les données sont réparties en trois segments : Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Les données sont réparties en trois segments : Les constantes peuvent se trouver dans le segment de texte ou parfois dans le segment.rodata. Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Les données sont réparties en trois segments : Les constantes peuvent se trouver dans le segment de texte ou parfois dans le segment.rodata. les segments.bss ou.data contiennent les variables globales ou statiques. Selon que les variables globales sont initialisées ou non non, elle vont dans l’un ou l’autre de ces segments de données. Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Les données sont réparties en trois segments : Les constantes peuvent se trouver dans le segment de texte ou parfois dans le segment.rodata. les segments.bss ou.data contiennent les variables globales ou statiques. Selon que les variables globales sont initialisées ou non non, elle vont dans l’un ou l’autre de ces segments de données. Les tailles de ces zones sont fixes car connues à la compilation. Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Les données sont réparties en trois segments : Les constantes peuvent se trouver dans le segment de texte ou parfois dans le segment.rodata. les segments.bss ou.data contiennent les variables globales ou statiques. Selon que les variables globales sont initialisées ou non non, elle vont dans l’un ou l’autre de ces segments de données. Les tailles de ces zones sont fixes car connues à la compilation. Le segment de pile contient l’espace mémoire alloué dynamiquement par un programme sans intervention explicite du programmeur. La pile est utilisée au moment de l’appel de fonction pour stocker paramètres et variables locales de ces fonctions. Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Découpage en segments Schématiquement, l’espace mémoire d’un processus est découpé en 4 parties appelées segments de mémoire Le segment de code contient les instructions du programme en langage machine. Les données sont réparties en trois segments : Les constantes peuvent se trouver dans le segment de texte ou parfois dans le segment.rodata. les segments.bss ou.data contiennent les variables globales ou statiques. Selon que les variables globales sont initialisées ou non non, elle vont dans l’un ou l’autre de ces segments de données. Les tailles de ces zones sont fixes car connues à la compilation. Le segment de pile contient l’espace mémoire alloué dynamiquement par un programme sans intervention explicite du programmeur. La pile est utilisée au moment de l’appel de fonction pour stocker paramètres et variables locales de ces fonctions. Le segment de tas contient l’espace mémoire alloué dynamiquement par un programme avec intervention explicite du programmeur Gestion de la mémoire d’un processus 14 / 53 Organisation de la mémoire Généralités Une bonne explication se trouve sur cette page Linkedln notamment pour les stacks frame Gestion de la mémoire d’un processus 15 / 53 Organisation de la mémoire Généralités Organisation de la mémoire en C♥ stack (pile) Les segments de tas et de pile sont souvent représentés progressant l’un vers l’autre : la pile avec des adresses heap (tas) décroissantes, le tas avec des données non initialisées adresses croissantes... (.bss) ou l’inverse ! données initialisées segments de données La taille des segments (.data).text,.rodata,.data et.bss est déterminée à la constantes (.rodata) compilation et ne change code exécutable (.text) pas à l’exécution. Gestion de la mémoire d’un processus 16 / 53 Organisation de la mémoire Généralités Accès aux mots de la mémoire En première approximation, la mémoire d’un ordinateur peut être vue comme un tableau de case mémoires élémentaires appelées mots mémoires et de taille entre 8 et 64 bits. L’adresse d’un mot mémoire s’obtient en additionnant l’adresse du début du segment memoire où il se trouve (code, données, tas, pile), qu’on appelle base, et la position de ce mot dans le segment, qu’on appelle déplacement. Informatique, cours et exercices corrigés, MPI/MPII Gestion de la mémoire d’un processus 17 / 53 Organisation de la mémoire Généralités Accès aux mots de la mémoire En première approximation, la mémoire d’un ordinateur peut être vue comme un tableau de case mémoires élémentaires appelées mots mémoires et de taille entre 8 et 64 bits. L’adresse d’un mot mémoire s’obtient en additionnant l’adresse du début du segment memoire où il se trouve (code, données, tas, pile), qu’on appelle base, et la position de ce mot dans le segment, qu’on appelle déplacement. Cet adressage dit relatif à une base, permet à un programme de s’exécuter de la même façon dans n’importe quelle partie de la mémoire d’un ordinateur : pas besoin de changer les instructions d’accès en lecture ou écriture, l’OS fera automatiquement les translations nécessaires. Informatique, cours et exercices corrigés, MPI/MPII Gestion de la mémoire d’un processus 17 / 53 Organisation de la mémoire Segments de code et de données 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 18 / 53 Organisation de la mémoire Segments de code et de données Le segment de code Appelé aussi segment de texte. C’est la zone de la mémoire du processus qui contient les instructions à exécuter. Gestion de la mémoire d’un processus 19 / 53 Organisation de la mémoire Segments de code et de données Le segment de code Appelé aussi segment de texte. C’est la zone de la mémoire du processus qui contient les instructions à exécuter. Souvent en lecture seule pour éviter d’être accidentellement réécrit. Gestion de la mémoire d’un processus 19 / 53 Organisation de la mémoire Segments de code et de données Le segment de code Appelé aussi segment de texte. C’est la zone de la mémoire du processus qui contient les instructions à exécuter. Souvent en lecture seule pour éviter d’être accidentellement réécrit. Placé dans les adresses inférieures pour que des dépassement de pile ou de tas n’écrivent pas dedans. Gestion de la mémoire d’un processus 19 / 53 Organisation de la mémoire Segments de code et de données Le segment de code Appelé aussi segment de texte. C’est la zone de la mémoire du processus qui contient les instructions à exécuter. Souvent en lecture seule pour éviter d’être accidentellement réécrit. Placé dans les adresses inférieures pour que des dépassement de pile ou de tas n’écrivent pas dedans. Certaines implémentation de C y placent aussi les chaı̂nes de caractères en lecture seule comme le Hello de printf("Hello"). Gestion de la mémoire d’un processus 19 / 53 Organisation de la mémoire Segments de code et de données Le segment de code Appelé aussi segment de texte. C’est la zone de la mémoire du processus qui contient les instructions à exécuter. Souvent en lecture seule pour éviter d’être accidentellement réécrit. Placé dans les adresses inférieures pour que des dépassement de pile ou de tas n’écrivent pas dedans. Certaines implémentation de C y placent aussi les chaı̂nes de caractères en lecture seule comme le Hello de printf("Hello"). Le segment rodata contient les constantes (et peut contenir les constantes chaı̂nes). 1 // va en segment rodata 2 const int x = 3; 3 Gestion de la mémoire d’un processus 19 / 53 Organisation de la mémoire Segments de code et de données Les segment de données.data et.bss Souvent représentés en-dessous du tas. En tout cas jamais entre pile et tas. Segment de données initialisées ou segment.data. Contient les variables initialisées globales (y compris des pointeurs) et les variables locales statiques initialisées. Gestion de la mémoire d’un processus 20 / 53 Organisation de la mémoire Segments de code et de données Les segment de données.data et.bss Souvent représentés en-dessous du tas. En tout cas jamais entre pile et tas. Segment de données initialisées ou segment.data. Contient les variables initialisées globales (y compris des pointeurs) et les variables locales statiques initialisées. Segment des données non initialisées ou segment.bss (pour block starting symbol ) contient les variables globales et variables locales statiques non initialisées OU les variables ou pointeurs initialisés à 0 ou NULL. Gestion de la mémoire d’un processus 20 / 53 Organisation de la mémoire Segments de code et de données Exemple 1 char s [] = ”hello world”; 2 int debug=1; 3 const char∗ string = ”hello world”;// ptr sur type const char 4 float x; 5 6 int main(){ 7 return 0; 8 } 9 La chaı̂ne de caractères s comme la variable entière debug sont dans le segment de données (.data). Gestion de la mémoire d’un processus 21 / 53 Organisation de la mémoire Segments de code et de données Exemple 1 char s [] = ”hello world”; 2 int debug=1; 3 const char∗ string = ”hello world”;// ptr sur type const char 4 float x; 5 6 int main(){ 7 return 0; 8 } 9 La chaı̂ne de caractères s comme la variable entière debug sont dans le segment de données (.data). Le pointeur de caractère string est aussi dans le segment de données mais la chaı̂ne de caractères littérale "hello world" est dans la zone en lecture seule (.rodata). Gestion de la mémoire d’un processus 21 / 53 Organisation de la mémoire Segments de code et de données Exemple 1 char s [] = ”hello world”; 2 int debug=1; 3 const char∗ string = ”hello world”;// ptr sur type const char 4 float x; 5 6 int main(){ 7 return 0; 8 } 9 La chaı̂ne de caractères s comme la variable entière debug sont dans le segment de données (.data). Le pointeur de caractère string est aussi dans le segment de données mais la chaı̂ne de caractères littérale "hello world" est dans la zone en lecture seule (.rodata). La variable globale x non initialisée est dans le segment.bss. Gestion de la mémoire d’un processus 21 / 53 Organisation de la mémoire Segments de code et de données Exemple 1 char s [] = ”hello world”; 2 int debug=1; 3 const char∗ string = ”hello world”;// ptr sur type const char 4 float x; 5 6 int main(){ 7 return 0; 8 } 9 La chaı̂ne de caractères s comme la variable entière debug sont dans le segment de données (.data). Le pointeur de caractère string est aussi dans le segment de données mais la chaı̂ne de caractères littérale "hello world" est dans la zone en lecture seule (.rodata). La variable globale x non initialisée est dans le segment.bss. La fonction main est dans le segment de texte.text Gestion de la mémoire d’un processus 21 / 53 Organisation de la mémoire Segments de code et de données BSS : compléments Le segment BSS ne prend aucune place dans le fichier objet. C’est pour cela qu’on ne trouve pas les variables stockées dans le BSS avec un utilitaire comme objdump. Gestion de la mémoire d’un processus 22 / 53 Organisation de la mémoire Segments de code et de données BSS : compléments Le segment BSS ne prend aucune place dans le fichier objet. C’est pour cela qu’on ne trouve pas les variables stockées dans le BSS avec un utilitaire comme objdump. C’est le chargeur de programme qui, au moment du chargement, initialise la mémoire allouée pour le segment BSS. Gestion de la mémoire d’un processus 22 / 53 Organisation de la mémoire Segments de code et de données BSS : compléments Le segment BSS ne prend aucune place dans le fichier objet. C’est pour cela qu’on ne trouve pas les variables stockées dans le BSS avec un utilitaire comme objdump. C’est le chargeur de programme qui, au moment du chargement, initialise la mémoire allouée pour le segment BSS. L’information sur la place que prendra le segment BSS à l’exécution est, elle, stockée dans le fichier objet. Gestion de la mémoire d’un processus 22 / 53 Organisation de la mémoire Pile 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 23 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; les arguments passés à la fonction ; Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; les arguments passés à la fonction ; un espace de stockage pour la valeur de retour ; Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; les arguments passés à la fonction ; un espace de stockage pour la valeur de retour ; l’adresse (dite de retour) d’où on a appelé la fonction. Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; les arguments passés à la fonction ; un espace de stockage pour la valeur de retour ; l’adresse (dite de retour) d’où on a appelé la fonction. Les variables stockées dans la pile pour une fonction sont détruites dès que l’exécution de la fonction termine. Allocation et libération sont automatiques. Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; les arguments passés à la fonction ; un espace de stockage pour la valeur de retour ; l’adresse (dite de retour) d’où on a appelé la fonction. Les variables stockées dans la pile pour une fonction sont détruites dès que l’exécution de la fonction termine. Allocation et libération sont automatiques. Il y a une limite (8 Mio sous Linux) à la taille de la pile qui dépend de plusieurs facteurs comme le langage de programmation, de l’OS, du traitement multithread et de la quantité de RAM disponible. Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile La pile Le segment de pile est utilisé pour stocker les arguments ou les variables qui sont créées dans une fonction. On y empile les stackframe qui contiennent : les variables locales à la fonction considérée (y compris les pointeurs locaux) ; les arguments passés à la fonction ; un espace de stockage pour la valeur de retour ; l’adresse (dite de retour) d’où on a appelé la fonction. Les variables stockées dans la pile pour une fonction sont détruites dès que l’exécution de la fonction termine. Allocation et libération sont automatiques. Il y a une limite (8 Mio sous Linux) à la taille de la pile qui dépend de plusieurs facteurs comme le langage de programmation, de l’OS, du traitement multithread et de la quantité de RAM disponible. Alors que les noms des variables globales sont bien connus dans le segment de données, les noms des variables locales et des arguments ne sont pas des informations stockées dans la pile. Gestion de la mémoire d’un processus 24 / 53 Organisation de la mémoire Pile Stack overflow Un dépassement de pile (d’exécution) (pour stack overflow) est un bug causé par un processus qui, lors de l’écriture dans la pile d’exécution, écrit à l’extérieur de l’espace alloué à la pile, écrasant ainsi des informations nécessaires au processus. Gestion de la mémoire d’un processus 25 / 53 Organisation de la mémoire Pile Stack overflow Un dépassement de pile (d’exécution) (pour stack overflow) est un bug causé par un processus qui, lors de l’écriture dans la pile d’exécution, écrit à l’extérieur de l’espace alloué à la pile, écrasant ainsi des informations nécessaires au processus. Récursivité infinie 1 void a() 2 { 3 a() ; // nb appels imbriqués non borné 4 } 5 6 int main() 7 { 8 a() ;// trop gd nb appels imbriqués 9 return 0; 10 }// Erreur de segmentation (core dumped) 11 La pile devient pleine et une erreur de dépassement de pile est soulevée. Gestion de la mémoire d’un processus 25 / 53 Organisation de la mémoire Pile Stack frame Chaque fonction pousse dans la pile des informations comme la valeur des arguments, la valeur des variables locales et l’adresse de retour Gestion de la mémoire d’un processus 26 / 53 Organisation de la mémoire Pile Stack frame Chaque fonction pousse dans la pile des informations comme la valeur des arguments, la valeur des variables locales et l’adresse de retour Cet ensemble d’informations associées à la fonction est une trame de pile ( pour stack frame en anglais). Gestion de la mémoire d’un processus 26 / 53 Organisation de la mémoire Pile Stack frame Chaque fonction pousse dans la pile des informations comme la valeur des arguments, la valeur des variables locales et l’adresse de retour Cet ensemble d’informations associées à la fonction est une trame de pile ( pour stack frame en anglais). Une stack frame contient au moins un espace pour stocker la valeur retournée par la fonction. Gestion de la mémoire d’un processus 26 / 53 Organisation de la mémoire Pile Stack frame Chaque fonction pousse dans la pile des informations comme la valeur des arguments, la valeur des variables locales et l’adresse de retour Cet ensemble d’informations associées à la fonction est une trame de pile ( pour stack frame en anglais). Une stack frame contient au moins un espace pour stocker la valeur retournée par la fonction. La pile est donc organisée par empilement/dépilement de stack frame. Gestion de la mémoire d’un processus 26 / 53 Organisation de la mémoire Pile Stack frame Chaque fonction pousse dans la pile des informations comme la valeur des arguments, la valeur des variables locales et l’adresse de retour Cet ensemble d’informations associées à la fonction est une trame de pile ( pour stack frame en anglais). Une stack frame contient au moins un espace pour stocker la valeur retournée par la fonction. La pile est donc organisée par empilement/dépilement de stack frame. Un registre du processeur, le pointeur de pile (Stack Pointer), pointe sur le sommet de la pile et est mis à jour après chaque empilement. Gestion de la mémoire d’un processus 26 / 53 Organisation de la mémoire Pile Stack frame Chaque fonction pousse dans la pile des informations comme la valeur des arguments, la valeur des variables locales et l’adresse de retour Cet ensemble d’informations associées à la fonction est une trame de pile ( pour stack frame en anglais). Une stack frame contient au moins un espace pour stocker la valeur retournée par la fonction. La pile est donc organisée par empilement/dépilement de stack frame. Un registre du processeur, le pointeur de pile (Stack Pointer), pointe sur le sommet de la pile et est mis à jour après chaque empilement. Dans chaque stack frame, les informations sont elles-mêmes stockées sous forme de pile. Il y a donc aussi un pointeur de trame (Frame Pointer) qui pointe sur le sommet de la trame. Gestion de la mémoire d’un processus 26 / 53 Organisation de la mémoire Pile Stack A la base de la pile, on trouve la stack frame de main avec ses arguments et variables. main 1 void f2( int c){ adresse de retour 2 return c+3; stack pointer3 } var. locales : z 4 paramètres 5 6 void f1( int x){ 7 int a = 10;// local 8 return f2(a+x); // adresse retour 9 } 10 11 12 void main(){ 13 int z = f1(3); 14 } Gestion de la mémoire d’un processus 27 / 53 Organisation de la mémoire Pile Stack A l’appel f1(3) , une autre frame stack est ajoutée à la pile. main 1 void f2( int c){ ret. 2 return c+3; 3 } var. locales 4 paramètres 5... 6 void f1( int x){ 7 int a = 10;// local f1 8 return f2(a+x); // adresse ret. retour a : 10 stack pointer9 } 10 x :3 11... 12 void main(){ 13 int z = f1(3); 14 } Gestion de la mémoire d’un processus 28 / 53 Organisation de la mémoire Pile Stack : appel f2(10+3) main L’appel f2(a+x) ret. var. locales entraı̂ne l’ajout de la stack frame paramètres 1 void f2( int c){ de f2 return c+3;... 2 3 } f1 4 5 ret. 6 void f1( int x){ a : 10 7 int a = 10;// local x :3 Libre 8 return f2(a+x); // adresse... retour 9 } f2 10 ret. 13+3 11 stack pointer 12 void main(){ c : 13 13 int z = f1(3);... 14 } Gestion de la mémoire d’un processus 29 / 53 Organisation de la mémoire Pile Dépilement Après l’exécution de f2(a+x) , le programme dépile la stack frame de f2 et revient à l’instruction écrite en L4. Gestion de la mémoire d’un processus 30 / 53 Organisation de la mémoire Pile Dépilement Après l’exécution de f2(a+x) , le programme dépile la stack frame de f2 et revient à l’instruction écrite en L4. L’exécution de f1(3) termine et le programme revient en L12. Gestion de la mémoire d’un processus 30 / 53 Organisation de la mémoire Pile Dépilement de la trame de f2 main 1 void f2( int c){ ret. 2 return c+3; 3 } var. locales 4 paramètres 5... 6 void f1( int x){ 7 int a = 10;// local f1 Libre 8 return f2(a+x); // adresse ret. 16 retour a : 10 stack pointer9 } 10 x :3 11... 12 void main(){ 13 int z = f1(3); 14 } Gestion de la mémoire d’un processus 31 / 53 Organisation de la mémoire Pile Dépilement de la trame de f1 main 1 void f2( int c){ adresse de retour 2 return c+3; stack pointer3 } z : 16 4 paramètres 5 6 void f1( int x){ 7 int a = 10;// local 8 return f2(a+x); // adresse retour 9 } 10 11 12 void main(){ 13 int z = f1(3); 14 } Gestion de la mémoire d’un processus 32 / 53 Organisation de la mémoire Tas 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 33 / 53 Organisation de la mémoire Tas Le segment de tas Ce segment est conçu pour supporter l’allocation dynamique de mémoire typiquement par malloc, calloc, realloc. Gestion de la mémoire d’un processus 34 / 53 Organisation de la mémoire Tas Le segment de tas Ce segment est conçu pour supporter l’allocation dynamique de mémoire typiquement par malloc, calloc, realloc. La taille des variables sur le tas n’est en principe pas limitée sinon par la taille de la RAM. Gestion de la mémoire d’un processus 34 / 53 Organisation de la mémoire Tas Le segment de tas Ce segment est conçu pour supporter l’allocation dynamique de mémoire typiquement par malloc, calloc, realloc. La taille des variables sur le tas n’est en principe pas limitée sinon par la taille de la RAM. Les variables créées sur le tas sont accessible de n’importe où dans le programme : leur portée est globale. Gestion de la mémoire d’un processus 34 / 53 Organisation de la mémoire Tas Le segment de tas Ce segment est conçu pour supporter l’allocation dynamique de mémoire typiquement par malloc, calloc, realloc. La taille des variables sur le tas n’est en principe pas limitée sinon par la taille de la RAM. Les variables créées sur le tas sont accessible de n’importe où dans le programme : leur portée est globale. Les variables sur le tas peuvent être redimensionnées. Gestion de la mémoire d’un processus 34 / 53 Organisation de la mémoire Tas Le segment de tas Ce segment est conçu pour supporter l’allocation dynamique de mémoire typiquement par malloc, calloc, realloc. La taille des variables sur le tas n’est en principe pas limitée sinon par la taille de la RAM. Les variables créées sur le tas sont accessible de n’importe où dans le programme : leur portée est globale. Les variables sur le tas peuvent être redimensionnées. Tout emplacement alloué doit être libéré avec free. Une règle simple : celui qui alloue est celui qui libère. Gestion de la mémoire d’un processus 34 / 53 Organisation de la mémoire Tas Erreurs de libération Dans ce programme, on veut libérer un objet (l’adresse de a ) qui n’est pas sur le tas. 1 #include 2 3 int main()//exemple marc de falco 4 { 5 int a; 6 free (&a); 7 return 0; 8 } A la compilation avec -Wall , on obtient un avertissement attempt to free a non-heap object ’a’. A l’exécution, on obtient une erreur munmap_chunk (): invalid pointer Abandon ( core dumped ) Gestion de la mémoire d’un processus 35 / 53 Organisation de la mémoire Tas Erreurs de libération Dans le programme suivant, pas d’erreur de compilation car on appelle free avec un objet qui est sur le tas. Cependant cet objet n’a pas été explicitement alloué par un malloc. On obtient une erreur d’exécution. 1 #include 2 3 int main()// exemple marc de falco 4 { 5 char ∗a = malloc(2); 6 free (&(a)) ; 7 return 0; 8 } free (): invalid pointer Abandon ( core dumped ) Gestion de la mémoire d’un processus 36 / 53 Organisation de la mémoire Tas Double libération On libère deux fois le même objet qui n’a fait l’objet que d’une allocation. On obtient une erreur de double libération. 1 #include 2 3 int main()// exemple marc de falco 4 { 5 char ∗a = malloc(2); 6 free (a); 7 free (a);// double lib é ration 8 return 0; 9 } free (): double free detected in tcache 2 Abandon ( core dumped ) Gestion de la mémoire d’un processus 37 / 53 Organisation de la mémoire Convergence 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 38 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses La pile est souvent située dans la partie haute de la mémoire (les adresses élevées). Les adresses utilisées sont alors décroissantes Gestion de la mémoire d’un processus 39 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses La pile est souvent située dans la partie haute de la mémoire (les adresses élevées). Les adresses utilisées sont alors décroissantes Un registre du processeur, le pointeur de pile (stack pointer) suit la progression du sommet de la pile. Il est mis à jour chaque fois qu’une nouvelle valeur est empilée (donc à chaque nouvel appel de fonction). Gestion de la mémoire d’un processus 39 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses La pile est souvent située dans la partie haute de la mémoire (les adresses élevées). Les adresses utilisées sont alors décroissantes Un registre du processeur, le pointeur de pile (stack pointer) suit la progression du sommet de la pile. Il est mis à jour chaque fois qu’une nouvelle valeur est empilée (donc à chaque nouvel appel de fonction). Le tas démarre souvent à la fin du segment BSS (les variables globales non initialisées). Et les adresses utilisées successives grossissent alors. Gestion de la mémoire d’un processus 39 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses La pile est souvent située dans la partie haute de la mémoire (les adresses élevées). Les adresses utilisées sont alors décroissantes Un registre du processeur, le pointeur de pile (stack pointer) suit la progression du sommet de la pile. Il est mis à jour chaque fois qu’une nouvelle valeur est empilée (donc à chaque nouvel appel de fonction). Le tas démarre souvent à la fin du segment BSS (les variables globales non initialisées). Et les adresses utilisées successives grossissent alors. Suivant les implémentations, les adresses du tas peuvent décroı̂tre et celles de la pile croı̂tre. Gestion de la mémoire d’un processus 39 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses La pile est souvent située dans la partie haute de la mémoire (les adresses élevées). Les adresses utilisées sont alors décroissantes Un registre du processeur, le pointeur de pile (stack pointer) suit la progression du sommet de la pile. Il est mis à jour chaque fois qu’une nouvelle valeur est empilée (donc à chaque nouvel appel de fonction). Le tas démarre souvent à la fin du segment BSS (les variables globales non initialisées). Et les adresses utilisées successives grossissent alors. Suivant les implémentations, les adresses du tas peuvent décroı̂tre et celles de la pile croı̂tre. Quoi qu’il en soit, traditionnellement, les adresses d’une zone sont présentées comme progressant vers l’autre zone. Gestion de la mémoire d’un processus 39 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses La pile est souvent située dans la partie haute de la mémoire (les adresses élevées). Les adresses utilisées sont alors décroissantes Un registre du processeur, le pointeur de pile (stack pointer) suit la progression du sommet de la pile. Il est mis à jour chaque fois qu’une nouvelle valeur est empilée (donc à chaque nouvel appel de fonction). Le tas démarre souvent à la fin du segment BSS (les variables globales non initialisées). Et les adresses utilisées successives grossissent alors. Suivant les implémentations, les adresses du tas peuvent décroı̂tre et celles de la pile croı̂tre. Quoi qu’il en soit, traditionnellement, les adresses d’une zone sont présentées comme progressant vers l’autre zone. Quand les pointeurs de la pile et du tas se rejoignent, c’est le signe qu’il n’y a plus de mémoire disponible pour le programme. Gestion de la mémoire d’un processus 39 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses Considérons la fonction récursive f : 1 void f ( int k){// exemple inès klimann 2 int n = 3; 3 int ∗p = malloc(sizeof( int )) ; 4 5 if (k==0) return; 6 printf (”k = %d, &n : %p, p : %p\n”, k, &n, p); 7 f (k−1); 8 free (p); 9 } 10 11 int main(){ 12 f (5) ; 13 } la variable locale n est dans la pile Gestion de la mémoire d’un processus 40 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses Considérons la fonction récursive f : 1 void f ( int k){// exemple inès klimann 2 int n = 3; 3 int ∗p = malloc(sizeof( int )) ; 4 5 if (k==0) return; 6 printf (”k = %d, &n : %p, p : %p\n”, k, &n, p); 7 f (k−1); 8 free (p); 9 } 10 11 int main(){ 12 f (5) ; 13 } la variable locale n est dans la pile la variable p est dans le tas. Gestion de la mémoire d’un processus 40 / 53 Organisation de la mémoire Convergence Croissance et décroissance des adresses dans la pile et le tas Résultat : k = 5, &n : 0 x7ffde641144c , p : 0 x55aab027e260 k = 4, &n : 0 x7ffde641140c , p : 0 x55aab027e690 k = 3, &n : 0 x7ffde64113cc , p : 0 x55aab027e6b0 k = 2, &n : 0 x7ffde641138c , p : 0 x55aab027e6d0 k = 1, &n : 0 x7ffde641134c , p : 0 x55aab027e6f0 Les adresses de la pile ( &n ) décroissent 44c, 40c, 3cc, 38c, 34c celle du tas ( p ) augmentent 60, 90, b0, d0, f 0 et les adresses de piles sont plus grandes que celles de tas 0x7ffde641134c > 0x55aab027e6f 0 Gestion de la mémoire d’un processus 41 / 53 Protection mémoire 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 42 / 53 Protection mémoire Segments et protection Lorsqu’un programme s’exécute, il possède un environnement mémoire constitué de plusieurs segments. Certains d’entre eux sont en lecture seule. Gestion de la mémoire d’un processus 43 / 53 Protection mémoire Segments et protection Lorsqu’un programme s’exécute, il possède un environnement mémoire constitué de plusieurs segments. Certains d’entre eux sont en lecture seule. Cette division de la mémoire allouée au programme permet de protéger la mémoire. L’unité (physique) de gestion de la mémoire sait quelles zones sont accessibles au programme et quels sont les droits de ces zones. Gestion de la mémoire d’un processus 43 / 53 Protection mémoire Segments et protection Lorsqu’un programme s’exécute, il possède un environnement mémoire constitué de plusieurs segments. Certains d’entre eux sont en lecture seule. Cette division de la mémoire allouée au programme permet de protéger la mémoire. L’unité (physique) de gestion de la mémoire sait quelles zones sont accessibles au programme et quels sont les droits de ces zones. En cas d’accès anormal, le matériel provoque une erreur qui remonte au système d’exploitation, lequel provoque alors l’arrêt du programme avec l’erreur Segmentation fault (erreur de segmentation). Gestion de la mémoire d’un processus 43 / 53 Protection mémoire Exemple de Segmentation fault La fonction scanf cherche à récupérer un entier sur l’entrée standard et stocke cette valeur à l’adresse x. 1 #include 2 #include 3 4 int main() 5 { 6 int ∗x;// non initialis ée 7 printf (” entrer un nombre : ”); 8 scanf(”%d”, x); 9 return (EXIT SUCCESS); 10 }//Erreur de segmentation (core dumped) Comme x contient n’importe quoi, le programme tente sans doute d’écrire dans une zone interdite pour lui. Gestion de la mémoire d’un processus 44 / 53 Protection mémoire Exemple de Segmentation fault Lecture à l’adresse zéro : cela provoque toujours une erreur. 1 int main()// exemple marc de falco 2 { 3 int ∗a = 0; 4 5 //return a ; 6 return ∗a; 7 }//Erreur de segmentation (core dumped) Gestion de la mémoire d’un processus 45 / 53 Protection mémoire Exemple de Segmentation fault Le code de la fonction main est dans le segment de code, lequel est read-only. Le pointeur a désigne le début du corps de main. Essayer d’écrire 0 (ou n’importe quoi d’autre) à cette adresse, provoque une erreur. 1 int main()// exemple marc de falco 2 { 3 int ∗a = (int∗) (&main); 4 // a pointe sur le corps de la fonction main 5 6 ∗a = 0; 7 8 return 0; 9 } Gestion de la mémoire d’un processus 46 / 53 Protection mémoire Exemple de Segmentation fault Dans cet exemple, on crée une chaı̂ne de caractère "hello". Elle est placée dans la section.rodata qui est read-only. 1 int main(void) 2 { 3 char ∗s = ”hello”;// emplacement d’adresse statique 4 ∗s = ’H’; // ou s=’H’; 5 }//seg fault Le pointeur s pointe sur la première position de "hello". En utilisant ce pointeur, on veut mettre un ’H’ dans cette zone mémoire protégée d’où le segmentation fault. Gestion de la mémoire d’un processus 47 / 53 Protection mémoire Eviter Segmentation fault Au lieu d’utiliser une constante chaı̂ne, laquelle est de classe d’allocation statique (rodata), on peut préférer utiliser un tableau de caractères. Alors la variable locale (à main ) s est dans la pile et elle est donc modifiable. 1 int main(){ 2 3 char s [] = ”hello”;// emplacement d’adresse dynamique 4 s = ’H’; 5 return 0; 6 } Gestion de la mémoire d’un processus 48 / 53 Divers 1 Rappels sur la portée et la durée de vie 2 Organisation de la mémoire Généralités Segments de code et de données Pile Tas Convergence 3 Protection mémoire 4 Divers Gestion de la mémoire d’un processus 49 / 53 Divers Mémoire cache Dans le modèle de Von Neumann, il y constamment des échanges entre CPU et RAM, soit pour charger la prochaine instruction à exécuter, soit pour récupérer les données sur lesquelles agit l’instruction courante. Gestion de la mémoire d’un processus 50 / 53 Divers Mémoire cache Dans le modèle de Von Neumann, il y constamment des échanges entre CPU et RAM, soit pour charger la prochaine instruction à exécuter, soit pour récupérer les données sur lesquelles agit l’instruction courante. Cependant, comme les micro-processeurs sont beaucoup plus rapides que la mémoire, ils passeraient leur temps à attendre les données (on parle de goulet d’étranglement). Gestion de la mémoire d’un processus 50 / 53 Divers Mémoire cache Dans le modèle de Von Neumann, il y constamment des échanges entre CPU et RAM, soit pour charger la prochaine instruction à exécuter, soit pour récupérer les données sur lesquelles agit l’instruction courante. Cependant, comme les micro-processeurs sont beaucoup plus rapides que la mémoire, ils passeraient leur temps à attendre les données (on parle de goulet d’étranglement). C’est pour cela qu’on été introduites les mémoires caches. Pour gagner du temps, la mémoire cache est chargée avec les données provenant de la RAM lorsqu’une instruction en a besoin. Gestion de la mémoire d’un processus 50 / 53 Divers Mémoire cache Dans le modèle de Von Neumann, il y constamment des échanges entre CPU et RAM, soit pour charger la prochaine instruction à exécuter, soit pour récupérer les données sur lesquelles agit l’instruction courante. Cependant, comme les micro-processeurs sont beaucoup plus rapides que la mémoire, ils passeraient leur temps à attendre les données (on parle de goulet d’étranglement). C’est pour cela qu’on été introduites les mémoires caches. Pour gagner du temps, la mémoire cache est chargée avec les données provenant de la RAM lorsqu’une instruction en a besoin. L’idée, c’est que si on a eu besoin une fois d’une donnée, on risque d’en avoir besoin plusieurs fois. On gagne ainsi du temps sur les accès ultérieurs à cette donnée. Gestion de la mémoire d’un processus 50 / 53 Divers Cycle d’exécution d’une instruction Dans la mémoire sont stockées de la même façon un opcode (instructions en langage machine qui spécifie l’opération à traiter) et les données qu’elle manipule : sous forme d’octets. Gestion de la mémoire d’un processus 51 / 53 Divers Cycle d’exécution d’une instruction Dans la mémoire sont stockées de la même façon un opcode (instructions en langage machine qui spécifie l’opération à traiter) et les données qu’elle manipule : sous forme d’octets. Pour progresser dans l’exécution du programme, l’unité de contrôle de l’ordinateur réalise de manière continue un cycle appelé Cycle d’exécution d’une instruction. Gestion de la mémoire d’un processus 51 / 53 Divers Cycle d’exécution d’une instruction Dans la mémoire sont stockées de la même façon un opcode (instructions en langage machine qui spécifie l’opération à traiter) et les données qu’elle manipule : sous forme d’octets. Pour progresser dans l’exécution du programme, l’unité de contrôle de l’ordinateur réalise de manière continue un cycle appelé Cycle d’exécution d’une instruction. La durée de ce cycle est imposée par une horloge globale. L’horloge permet d’assurer que les données sont valides au cycle d’horloge suivant, c’est à dire que les calculs sont terminés et les résultats stabilisés. Gestion de la mémoire d’un processus 51 / 53 Divers Cycle d’exécution d’une instruction Registres IP et IR Le registre IP ( Instruction Pointer ou compteur ordinal ) est un registre qui s’incrémente sans cesse. Il contient en permanence l’adresse de la prochaine instruction à réaliser. Faire un saut dans un programme, revient à inscrire dans le registre IP l’adresse de l’instruction ou le programme doit se rendre. L’incrémentation reprend alors à partir de cette nouvelle valeur. Gestion de la mémoire d’un processus 52 / 53 Divers Cycle d’exécution d’une instruction Registres IP et IR Le registre IP ( Instruction Pointer ou compteur ordinal ) est un registre qui s’incrémente sans cesse. Il contient en permanence l’adresse de la prochaine instruction à réaliser. Faire un saut dans un programme, revient à inscrire dans le registre IP l’adresse de l’instruction ou le programme doit se rendre. L’incrémentation reprend alors à partir de cette nouvelle valeur. Le registre d’instruction (IR) contient l’instruction en cours d’exécution. Ce registre est chargé par l’Unité de Contrôle au début du cycle d’exécution avec l’opcode de l’instruction dont l’adresse est donnée par le registre IR. Gestion de la mémoire d’un processus 52 / 53 Divers Cycle d’exécution d’une instruction Déroulement 1 Recherche puis Chargement. L’UC récupère le mot machine contenu à l’adresse mémoire indiqué par le registre IP et le met dans le registre IR. Gestion de la mémoire d’un processus 53 / 53 Divers Cycle d’exécution d’une instruction Déroulement 1 Recherche puis Chargement. L’UC récupère le mot machine contenu à l’adresse mémoire indiqué par le registre IP et le met dans le registre IR. 2 Décodage. La suite de bits du mot contenu dans le registre IR est décodée pour connaı̂tre : Cette étape, complexe, peut donc nécessiter de lire d’autres mots machines. Gestion de la mémoire d’un processus 53 / 53 Divers Cycle d’exécution d’une instruction Déroulement 1 Recherche puis Chargement. L’UC récupère le mot machine contenu à l’adresse mémoire indiqué par le registre IP et le met dans le registre IR. 2 Décodage. La suite de bits du mot contenu dans le registre IR est décodée pour connaı̂tre : l’opération à exécuter, Cette étape, complexe, peut donc nécessiter de lire d’autres mots machines. Gestion de la mémoire d’un processus 53 / 53 Divers Cycle d’exécution d’une instruction Déroulement 1 Recherche puis Chargement. L’UC récupère le mot machine contenu à l’adresse mémoire indiqué par le registre IP et le met dans le registre IR. 2 Décodage. La suite de bits du mot contenu dans le registre IR est décodée pour connaı̂tre : l’opération à exécuter, les données (opérandes) sur lesquelles elle agit (elles peuvent être en RAM, dans le cache, ou dans des registres). Cette étape, complexe, peut donc nécessiter de lire d’autres mots machines. Gestion de la mémoire d’un processus 53 / 53 Divers Cycle d’exécution d’une instruction Déroulement 1 Recherche puis Chargement. L’UC récupère le mot machine contenu à l’adresse mémoire indiqué par le registre IP et le met dans le registre IR. 2 Décodage. La suite de bits du mot contenu dans le registre IR est décodée pour connaı̂tre : l’opération à exécuter, les données (opérandes) sur lesquelles elle agit (elles peuvent être en RAM, dans le cache, ou dans des registres). Cette étape, complexe, peut donc nécessiter de lire d’autres mots machines. 3 Exécution. Elle peut être réalisée soit par l’UAL (cas d’une opération arithmétique ou logique) soit par l’Unité de Contrôle (cas d’une opération de branchement). Dans ce dernier cas, le registre IP est modifié et non plus seulement incrémenté. Gestion de la mémoire d’un processus 53 / 53 Divers Cycle d’exécution d’une instruction Déroulement 1 Recherche puis Chargement. L’UC récupère le mot machine contenu à l’adresse mémoire indiqué par le registre IP et le met dans le registre IR. 2 Décodage. La suite de bits du mot contenu dans le registre IR est décodée pour connaı̂tre : l’opération à exécuter, les données (opérandes) sur lesquelles elle agit (elles peuvent être en RAM, dans le cache, ou dans des registres). Cette étape, complexe, peut donc nécessiter de lire d’autres mots machines. 3 Exécution. Elle peut être réalisée soit par l’UAL (cas d’une opération arithmétique ou logique) soit par l’Unité de Contrôle (cas d’une opération de branchement). Dans ce dernier cas, le registre IP est modifié et non plus seulement incrémenté. 4 Ecriture du résultat. Puis recommencer. Gestion de la mémoire d’un processus 53 / 53