Mémoire, fichiers et entrées-sorties
Cours · informatique (MP2I/MPI), chapitre 8 · MP2I et MPI · le début du chapitre, la suite sur Adloun
8.1 Ce que le système fait pour vous
Le programme donne à cette partie un objectif mesuré : « donner un premier aperçu des liens qu'assurent les systèmes d'exploitation … entre les programmes et les ressources offertes par les machines qui les exécutent ». Et il écarte aussitôt l'essentiel de ce qu'un cours de système contiendrait : « le fonctionnement du matériel, l'architecture des ordinateurs, la conception des systèmes, la gestion des interfaces, les protocoles de communication, la virtualisation … sont hors programme ».
Restent trois choses, et elles suffisent à comprendre pourquoi un programme plante : comment il occupe la mémoire, comment il lit et écrit des fichiers, et — au chapitre chap:concurrence — comment plusieurs fils s'y bousculent. Le système Linux sert de support, « le plus propice pour introduire les éléments de ce programme ».
8.2 La mémoire d'un processus
8.2.1 Pile et tas
Un programme en cours d'exécution dispose de plusieurs zones de mémoire. Deux nous intéressent :
- la pile (stack) : les blocs d'activation des appels de fonction, empilés et dépilés automatiquement. Rapide, de taille bornée, gérée sans que vous n'y pensiez.
- le tas (heap) : la mémoire demandée explicitement par
malloc, rendue parfree. Vaste, à durée de vie choisie, entièrement à votre charge en C.
Le programme demande de distinguer ces deux notions, qu'on confond volontiers.
- La portée est syntaxique : c'est la région du texte du programme où un nom désigne cette variable. En C, les accolades la délimitent.
- La durée de vie est temporelle : c'est l'intervalle pendant lequel la case mémoire existe.
Elles ne coïncident pas. Un objet du tas survit à la fonction qui l'a créé — c'est tout son intérêt.
| Nature de la variable | Où elle vit | Durée de vie |
|---|---|---|
| globale | zone des globales | tout le programme |
| locale, paramètre | pile | l'appel de la fonction |
allouée par malloc | tas | jusqu'au free |
int* faute(void) {
int x = 42;
return &x; /* x MEURT ici : l'adresse rendue ne désigne plus rien */
}
Le bloc d'activation est dépilé au retour ; la case existe encore physiquement, et un prochain appel la réutilisera. Le programme lira donc une valeur qui change toute seule. gcc -Wall avertit : function returns address of local variable. C'est un avertissement qu'on ne discute pas.
8.2.2 La protection mémoire
Le système attribue à chaque processus des plages d'adresses. Toute lecture ou écriture hors de ces plages est interceptée par le matériel, et le processus est tué : c'est la segmentation violation, que le programme cite explicitement.
int* p = NULL;
*p = 1; /* Segmentation fault */
Exercices du chapitre
- L'adresse d'une locale, et ce qu'elle vaut trois lignes plus loin corrigé
- Ouvrir, vérifier, fermer corrigé
- Ce que fscanf renvoie, et ce qu'il coûte de l'ignorer corrigé
- Quatre façons de perdre ce qu'on a écrit corrigé
- Un nom n'est pas un fichier corrigé
- Problème — Un format de fichier qui survit à l'aller-retour corrigé