Gestion d’un tas§

Systèmes d’exploitation

auteur:Pierre-Antoine Champin
adresse:Département Informatique - IUT - Lyon1
licence:Ce travail est sous license Creative Commons Attribution-ShareAlike 3.0 France
1

Problématique§

2

Exemple§

Tpoint* alloue_point (double x, double y, double z) {
    Tpoint* p = malloc(sizeof(Tpoint));
    p->x = x; p->y = y; p->z = z;
    return p;
}

void libere_point (Tpoint* p) {
    free(p)
}
3

Rappels: allocation statique§

4

Rappels: allocation dynamique§

5

Besoins§

Besoins: gérer l’occupation d’une plage de mémoire (éventuellement extensible)

Critères:

6

Remarques§

→ notion étendue de système d’exploitation.

7

Méthodes§

8

Carte de bits§

_images/carte_de_bits.svg
map:    11000111  11000000  00111000  01111110
limits: 01000000  01000000  00001000  00100010
9

Avantages§

10

Inconvénients§

→ Peu utilisé en pratique

11

Liste chaînée§

On représente l’état de la mémoire par une liste chaînée dont chaque maillon représente une zone (adresse, taille), son état (alloué ou libre) et pointe vers le maillon représentant la zone suivante.

_images/tas_liste_chainee.svg
12

Évaluation§

13

Allocation§

_images/tas_liste_chaine_anim01.png

1. On recherche une zone libre de taille suffisante (de taille ≥ à la taille réclamée).

_images/tas_liste_chaine_anim02.png

2. On fractionne la zone libre en deux (la première ayant exactement la taille à allouer).

_images/tas_liste_chaine_anim03.png

3. On marque la première comme allouée et on retourne son adresse.

14

Libération§

_images/tas_liste_chaine_anim04.png

1. On parcours la liste jusqu’à trouver le maillon pointant vers la zone à libérer.

_images/tas_liste_chaine_anim05.png

2. On marque ce maillon comme libre. Attention à la fragmentation externe.

_images/tas_liste_chaine_anim06.png

3. Le cas échéant, on fusionne la zone libre avec les zones libres voisines.

_images/tas_liste_chaine_anim07.png

NB: seuls les voisins immédiats peuvent être libres, donc la fusion ne pénalise pas l’opération de libération (temps constant).

15

Choix d’une zone libre§

Lors d’une allocation mémoire, si plusieurs zones libres de taille suffisante sont disponibles, laquelle choisir?

Avantages ? Inconvénients ?

16

Variante 1§

_images/tas_liste_chaine_ext1a.svg

Séparer les zones libres et occupées en deux listes.

17
Variante 1 (suite)§
_images/tas_liste_chaine_ext1b.svg

Oblige à maintenir deux structures en parallèle.

18

Variante 2§

_images/tas_liste_chaine_ext2a.svg

Séparer les zones libres par taille.

19
Variante 2 (suite)§
_images/tas_liste_chaine_ext2b.svg

Oblige en plus à gérer les changements de taille.

20

Méthode Buddy§

Principe

Méthode basée sur le principe dichotomique, permettant de diviser la taille du tas par des puissances de 2.

Inconvénients

Avantages

21

Fonctionnement§

22

Exemple§

_images/buddy_anim01.png

tas de 16ko

_images/buddy_anim02.png

alloue 3ko (1)

_images/buddy_anim03.png

alloue 3ko (2)

_images/buddy_anim04.png

alloue 2ko (1)

_images/buddy_anim05.png

alloue 2Ko (2)

_images/buddy_anim06.png

libère zone 2 (1)

_images/buddy_anim07.png

libère zone 2 (2)

_images/buddy_later.png

un peu plus tard

23

Application§

Linux utilise la méthode Buddy pour l’allocation des pages.

→ La fragmentation (interne ou externe) n’est plus un problème puisque

24

Méthode Slab§

25

Illustration§

_images/slab_naive.png

NB:

26

Optimisation§

On peut recycler les cases libres du tableaux elles même pour stocker

→ surcoût mémoire minime.

_images/slab_optimized.png
27

Applications§

28
Applications (2)§
29

Extension: ramasse-miettes§

30

Ramasse-miettes§

Problème

Mise en œuvre

La plupart des langages modernes (Java, Javascript, PHP, Python, Ruby…) intègrent un mécanisme de ramasse-miettes (garbage collector).

31

Compteur de références§

32
Exemple§
digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=1" ]
  "b" [ label="<id> b|<ptr>...|ref=1" ]
  "c" [ label="<id> c|<ptr>...|ref=1" ]
  "d" [ label="<id> d|<ptr>...|ref=1" ]
  "e" [ label="<id> e|<ptr>...|ref=2" ]
  "f" [ label="<id> f|<ptr>...|ref=2" ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"
  "a":ptr -> "b"
  "a":ptr -> "c"
  "b":ptr -> "d"
  "b":ptr -> "e"
  "c":ptr -> "e"
  "d":ptr -> "f"
  "e":ptr -> "f"
  "f":ptr -> antiroot [color=transparent]
} digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=0", color=red, fontcolor=red ]
  "b" [ label="<id> b|<ptr>...|ref=1" ]
  "c" [ label="<id> c|<ptr>...|ref=1" ]
  "d" [ label="<id> d|<ptr>...|ref=1" ]
  "e" [ label="<id> e|<ptr>...|ref=2" ]
  "f" [ label="<id> f|<ptr>...|ref=2" ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"    [ style=dotted, color=red ]
  "a":ptr -> "b"
  "a":ptr -> "c"
  "b":ptr -> "d"
  "b":ptr -> "e"
  "c":ptr -> "e"
  "d":ptr -> "f"
  "e":ptr -> "f"
  "f":ptr -> antiroot [color=transparent]
} digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=0", color=transparent, fontcolor=transparent , fillcolor=transparent ]
  "b" [ label="<id> b|<ptr>...|ref=0", color=red, fontcolor=red ]
  "c" [ label="<id> c|<ptr>...|ref=0", color=red, fontcolor=red ]
  "d" [ label="<id> d|<ptr>...|ref=1" ]
  "e" [ label="<id> e|<ptr>...|ref=2" ]
  "f" [ label="<id> f|<ptr>...|ref=2" ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"    [ color=transparent ]
  "a":ptr -> "b" [ style=dotted, color=red ]
  "a":ptr -> "c" [ style=dotted, color=red ]
  "b":ptr -> "d"
  "b":ptr -> "e"
  "c":ptr -> "e"
  "d":ptr -> "f"
  "e":ptr -> "f"
  "f":ptr -> antiroot [color=transparent]
} digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "b" [ label="<id> b|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "c" [ label="<id> c|<ptr>...|ref=0", color=red, fontcolor=red ]
  "d" [ label="<id> d|<ptr>...|ref=0", color=red, fontcolor=red  ]
  "e" [ label="<id> e|<ptr>...|ref=1", color=orange, fontcolor=orange  ]
  "f" [ label="<id> f|<ptr>...|ref=2" ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"    [ color=transparent ]
  "a":ptr -> "b" [ color=transparent ]
  "a":ptr -> "c" [ color=transparent ]
  "b":ptr -> "d" [ style=dotted, color=red ]
  "b":ptr -> "e" [ style=dotted, color=red ]
  "c":ptr -> "e"
  "d":ptr -> "f"
  "e":ptr -> "f"
  "f":ptr -> antiroot [color=transparent]
} digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "b" [ label="<id> b|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "c" [ label="<id> c|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "d" [ label="<id> d|<ptr>...|ref=0", color=red, fontcolor=red  ]
  "e" [ label="<id> e|<ptr>...|ref=0", color=red, fontcolor=red  ]
  "f" [ label="<id> f|<ptr>...|ref=2" ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"    [ color=transparent ]
  "a":ptr -> "b" [ color=transparent ]
  "a":ptr -> "c" [ color=transparent ]
  "b":ptr -> "d" [ color=transparent ]
  "b":ptr -> "e" [ color=transparent ]
  "c":ptr -> "e" [ style=dotted, color=red ]
  "d":ptr -> "f"
  "e":ptr -> "f"
  "f":ptr -> antiroot [color=transparent]
} digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "b" [ label="<id> b|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "c" [ label="<id> c|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "d" [ label="<id> d|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent  ]
  "e" [ label="<id> e|<ptr>...|ref=0", color=red, fontcolor=red  ]
  "f" [ label="<id> f|<ptr>...|ref=1", color=orange, fontcolor=orange  ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"    [ color=transparent ]
  "a":ptr -> "b" [ color=transparent ]
  "a":ptr -> "c" [ color=transparent ]
  "b":ptr -> "d" [ color=transparent ]
  "b":ptr -> "e" [ color=transparent ]
  "c":ptr -> "e" [ color=transparent ]
  "d":ptr -> "f" [ style=dotted, color=red ]
  "e":ptr -> "f"
  "f":ptr -> antiroot [color=transparent]
} digraph {
  margin=0;
  rankdir=LR;
  bgcolor=transparent;
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor=transparent ]
  "a" [ label="<id> a|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "b" [ label="<id> b|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "c" [ label="<id> c|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent ]
  "d" [ label="<id> d|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent  ]
  "e" [ label="<id> e|<ptr>...|ref=0", color=transparent, fontcolor=transparent, fillcolor=transparent  ]
  "f" [ label="<id> f|<ptr>...|ref=0", color=red, fontcolor=red  ]
  antiroot [ label="", shape=none, fillcolor=transparent ]

  root -> "a"    [ color=transparent ]
  "a":ptr -> "b" [ color=transparent ]
  "a":ptr -> "c" [ color=transparent ]
  "b":ptr -> "d" [ color=transparent ]
  "b":ptr -> "e" [ color=transparent ]
  "c":ptr -> "e" [ color=transparent ]
  "d":ptr -> "f" [ color=transparent ]
  "e":ptr -> "f" [ style=dotted, color=red ]
  "f":ptr -> antiroot [color=transparent]
}
33

Références cycliques§

Le comptage des références n’est pas suffisant.

digraph {
  margin=0;
  rankdir=LR;
  bgcolor="#FFFFFF00";
  node [ style=filled,color=black,fillcolor=white,shape=record ]

  root [ label="", shape=none, fillcolor="#FFFFFF00" ]
  "a" [ label="<id> a|<ptr>...|ref=1" ]
  "b" [ label="<id> b|<ptr>...|ref=2" ]
  "c" [ label="<id> c|<ptr>...|ref=1" ]
  "d" [ label="<id> d|<ptr>...|ref=1" ]
  "e" [ label="<id> e|<ptr>...|ref=1" ]
  antiroot [ label="", shape=none, fillcolor="#FFFFFF00" ]

  root -> "a"
  "a":ptr -> "b"
  "b":ptr -> "c"
  "c":ptr -> "d"
  "d":ptr -> "e"
  "e":ptr -> "b"
  "d":ptr -> antiroot [color="#FFFFFF00"]
}

→ nécessité de trouver un compromis entre l’économie de mémoire et le temps de clacul.

34