Académique Documents
Professionnel Documents
Culture Documents
Cours-Systeme Linux UNIX
Cours-Systeme Linux UNIX
D.Revuz
17 fevrier 2005
ii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
1
1
2
2
3
3
5
5
2 Syst`
eme de Gestion de Fichiers
2.1 Le concept de fichier . . . . . . . . . . .
2.2 Fichiers ordinaires / Fichiers speciaux.
2.3 Organisation utilisateur des Disques . .
2.4 Les inodes . . . . . . . . . . . . . . . . .
2.5 Organisation des disques System V . . .
2.6 Adressage des blocs dans les inodes . . .
2.7 Allocation des inodes dun disque . . . .
2.8 Allocation des blocs-disque . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
8
8
9
10
11
11
11
3 Le Buffer Cache
3.1 Introduction au buffer cache . . . . . . . . . . . . .
3.1.1 Avantages et desavantages du buffer cache .
3.2 Le buffer cache, structures de donnees. . . . . . . .
3.2.1 La liste doublement chanee des blocs libres
3.3 Lalgorithme de la primitive getblk . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
17
17
17
18
18
4 La biblioth`
eque standard
4.1 Les descripteurs de fichiers. . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Ouverture dun fichier . . . . . . . . . . . . . . . . . . . . .
4.1.2 Redirection dun descripteur : freopen . . . . . . . . . . .
4.1.3 Creation de fichiers temporaires . . . . . . . . . . . . . . . .
4.1.4 Ecriture non formatee . . . . . . . . . . . . . . . . . . . . .
4.1.5 Acc`es sequentiel . . . . . . . . . . . . . . . . . . . . . . . .
4.1.6 Manipulation du pointeur de fichier . . . . . . . . . . . . .
4.1.7 Un exemple dacc`es direct sur un fichier dentiers. . . . . .
4.1.8 Les autres fonctions de deplacement du pointeur de fichier.
4.2 Les tampons de fichiers de stdlib. . . . . . . . . . . . . . . . . . . .
4.2.1 Les modes de bufferisation par defaut. . . . . . . . . . . . .
4.2.2 Manipulation des tampons de la biblioth`eque standard. . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
23
24
24
25
25
26
26
26
26
27
27
27
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
`
TABLE DES MATIERES
iv
4.3
4.4
4.5
4.6
4.7
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
29
30
31
31
5 Appels syst`
eme du Syst`
eme de Gestion de Fichier
5.1 open . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.1 Deroulement interne dun appel de open . . .
5.2 creat . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 read . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4 write . . . . . . . . . . . . . . . . . . . . . . . . . .
5.5 lseek . . . . . . . . . . . . . . . . . . . . . . . . . .
5.6 dup et dup2 . . . . . . . . . . . . . . . . . . . . . . .
5.7 close . . . . . . . . . . . . . . . . . . . . . . . . . .
5.8 fcntl . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
33
33
35
36
36
36
37
37
38
38
6 Les processus
6.1 Introduction aux processus . . . . . . . . . . . . . . . . . .
6.1.1 Creation dun processus - fork() . . . . . . . . . .
6.2 Format dun fichier executable . . . . . . . . . . . . . . . .
6.3 Chargement/changement dun executable . . . . . . . . . .
6.4 zone u et table des processus . . . . . . . . . . . . . . . . .
6.5 fork et exec (revisites) . . . . . . . . . . . . . . . . . . . .
6.6 Le contexte dun processus . . . . . . . . . . . . . . . . . .
6.7 Commutation de mot detat et interruptions. . . . . . . . .
6.8 Les interruptions . . . . . . . . . . . . . . . . . . . . . . . .
6.9 Le probl`eme des cascades dinterruptions . . . . . . . . . . .
6.9.1 Etats et transitions dun processus . . . . . . . . . .
6.9.2 Listes des etats dun processus . . . . . . . . . . . .
6.10 Lecture du diagramme detat. . . . . . . . . . . . . . . . . .
6.11 Un exemple dexecution . . . . . . . . . . . . . . . . . . . .
6.12 La table des processus . . . . . . . . . . . . . . . . . . . . .
6.13 La zone u . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.14 Acc`es aux structures proc et user du processus courant . .
6.14.1 Les informations temporelles. . . . . . . . . . . . . .
6.14.2 Changement du repertoire racine pour un processus.
6.14.3 Recuperation du PID dun processus . . . . . . . . .
6.14.4 Positionement de leuid, ruid et suid . . . . . . . . .
6.15 Tailles limites dun processus . . . . . . . . . . . . . . . . .
6.15.1 Manipulation de la taille dun processus. . . . . . . .
6.15.2 Manipulation de la valeur nice . . . . . . . . . . . .
6.15.3 Manipulation de la valeur umask . . . . . . . . . . .
6.16 Lappel syst`eme fork . . . . . . . . . . . . . . . . . . . . .
6.17 Lappel syst`eme exec . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
41
41
41
42
42
43
43
45
45
46
47
47
47
48
49
49
50
50
50
51
51
51
52
52
52
52
53
53
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
55
55
56
56
57
57
57
58
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
`
TABLE DES MATIERES
7.4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8 La m
emoire
8.0.4 les memoires . . . . . . . . . . . . . . . . . . . . . . . . .
8.0.5 La memoire centrale . . . . . . . . . . . . . . . . . . . . .
8.1 Allocation contigue . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1 Pas de gestion de la memoire . . . . . . . . . . . . . . . .
8.1.2 Le moniteur residant . . . . . . . . . . . . . . . . . . . . .
8.1.3 Le registre barri`ere . . . . . . . . . . . . . . . . . . . . . .
8.1.4 Le registre base . . . . . . . . . . . . . . . . . . . . . . . .
8.1.5 Le swap . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.6 Le co
ut du swap . . . . . . . . . . . . . . . . . . . . . . .
8.1.7 Utilisation de la taille des processus . . . . . . . . . . . .
8.1.8 Swap et executions concurrentes . . . . . . . . . . . . . .
8.1.9 Contraintes . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.10 Deux solutions existent . . . . . . . . . . . . . . . . . . .
8.1.11 Les probl`emes de protection . . . . . . . . . . . . . . . . .
8.1.12 Les registres doubles . . . . . . . . . . . . . . . . . . . . .
8.2 Ordonnancement en memoire des processus . . . . . . . . . . . .
8.3 Allocation non-contigue . . . . . . . . . . . . . . . . . . . . . . .
8.3.1 Les pages et la pagination . . . . . . . . . . . . . . . . . .
8.3.2 Ordonnancement des processus dans une memoire paginee
8.3.3 Comment proteger la memoire paginee . . . . . . . . . . .
8.3.4 La memoire segmentee . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
58
58
58
59
60
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. .
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61
61
61
63
63
63
63
63
65
65
65
66
66
66
66
66
67
68
68
68
69
69
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9 La m
emoire virtuelle
9.0.5 Les overlays . . . . . . . . . . . . . . . . . . . . . . . .
9.0.6 Le chargement dynamique . . . . . . . . . . . . . . . .
9.1 Demand Paging . . . . . . . . . . . . . . . . . . . . . . . . . .
9.1.1 Efficacite . . . . . . . . . . . . . . . . . . . . . . . . .
9.2 Les algorithmes de remplacement de page . . . . . . . . . . .
9.2.1 Le remplacement optimal . . . . . . . . . . . . . . . .
9.2.2 Le remplacement peps (FIFO) . . . . . . . . . . . . .
9.2.3 Moins recemment utilisee LRU. . . . . . . . . . . . . .
9.2.4 Lalgorithme de la deuxi`eme chance . . . . . . . . . .
9.2.5 Plus frequemment utilise MFU . . . . . . . . . . . . .
9.2.6 Le bit de salete (Dirty Bit) . . . . . . . . . . . . . . .
9.3 Allocation de pages aux processus . . . . . . . . . . . . . . .
9.4 Lappel fork et la memoire virtuelle . . . . . . . . . . . . . . .
9.5 Projection de fichiers en memoire . . . . . . . . . . . . . . . .
9.6 Les conseils et politiques de chargement des zones mmappees
9.7 Chargement dynamique . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
71
71
72
72
73
75
75
75
76
76
76
77
77
78
78
80
81
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
83
83
83
85
86
86
86
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
`
TABLE DES MATIERES
vi
87
87
87
89
89
89
90
91
91
91
93
94
95
95
96
96
97
97
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
99
. 99
. 99
. 100
. 101
13 Algorithmes Distribu
es & Interblocages
13.1 exemples . . . . . . . . . . . . . . . . . . . . . . . .
13.1.1 Les mefaits des acc`es concurrents . . . . . .
13.1.2 Exclusion mutuelle . . . . . . . . . . . . . .
13.2 Mode dutilisation des ressources par un processus.
13.3 Definition de linterblocage (deadlock) . . . . . . .
13.4 Quatre conditions necessaires `a linterblocage. . . .
13.5 Les graphes dallocation de ressources . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
103
103
103
104
105
105
105
105
14 S
ecurit
e et S
uret
e de fonctionnement
14.1 Protection des syst`emes dexploitation . . . . . . . . . . . . . . . . . .
14.2 Generalites sur le controle dacc`es . . . . . . . . . . . . . . . . . . . . .
14.2.1 Domaines de protection et matrices dacc`es . . . . . . . . . . .
14.2.2 Domaines de protection restreints . . . . . . . . . . . . . . . . .
14.2.3 Avantages des domaines de protections restreints . . . . . . . .
14.3 Le cheval de Troie . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4 Le confinement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.5 les mecanismes de controle . . . . . . . . . . . . . . . . . . . . . . . . .
14.5.1 Application des capacites au domaines de protection restreints
14.6 Les ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.6.1 Appels systemes setacl et getacl . . . . . . . . . . . . . . . .
14.6.2 Autres pistes sur la securite . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
107
107
108
109
109
110
110
110
110
112
115
115
116
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
119
119
119
119
119
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
`
TABLE DES MATIERES
15.2.1 La primitive select .
15.2.2 La primitive poll . .
15.2.3 Le peripherique poll .
15.2.4 Les extensions de read
15.3 une solution multi-activites .
vii
. . . . . .
. . . . . .
. . . . . .
et write
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
119
121
122
123
123
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
125
125
125
127
127
127
128
128
128
129
129
129
130
130
132
132
133
134
134
134
134
17 Clustering
135
17.1 Le clustering sous linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
18 Bibliographie
137
18.1 Webographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
viii
`
TABLE DES MATIERES
Evolutions
futures : dr@univ-mlv.fr (jattend vos remarques), uniformisation de la presentation,
nettoyage des points obscurs, corrections orthographiques, complement sur fcntl, ioctl, plus dexemples,
des sujets de projets , des sujets dexamen.
Chapitre 1
Introduction
Ceci est un polycopie de cours de licence informatique sur les syst`emes dexploitations en
general et plus specialement sur la famille Unix.
Ce poly est le support utilise pour les licences et pour les Apprentis ingenieurs de la fili`ere Informatique et Reseau.
1.1
1.1.1
Unix
Pourquoi unix ?
LE PRIX
la disponibilite des sources
Lintelligence des solutions mise en oeuvre
de grande ressource bibliographique
il faut mieux apprendre les conceptes fondamentaux dans un syst`eme simple et ouvert puis
passer a des syst`emes proprietaires et fermes que linverse.
parceque je ne vais pas changer mon cours tout de suite
1.1.2
le succ`
es dUnix et de linux
1.1.3
CHAPITRE 1. INTRODUCTION
Langage (de haut niveau )
compilation separee, conditionnelle, parametrage, precompilation
Enrichissement constant
Ouverture (parametrabilite du poste de travail)
Souplesse des entrees/sorties
uniformite
Facilites de communication inter-syst`emes
Communautes dutilisateurs (/etc/groups)
Langages de commandes (flexibles et puissants)
Aspect multi-utilisateurs
connections de tout type de terminal, biblioth`eques, etc
Parallelisme
multi-taches : scheduling par tache
communication entre taches
multiprocesseurs
Interface syst`eme/applications
appels syst`eme, biblioth`eque
le syst`eme de gestion de fichiers
hierarchie
Interfaces graphiques normees : X11.
Profusion dinterfaces graphiques sous linux Gnome et KDE en particulier
1.1.4
Fragilite du S.G.F.
pertes de fichiers possible en cas de crash
regle avec les SGF journalises
Gestion et rattrapage des interruptions inadapte au temps reel
Des evolutions avec RLlinux et OS9.
Mecanisme de creation de processus lourd
de nombreuses ameliorations en particulier les threads.
Une edition de liens statique
Amelioration avec les librairies partagees.
des Modules noyau chargeables/dechargeables dynamiquement
Rattrapage derreur du compilateur C standard peu aise !
Ces bugs sont corrigees
Co
ut en ressources
reste globalement efficasse
Gestion
1.2
Structure g
en
erale des syst`
emes dexploitation
Un syst`eme dexploitation est un programme qui sert dinterface entre un utilisateur et un ordinateur.
ERALE
`
1.2. STRUCTURE GEN
DES SYSTEMES
DEXPLOITATION
Il est plus facile de definir un syst`eme dexploitation par ce quil fait que par ce quil est. J.L.
Peterson.
Un syst`eme dexploitation est un ensemble de procedures coherentes qui a pour but de gerer la
penurie de ressources. J-l. Stehle P. Hochard.
Quelques syst`
emes :
le batch Le traitement par lot (disparus).
interactifs Pour les utilisateurs (ce cher UNIX).
temps r
eels Pour manipuler des situations physiques par des peripheriques (OS9 un petit fr`ere
fute dUNIX). Lidee est de gerer le temps vrai.En particulier de gerer des ev`enement
aleatoires qui neccessite lexecution dune action en proirite absolue.
distribu
es UNIX ?, les micros noyaux ? lavenir ?
moniteurs transactionnels Ce sont des applications qui manipulent des objets `a taches multiples comme les comptes dans une banque, des reservations, etc. Lidee est de decomposer
lactivite en actions, chacune independantes des autres,pour ce faire elle sont ecrites pour
avoir un comportement dit atomique ainsi il ny a pas de programme mais des ev`enement
et des actions associees. Il ny pas dans de changement de context pour traiter une action,
cest le syst`eme adapte pour traite de gros volumes de petites operations.
SE orient
es objets Micro Noyaux.
1.2.1
Couches fonctionnelles :
Programmes utilisateurs
Programmes dapplication editeurs/tableurs/BD/CAO
Programmes syst`eme assembleurs/compilateurs/editeurs de liens/chargeurs
syst`eme dexploitation
langage machine
microprogramme
machines physiques
1.2.2
Larchitecture du syst`
eme
Larchitecture globale dUNIX est une architecture par couches (coquilles) successsives comme
le montre la figure 1.2. Les utilisateurs ordinaire communiquent avec la couche la plus evoluee celle
des applications (en generale aujourdhui associe avec une interface graphique). Le programmeur
lui va en fonction de ses besoins utiliser des couches de plus en plus profondes, plus precises mais
plus difficiles a utiliser.
Chaque couche est construite pour pouvoir etre utilisee sans connaitre les couches inferieures (ni
leur fonctionnement, ni leur interface).
Cette hierarchie dencapsulation permet decrire des applications plus portables. En effet si elles
sont ecrites dans les couches hautes, le travaille de portage est fait par le portage des couches
inferieures. Pour des applications o`
u le temps de calcul prime devant la portabilite, les couches
basses seront utilisees.
CHAPITRE 1. INTRODUCTION
Utilisateurs
user 1
user 2
user 3
compilateur
editeur
jeux
user N
Base de ...
Applications
Systme dexploitation
Matriel
utilisateur
utilisateur
utilisateur
SHELL
make
ls
awk
Hardware
cc
Kernel
vi
Applications
1.3. HISTORIQUE
Applications/utilisateurs
bibliotheques
Niveau Utilisateur
Niveau Noyau
Interface appels - systeme
Sous-Systeme
de
Gestion de fichiers
Sous-Systeme
Gestion des processus
communication
interprocessus
"scheduler"
cache
gestion memoire
caractere |
bloc
Controleurs
Controle Materiel
Niveau Noyau
Niveau Materiel
Materiel
1.2.3
Larchitecture du noyau
Lautre approche architecturale est larchitecture interne du Noyau (kernel). Cest une architecture logicielle elle permet aux developpeur de structurer le travail de developpement. Le but ici est
de simplifier la comprehension et la fabrication du syst`eme. Nous cherchons donc ici `a decomposer
le noyau en parties disjointes (qui sont concevables et programmables de facons disjointes). La
Figure 1.3 donne une idee de ce que peut etre larchitecture interne dun noyau UNIX. Noter bien
la position exterieure des biblioth`eques .
1.3
historique
CHAPITRE 1. INTRODUCTION
Chapitre 2
Syst`
eme de Gestion de Fichiers
Le syst`eme de gestion de fichiers est un outil de manipulation des fichiers et de la structure
darborescence des fichiers sur disque et a aussi le role sous UNIX de conserver toutes les informations dont la perennite est importante pour le syst`eme (et pour les utilisateurs biensur). Ainsi tous
les objets importants du syst`eme sont references dans le syst`eme de fichiers (memoire, terminaux,
peripheriques varies, etc).
Le syst`eme de gestion de fichier permet une manipulation simple des fichiers et g`ere de facon
transparente les differents probl`emes dacc`es aux supports de masse :
partage : utilisation dun meme fichier/disque par plusieurs utilisateurs
efficacite : utilisation de cache, uniformisation des acc`es
droits : protection des elements important du syst`eme et protection interutilisateurs
alignement : transtypage entre la memoire et les supports magnetiques
2.1
Le concept de fichier
`
CHAPITRE 2. SYSTEME
DE GESTION DE FICHIERS
2.2
Le syst`eme est un utilisateur du syst`eme de gestion de fichier et en temps que createur il definit
quelques contenus structures ces fichiers auront de ce fait des acc`es r`eglementes.
Pour le syst`eme les fichiers sont donc organises en deux grandes familles :
les fichiers standards que sont par exemple les fichiers texte, les executables, etc. Cest-`a-dire
tout ce qui est manipule et structure par les utilisateurs.
Les fichiers sp
eciaux peripheriques, memoire, et autre fichiers physiques ou logique. Ces fichiers ont une structure interne definie (par les developpeurs du syst`eme) qui doit etre respecte cest pourquoi leur manipulation nest possible que par par lintermediaire du syst`eme
(encore un bon exemple dencapsulation).
Les catalogues sont des fichiers speciaux, il faut pour les manipuler physiquement faire appel
au syst`eme ce qui en prot`ege la structure1 .
Les fichiers physiques dans le repertoire /dev (dev comme devices dispositifs materiels, les peripheriques
et quelques dispositifs logiques )
Character devices (peripheriques ou la communication ce fait octets par octets)
les terminaux (claviers, ecrans)
les imprimantes
la memoire
etc
Block devices (peripheriques ou la communication ce fait par groupe doctet appeles blocs)
les disques
les bandes magnetiques
etc
Les fichiers `a usages logiques et non physiques
liens symboliques
pseudo-terminaux
sockets
tubes nommes
Ce dernier type de fichiers speciaux est utilise pour servir dinterface entre disques, entre
machines et simuler : des terminaux, des lignes de communication, etc.
Cette distinction entre fichier ordinaire et speciaux et tout simplement le fait que le syst`eme est
un utilisateur comme les autres des fichiers. Pour certains fichier le syst`eme utilise une structure
interne speciale (dou le nom) qui ne doit pas etre modifier sous peine de comportement indefini.
Pour se proteger le syst`eme ne permet pas lacc`es direct aux informations cest lui qui fait toutes
les entrees sortie sur les fichiers speciaux de facon a en assurer lintegrite. Ceci est independant
du syst`eme de droits dacc`es, la structure du code du noyau ne permet pas dautres acc`es que les
acc`es speciaux 2 .
2.3
Comment permettre aux utilisateurs didentifier les donnees sur les supports de masse ?
Le syst`eme le plus rependu aujourdhui est un syst`eme arborescent avec des fichiers utilises comme
1 les r
epertoires sont rest
e accessible longtemps en lecture comme des fichiers ordinaires mais lacc`
es en
ecriture etait contraint, pour assurer la structure arborescente acyclique. Aujourdhui tout les acc`
es au r
epertoires
ont contraint et on a un ensemble dappels syst`
eme sp
ecifiques pour r
ealiser des entr
es sortie dans les repertoires. opendir(3), closedir(3), dirfd(3), readdir(3), rewinddir(3), scandir(3),seekdir(3), telldir(3)
approche qui permet d
etre effectivement plus ind
ependant sur la structure interne des r
epertoires, avec des syst`
eme
plus efficaces que les listes utilis
ees dans les premi`
ere impl
ementations. Voire Reiser fs par exemple.
2 Pour plsu dinformation sur le sujet aller voire dans les sources les structures de sgf et dinode TODO : nom
de fichiers concern
es .
2.4
Les inodes
Linode est le passage oblige de tous les echanges entre le syst`eme de fichier et la memoire.
Linode est la structure qui contient toutes les informations sur un fichier donne `a lexception de
3 Ce
`
CHAPITRE 2. SYSTEME
DE GESTION DE FICHIERS
10
sa reference dans larborescence (son nom), larborescence netant quun outil de referencement
des fichiers.
Les informations stockees dans une inode disque sont :
utilisateur proprietaire
groupe proprietaire
type de fichier
- fichiers ordinaires
d repertoire (dyrectory)
b mode bloc
c mode caract`ere
l lien symbolique
p pour une fifo (named pipe)
s pour une socket
droits dacc`es (ugo*rwx)
date de dernier acc`es
date de derni`ere modification
date de derni`ere modification de linode
taille du fichier
adresses des blocs-disque contenant le fichier.
Dans une inode en memoire (fichier en cours dutilisation par un processus) on trouve dautres
informations supplementaires :
le statut de linode
{ locked,
waiting P
inode `a ecrire,
fichier `a ecrire,
le fichier est un point de montage
}
Et deux valeurs qui permettent de localiser linode sur un des disques logiques :
Numero du disque logique
Numero de linode dans le disque
cette information est inutile sur le disque (on a une bijection entre la position de linode sur disque
et le numero dinode).
On trouve aussi dautres types dinformations comme lacc`es `a la table des verrous ou bien des
informations sur les disques `a distance dans les points de montage.
2.5
Lorganisation disque decrite sur la figure 2.2 est la plus simple que lon peut trouver de nos
jours sous UNIX, il en existe dautres o`
u lon peut en particulier placer un meme disque logique
sur plusieurs disques physiques (dangereux), certaines o`
u les blocs sont fragmentables, etc.
Boot bloc utilise au chargement du syst`eme.
Super Bloc il contient toutes les informations generales sur le disque logique.
Inode list Table des inodes.
blocs les blocs de donnees chaines `a la creation du disque (mkfs).
Les blocs de donnees ne sont pas fragmentables sous Syst`eme V.
11
Super
Bloc
Inode liste
Blocs de
donnes
Super Bloc
Inode liste
Boot Bloc
Blocs de
donnes
2.6
Le syst`eme dadressage des blocs dans les inodes (syst`eme V) consiste en 13 adresses de blocs.
Les dix premi`eres adresses sont des adresses qui pointent directement sur les blocs de donnees du
fichier. Les autres sont des adresses indirectes vers des blocs de donnees contenant des adresses.
La figure 2.3 nous montre les trois niveaux dindirection. Linteret de cette representation est
deconomiser sur la taille des inodes tout en permettant un acc`es rapide au petits fichiers (la majorite des fichiers sont petits). Mais en laissant la possibilite de creer de tr`es gros fichiers :
10 + 256 + (256 256) + (256 256 256)
blocs disques.
2.7
Lallocation des inodes est realisee en recherchant dans la zone des inodes du disque une inode
libre. Pour accelerer cette recherche : un tampon dinodes libres est gere dans le SuperBloc, de
plus lindice de la premi`ere inode libre est garde en reference dans le SuperBloc afin de redemarrer
la recherche qu`a partir de la premi`ere inode reellement libre.
Mais ce syst`eme a une faille quil faut prevoir dans lecriture dans lalgorithme ialloc dallocation
dinode, cette faille est decrite dans la Figure 2.10
2.8
Lalgorithme utilise pour gerer lallocation des inodes sappuie sur le fait que lon peut tester si
une inode est libre ou non en regardant son contenu. Ceci nest plus vrai pour les blocs. La solution
est de chaner les blocs. Ce chanage est realise par blocs dadresses pour accelerer les acc`es et
profiter au maximum du buffer cache. Il existe donc un bloc dadresses dans le super bloc qui sert
de zone de travail pour lallocateur de blocs. Lutilisation de ce bloc et le mecanisme dallocation
sont decrits dans les Figures 2.11 `a 2.16
`
CHAPITRE 2. SYSTEME
DE GESTION DE FICHIERS
12
Blocs de donnes
sur le disque
Inode
direct 0
direct 1
direct 2
direct 3
direct 4
direct 5
direct 6
direct 7
direct 8
direct 9
indirect
double
triple
83
19
18
vide
48
20
Curseur
vide
83
18
19
20
Curseur
13
473
0
Curseur
inodes libres
479
475
477
inodes libres
479
477
475
0
Curseur
inodes libres
479
477
475
0
Curseur
inodes libres
479
477
475
0
Curseur
`
CHAPITRE 2. SYSTEME
DE GESTION DE FICHIERS
14
Processus B
Processus A
allocation
de l'inode I
Processus C
en sommeil pendant
la lecture de l'inode (a)
allocation
avec super bloc vide (b)
l'inode I (libre) est remise
dans le super bloc (c)
Travail sur
l'Inode I en mmoire
allocation
d'une inode (d)
allocation (d)
de l'inode I
Mais l'inode I
n'est pas libre !!
allocation (e)
d'une autre l'inode
temps
(a)
(b)
(c)
JIK
(d)
JI
(e)
temps
Fig. 2.10 Faille de lalgorithme dallocation.
15
95
Bloc 109
211 208 205 202 199
112
Bloc 211
311 308 305 302 301
214
etc
Fig. 2.11 Liste chainee de blocs.
vide
112
112
112
`
CHAPITRE 2. SYSTEME
DE GESTION DE FICHIERS
16
112
Bloc 211
311 308 305 302 301
214
112
Chapitre 3
Le Buffer Cache
3.1
3.1.1
Avantages et d
esavantages du buffer cache
3.2
Le statut dun bloc cache est une combinaison des etats suivants :
verrouill
e lacc`es est reserve `a un processus.
1 Les
probl`
emes dalignement existent toujours quand on transf`
ere des donn
ees, cf. protocoles XDR,RPC
17
18
Prcdent sur
hash queue
tte de liste
b1
b2
bn
tte de liste
b2
bn
3.2.1
Les tampons libres appartiennent simultanement `a deux listes doublement chanees : la liste
des blocs libres et la hash-liste correspondant au dernier bloc ayant ete contenu dans ce tampon.
Linsertion dans la liste des tampons libres se fait en fin de liste, la suppression (allocation
du tampon `a un bloc donne) se fait en debut de liste, ainsi le tampon alloue est le plus vieux
tampon libere2 . Ceci permet une reponse immediate si le bloc correspondant est reutilise avant
que le tampon ne soit alloue `a un autre bloc.
3.3
19
bloc# 0 mod 4
28
64
bloc# 1 mod 4
17
97
bloc# 2 mod 4
98
50
10
bloc# 3 mod 4
35
99
liste libres
Fig. 3.3 Etat du buffer cache avant les scenarios 1, 2 et 3.
{
if (tampon dans sa hash liste)
{
if (tampon actif )
{
[5]
sleep attente de la liberation du tampon
continuer
}
[1]
verrouiller le tampon
retirer le tampon de la liste des tampons libres
retourner le tampon
}
else /* nest pas dans la hash liste */
{
if (aucun tampon libre )
{
[4]
sleep attente de la liberation dun tampon
continuer
}
retirer le tampon de la liste libre
[3]
if (le tampon est a ecrire)
{
lancer la sauvegarde sur disque
continuer
}
[2]
retirer le buffer de son ancienne liste
de hashage, le placer sur la nouvelle
retourner le tampon
}
}
}
20
bloc# 0 mod 4
28
64
bloc# 1 mod 4
17
97
bloc# 2 mod 4
98
50
10
bloc# 3 mod 4
35
99
liste libres
Fig. 3.4 Scenario 1- Demande dun tampon pour le bloc-disque 4.
bloc# 0 mod 4
28
64
bloc# 1 mod 4
17
97
bloc# 2 mod 4
98
50
10
35
99
bloc# 3 mod 4
41
liste libres
bloc# 0 mod 4
28
bloc# 1 mod 4
17
64
97
writing
bloc# 2 mod 4
98
50
10
bloc# 3 mod 4
35
99
18
writing
liste libres
21
bloc# 0 mod 4
28
64
bloc# 1 mod 4
17
97
bloc# 2 mod 4
98
50
10
bloc# 3 mod 4
35
99
liste libres
Fig. 3.7 Scenario 4- Plus de blocs libres.
bloc# 0 mod 4
28
64
bloc# 1 mod 4
17
97
bloc# 2 mod 4
98
50
10
bloc# 3 mod 4
35
99
liste libres
Fig. 3.8 Scenario 5- Demande pour le bloc 17 qui est dej`a utilise.
22
Chapitre 4
La biblioth`
eque standard
4.1
Le fichier dinclusion <stdio.h> contient la definition du type FILE. Ce type est une structure
contenant les informations necessaires au syst`eme pour la manipulation dun fichier ouvert. Le
contenu exact de cette structure peut varier dun syst`eme `a lautre (UNIX, VMS, autre).
Toutes les fonctions dE/S utilisent en premier argument un pointeur sur une telle structure :
FILE *. Le role de cet argument est dindiquer le flux sur lequel on doit effectuer loperation
decriture ou de lecture.
Pour pouvoir utiliser une fonction dentree-sortie il faut donc avoir une valeur pour ce premier
argument, cest le role de la fonction fopen de nous fournir ce pointeur en ouvrant le fichier.
Les deux fonctions printf et scanf sont des synonymes de
fprintf(stdout, format, ...)
et
fscanf(stdin, format, ...)
o`
u stdout et stdin sont des expressions de type FILE * definies sous forme de macro-definitions
dans le fichier <stdio.h> . Avec POSIX ce sont effectivement des fonctions.
Sur les syst`eme de la famille UNIX les fichiers ouverts par un processus le restent dans ses fils.
Par exemple le shell a en general trois flux standards :
stdin le terminal ouvert en lecture.
stdout le terminal ouvert en ecriture.
stderr le terminal ouvert en ecriture, et en mode non bufferise.
ainsi si lexecution dun programme C est realisee `a partir du shell le programme C a dej`a ces
trois descripteurs de fichiers utilisables. Cest pourquoi il est en general possible dutiliser printf
et scanf sans ouvrir prealablement de fichiers. Mais si lentree standard nest pas ouverte, scanf
echoue :
#include <stdio.h>
main()
{
int i;
if (scanf("%d", &i) == EOF)
{
printf("l\entree standard est fermee\n");
}
else
{
printf("l\entree standard est ouverte\n");
23
`
CHAPITRE 4. LA BIBLIOTHEQUE
STANDARD
24
}
}
4.1.1
4.1.2
Permet dassocier un descripteur dej`a utilise `a une autre ouverture de fichier. Ceci permet de
realiser facilement les redirections du shell.
FILE *freopen(const char *ref,
const char *mode,
FILE *f)
Par exemple les redirections de la ligne shell :
com <ref1 >>ref2
peuvent etre realisees avec
25
4.1.3
Cr
eation de fichiers temporaires
La fonction
#include <stdio.h>
FILE *tmpfile(void);
cree et ouvre en ecriture un nouveau fichier temporaire, qui sera detruit (un unlink est realise
immediatement) `a la fin de lexecution du processus, attention le descripteur est la aussi herite
par les fils, et il faut en gerer le partage. Cette fonction utilise la fonction
int mkstemp(char *patron);
Les 6 dernier caract`ere du chemin patron doivent etre XXXXXX il seront remplace par une
chaine rendant le nom unique, ce chemin sera utilise pour ouvrir un fichier temporaire avec loption
creation et echec sur creation avec les droit 0600 ce qui permet deviter des troux de securite. La
fonction retourne le descripteur. Attention mkstemp nassure pas que le fichier sera detruit apr`es
utilisation comme cetait le cas avec tmpfile , par contre il devient tr`es difficile de realiser une
attaque sur les fichiers temporaire creer par mkstemp.
4.1.4
Les deux fonctions suivantes permettent decrire et de lire des zones memoire, le contenu de
la memoire est directement ecrit sur disque sans transformation, et reciproquement le contenu du
disque est place tel quel en memoire. Linteret de ces fonctions est dobtenir des entrees sorties
plus rapides et des sauvegardes disque plus compactes mais malheureusement illisibles (binaire).
Dautre part les fonction de lecture et decriture sont exactement symetrique ce qui nest pas le
cas de scanf et printf
#include <stdio.h>
int fwrite(void *add, size_t ta, size_t nbobjets, FILE *f);
Ecrit nbobjets de taille ta qui se trouvent `a ladresse add dans le fichier de descripteur f.
#include <stdio.h>
int fread(void *add, size_t ta, size_t nbobjets, FILE *f);
Lit nbobjets de taille ta dans le fichier de descripteur f et les place `a partir de ladresse add
en memoire.
Attention : La fonction fread retourne 0 si lon essaye de lire au del`a du fichier. Pour ecrire
une boucle de lecture propre on utilise la fonction feof(FILE *) :
int n[2];
while (fread(n, sizeof(int), 2, f), !feof(f))
printf("%d %d \n", n[0], n[1]);
`
CHAPITRE 4. LA BIBLIOTHEQUE
STANDARD
26
4.1.5
Acc`
es s
equentiel
4.1.6
Le pointeur de fichier est un entier long qui indique `a partir de quel octet du fichier la prochaine
fonction dentree-sortie doit seffectuer.
En debut de fichier cet entier est nul.
#include <stdio.h>
int fseek(FILE *f, long pos, int direction);
f le descripteur du fichier dans lequel ont deplace le pointeur.
direction est une des trois constantes enti`eres suivantes :
SEEK SET positionnement sur loctet pos du fichier
SEEK CUR positionnement sur le pos-i`eme octet apr`es la position courante du pointeur de
fichier. (equivalent `a SEEK SET courant+pos).
SEEK END positionnement sur le pos-i`eme octet apr`es la fin du fichier.
Remarquer que pos est un entier signe : il est possible se placer sur le 4i`eme octet avant la fin
du fichier :
fseek(f, -4L, SEEK_END);
4.1.7
Un exemple dacc`
es direct sur un fichier dentiers.
La fonction suivante lit le n-i`eme entier dun fichier dentiers prealablement ecrit grace `a
fwrite :
int lirenieme(int n, FILE *f)
{
int buf;
4.1.8
La fonction ftell
long int ftell(FILE *);
27
4.2
La biblioth`eque standard utilise des tampons pour minimiser le nombre dappels syst`eme. Il est
possible de tester lefficacite de cette bufferisation en comparant la vitesse de recopie dun meme
fichier avec un tampon de taille 1 octet et un tampon adapte `a la machine, la difference devient
vite tr`es importante. Une facon simple de le percevoir est decrire un programme com qui realise
des ecritures sur la sortie standard ligne par ligne, de regarder sa vitesse puis de comparer avec la
commande suivantes :com | cat la biblioth`eque standard utilisant des buffer differents dans les
deux cas une difference de vitese dexecution est perceptible (sur une machine lente la difference
de vitesse est evidente, mais elle existe aussi sur une rapide. . .).
4.2.1
Le mode de bufferisation des fichiers ouverts par la biblioth`eque standard depend du type de
peripherique.
Si le fichier est un terminal la bufferisation est faite ligne `a ligne.
En ecriture le tampon est vide `a chaque ecriture dun \n , ou quand il est plein
(premi`ere des deux occurences).
En lecture le tampon est rempli apr`es chaque validation (RC), si lon tape trop de
caract`eres le terminal proteste (beep) le buffer clavier etant plein.
Si le fichier est sur un disque magn
etique
En ecriture le tampon est vide avant de deborder.
En lecture le tampon est rempli quand il est vide.
Le shell de login change le mode de bufferisation de stderr qui est un fichier terminal `a non
bufferise.
Nous avons donc `a notre disposition trois modes de bufferisation standards :
Non bufferise (sortie erreur standard),
Bufferise par ligne (lecture/ecriture sur terminal),
Bufferise par blocs (taille des tampons du buffer cache).
Un exemple de reouverture de la sortie standard, avec perte du mode de bufferisation :
#include <stdio.h>
main()
{
freopen("/dev/tty", "w", stderr);
fprintf(stderr, "texte non termine par un newline ");
sleep(12);
exit(0); /* realise fclose(stderr) qui realise fflush(stderr) */
}
Il faut attendre 12 secondes laffichage.
4.2.2
Un tampon alloue automatiquement (malloc) est associe `a chaque ouverture de fichier par
fopen au moment de la premi`ere entree-sortie sur le fichier.
`
CHAPITRE 4. LA BIBLIOTHEQUE
STANDARD
28
bufferise
Non bufferise
Mon buffer
bufferise par ligne (ex: les terminaux)
Attention : Il ne faut pas appeler cette fonction apr`es lallocation automatique realisee par la
biblioth`eque standard apr`es le premier appel `a une fonction dentree-sortie sur le fichier.
Il est fortement conseille que la zone memoire pointee par adresse soit au moins dune taille egale
`a taille.
Seul un passage au mode bufferise en ligne ou non bufferise peut etre realise apr`es lallocation
automatique du tampon, au risque de perdre ce tampon (absence d appel de free). Ce qui permet
par exemple de changer le mode de bufferisation de la sortie standard apr`es un fork. Attention
ce peut etre dangereux, pour le contenu courant du tampon comme le montre lexemple suivant.
Avant cette fonction de norme POSIX on utilisait trois fonctions :
void setbuf(FILE *f, char *buf);
void setbuffer(FILE *f,char *adresse,size_t t);
void setlignebuf(FILE *f);
4.3
29
*/
4.4
#include <stdlib.h>
int system(const char *chaine_de_commande);
Cree un processus /bin/posix/sh qui execute la commande ; il y a attente de la fin du shell,
(la commande peut elle etre lancee en mode detache ce qui fait que le shell retourne immediatement
`
CHAPITRE 4. LA BIBLIOTHEQUE
STANDARD
30
4.5
exit
#include <stdlib.h>
void _exit(int valeur);
La primitive exit est la fonction de terminaison bas niveau
elle ferme les descripteurs ouverts par open, opendir ou herites du processus p`ere.
la valeur est fournie au processus p`ere qui la recup`ere par lappel syst`eme wait. Cette valeur
est le code de retour de processus en shell.
Cette primitive est automatiquement appelee `a la fin de la fonction main (sauf en cas dappels
recursifs de main).
exit
#include <stdlib.h>
void exit(int valeur);
la fonction exit :
lance les fonctions definies par atexit.
ferme lensemble des descripteurs ouverts grace `a la biblioth`eque standard (fopen).
detruit les fichiers fabriques par la primitive tmpfile
appelle exit avec valeur.
atexit La primitive atexit permet de specifier des fonctions `a appeler en fin dexecution, elle
sont lancees par exit dans lordre inverse de leur positionnement par atexit.
#include <stdlib.h>
int atexit(void (*fonction) (void ));
Exemple :
void bob(void) {printf("coucou\n");}
void bib(void) {printf("cuicui ");}
main(int argc)
{
atexit(bob);
atexit(bib);
if (argc - 1)
exit(0);
else
_exit(0);
}
$ make atexit
cc
atexit.c -o atexit
$ atexit
$ atexit unargument
cuicui coucou
$
4.6
31
4.7
Cr
eation et destruction de r
epertoires
mode);
Destruction :
int rmdir(char *ref);
avec les memes restrictions que pour les shells sur le contenu du repertoire (impossible de
detruire un repertoire non vide).
32
`
CHAPITRE 4. LA BIBLIOTHEQUE
STANDARD
Chapitre 5
Appels syst`
eme du Syst`
eme de
Gestion de Fichier
Les appels syst`eme dentrees-sorties ou entrees-sorties de bas niveau sont rudimentaires mais
polymorphes, en effet cest eux qui permettent decrire des programmes independamment des supports physiques sur lesquels se font les entrees/sorties et de pouvoir facilement changer les supports
physiques associes a une entree-sortie.
Les appels syst`eme du syst`eme de gestion de fichier sont :
open/creat ouverture/creation dun fichier
read/write lecture/ecriture sur un fichier ouvert
lseek deplacement du pointeur de fichier
dup,dup2 copie douverture de fichier
close fermeture dun fichier
mount chargement dun disque
mknode creation dun inode de fichier special
pipe creation dun tube
fcntl manipulation des caracteristiques des ouvertures de fichiers
Les appels syst`eme sont realises par le noyau et retournent -1 en cas derreur.
5.1
open
#include <fcntl.h>
int open(char *ref, int mode, int perm);
Ouverture du fichier de reference (absolue ou relative `a .) ref.
Le mode douverture est une conjonction des masques suivants :
O_RDONLY
O_WRONLY
O_RDWR
O_NDELAY
O_APPEND
O_CREAT
O_TRUNC
O_EXCL
/*
/*
/*
/*
/*
/*
/*
/*
table des
descripteurs
0
1
Dans chaque
processus
la table systme
des fichiers ouverts
la table des
inodes
en mmoire
Dans le noyau
Buffer
cache
donnes
inodes
Sur Disque
34
`
`
CHAPITRE 5. APPELS SYSTEME
DU SYSTEME
DE GESTION DE FICHIER
5.1. OPEN
35
Dans le
processus
Dans le noyau
inodes en mmoire
descripteurs
0
1
2
1 rd
Dans le
processus
1 wr Dans le noyau
1 wr
descripteurs
0
1
2
fd
vers
le buffer
cache et
le disque
inodes en mmoire
1 rw
1 rd
1 wr
1 wr
vers
le buffer
cache et
le disque
fd=open("toto",O_RDWR |O_CREAT,0666);
Fig. 5.2 Avant louverture, descripteurs standard ouverts, puis apr`es louverture de toto.
Le param`etre permission na de sens qu`a la creation du fichier, il permet de positionner les
valeurs du champ mode de linode. Les droits effectivement positionnes dependent de la valeur
de umask, grace `a la formule droits = perm & ~ umask. La valeur par defaut de umask est 066
(valeur octale).
La valeur de retour de open est le numero dans la table de descripteurs du processus qui a ete
utilise par open. Ce numero est appele descripteur de louverture. Ce descripteur est utilise dans
les autres appels syst`eme pour specifier louverture de fichier sur laquelle on veut travailler1 , et -1
en cas dechec de louverture.
5.1.1
D
eroulement interne dun appel de open
1 Un
m
eme fichier peut
etre ouvert plusieurs fois.
`
`
CHAPITRE 5. APPELS SYSTEME
DU SYSTEME
DE GESTION DE FICHIER
36
5.2
creat
5.3
read
5.4
write
5.5. LSEEK
37
Remarquons ici encore le polymorphisme de ces deux appels syst`eme qui permet de lire et decrire
sur une grande variete de peripheriques en utilisant une seule syntaxe. Le code C utilisant lappel syst`eme marchera donc indifferemment sur tous les types de peripheriques qui sont definis
dans le syst`eme de fichier. Par exemple, il existe deux peripheriques logiques qui sont /dev/null
et /dev/zero (que lon ne trouve pas sur toutes les machines). Le premier est toujours vide en
lecture et les ecritures nont aucun effet (il est donc possible de deverser nimporte quoi sur ce
peripherique). Le deuxi`eme fournit en lecture une infinite de zero et naccepte pas lecriture.
5.5
lseek
#include <fcntl.h>
off_t lseek(int d, off_t offset, int direction)
lseek permet de deplacer le curseur de fichier dans la table des fichiers ouverts du syst`eme.
offset un deplacement en octets.
d le descripteur.
direction une des trois macros L SET, L INCR, L XTND.
L SET la nouvelle position est offset sauf si offset est superieur `a la taille du fichier, auquel cas
la position est egale `a la taille du fichier. Si loffset est negatif, alors la position est zero.
L INCR la position courante est incrementee de offset place (meme contrainte sur la position
maximum et la position minimum).
L XTND Deplacement par rapport `a la fin du fichier, cette option permet daugmenter la taille
du fichier (ne pas creer de fichiers virtuellement gros avec ce mecanisme, ils posent des
probl`emes de sauvegarde).
La valeur de retour de lseek est la nouvelle position du curseur dans le fichier ou -1 si lappel
a echoue.
5.6
dup et dup2
Les appels dup et dup2 permettent de dupliquer des entrees de la table des descripteurs du
processus.
int
`
`
CHAPITRE 5. APPELS SYSTEME
DU SYSTEME
DE GESTION DE FICHIER
38
close(tempout);
close(1);
newout = dup(oldout);
close(oldout);
Il est aussi possible de choisir le descripteur cible avec
int ok = dup2(int source, int destination);
Recopie du descripteur source dans lentree destination de la table des descripteurs. Si
destination designe le descripteur dun fichier ouvert, celui-ci est prealablement ferme avant
duplication. Si destination nest pas un numero de descripteur valide, il y a une erreur, retour
-1.
5.7
close
5.8
fcntl
Lappel syst`eme fnctl permet de manipuler les ouverture de fichier apr`es louverture, bien
sur il nest pas possible de changer le mode douverture (lecture/ecriture/lecture-ecriture) apr`es
louverture.
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int fcntl(int desc, int commande);
int fcntl(int desc, int commande, long arg);
int fcntl(int desc, int commande, struct flock *verrou);
Lappel syst`eme fnctl permet de positionner des verrous de fichier voire le chapitre 12. Lappel
syst`eme fnctl permet la manipulation de certains des drapeaux douverture :
O APPEND
5.8. FCNTL
39
dup2(fd,1);
descripteurs
0
1
2
fd
2 rw
1 rd
1 wr
close(fd);
0
1
2
1 rw
1 rd
1 wr
40
`
`
CHAPITRE 5. APPELS SYSTEME
DU SYSTEME
DE GESTION DE FICHIER
Chapitre 6
Les processus
6.1
Un processus est un ensemble doctets (en langage machine) en cours dexecution, en dautres
termes, cest lexecution dun programme.
Un processus UNIX se decompose en :
1. un espace dadressage (visible par lutilisateur/programmeur)
2. Le bloc de controle du processus (BCP) lui-meme decompose en :
une entree dans la table des processus du noyau struct proc
definie dans <sys/proc.h>.
une structure struct user appelee zone u definie dans <sys/user.h>
Les processus sous Unix apportent :
La multiplicite des executions
Plusieurs processus peuvent etre lexecution dun meme programme.
La protection des executions
Un processus ne peut executer que ses instructions propres et ce de facon sequentielle ; il ne
peut pas executer des instructions appartenant `a un autre processus.
Les processus sous UNIX communiquent entre eux et avec le reste du monde grace aux
appels syst`eme.
6.1.1
Cr
eation dun processus - fork()
P1
le noyau
P5
P1
les processus
P5
42
Tous les processus sauf le processus didentification 0, sont crees par un appel `a fork.
Le processus qui appelle le fork est appele processus p`ere.
Le nouveau processus est appele processus fils.
Tout processus a un seul processus p`ere.
Tout processus peut avoir zero ou plusieurs processus fils.
Chaque processus est identifie par un numero unique, son PID.
Le processus de PID=0 est cree manuellement au demarrage de la machine, ce processus
a toujours un role special1 pour le syst`eme, de plus pour le bon fonctionement des programmes
utilisant fork() il faut que le PID zero reste toujours utilise. Le processus zero cree, grace `a un
appel de fork, le processus init de PID=1.
Le processus de PID=1 de nom init est lancetre de tous les autres processus (le processus 0
ne realisant plus de fork()), cest lui qui accueille tous les processus orphelins de p`ere (ceci a fin
de collecter les information `a la mort de chaque processus).
6.2
Les compilateurs nous permettent de creer des fichiers executables. Ces fichiers ont le format
suivant qui permet au noyau de les transformer en processus :
Une en-tete qui decrit lensemble du fichier, ses attributs et sa carte des sections.
La taille `a allouer pour les variables non initialisees.
Une section TEXT qui contient le code (en langage machine)
Une section donnees (DATA) codee en langage machine qui contient les donnees initialisees.
Eventuellement dautres sections : Table des symboles pour le debugeur, Images, ICONS,
Table des chanes, etc.
Pour plus dinformations se reporter au manuel a.out.h sur la machine.
6.3
Chargement/changement dun ex
ecutable
de pages
43
Pile
Donnes non-initialises
Donnes initialise
Texte
} initialise zro
par exec
lu par exec
Adresse Basse =0
Le code du programme g`ere les extensions de pile (appel ou retour de fonction), cest le noyau qui
alloue lespace necessaire `a ces extensions. Sur certains syst`emes on trouve une fonction alloca()
qui permet de faire des demandes de memoire sur la pile.
Un processus UNIX pouvant sexecuter en deux modes (noyau, utilisateur), une pile privee sera
utilisee dans chaque mode.
La pile noyau sera vide quand le processus est en mode utilisateur.
Le tas est une zone o`
u est realisee lallocation dynamique avec les fonctions Xalloc().
6.4
Tous les processus sont associes `a une entree dans la table des processus qui est interne au
noyau. De plus, le noyau alloue pour chaque processus une structure appelee zone u , qui contient
des donnees privees du processus, uniquement manipulables par le noyau.
La table des processus nous permet dacceder `a la table des regions par processus qui permet dacceder `a la table des
regions. Ce double niveau dindirection permet de faire partager des regions.
Dans lorganisation avec une memoire virtuelle, la table des regions est materialisee logiquement
dans la table de pages.
Les structures de regions de la table des regions contiennent des informations sur le type, les
droits dacc`es et la localisation (adresses en memoire ou adresses sur disque) de la region.
Seule la zone u du processus courant est manipulable par le noyau, les autres sont inaccessibles. Ladresse de la zone u est placee dans le mot detat du processus.
6.5
Quand un processus realise un fork, le contenu de lentree de la table des regions est duplique,
chaque region est ensuite, en fonction de son type, partagee ou copiee.
Quand un processus realise un exec, il y a liberation des regions et reallocation de nouvelles
regions en fonction des valeurs definies dans le nouvel executable.
44
zone u
Mmoire Centrale
Fig. 6.3 Table des regions, table des regions par processus
zone u
zone u
copie
Table des processus
fork()
pre =
fils =
Mmoire Centrale
zone u
ancienne
entre
exec()
Mmoire Centrale
6.6
45
Le contexte dun processus est lensemble des donnees qui permettent de reprendre lexecution
dun processus qui a ete interrompu.
Le contexte dun processus est lensemble de
1. son etat
2. son mot detat : en particulier
La valeur des registres actifs
Le compteur ordinal
3. les valeurs des variables globales statiques ou dynamiques
4. son entree dans la table des processus
5. sa zone u
6. Les piles user et system
7. les zones de code et de donnees.
Le noyau et ses variables ne font partie du contexte daucun processus !
Lexecution dun processus se fait dans son contexte.
Quand il y a changement de processus courant, il y a realisation dune commutation de mot
d
etat et dun changement de contexte. Le noyau sexecute alors dans le nouveau contexte.
6.7
Commutation de mot d
etat et interruptions.
Ces fonctions de tr`es bas niveau sont fondamentales pour pouvoir programmer un syst`eme
dexploitation.
Pour etre execute et donner naissance `a un processus, un programme et ses donnees doivent
etre charges en memoire centrale. Les instructions du programme sont transferees une `a une de la
memoire centrale sur lunite centrale o`
u elles sont executees.
Lunite centrale :
Elle comprend des circuits logiques et arithmetiques qui effectuent les instructions mais aussi des
memoires appelees registres.
Certains de ces registres sont specialises directement par les constructeurs de lunite centrale,
dautres le sont par le programmeur du noyau. Quelques registres specialises :
Laccumulateur qui recoit le resultat dune instruction ; sur les machines `a registres multiples,
le jeu dinstructions permet souvent dutiliser nimporte lequel des registres comme accumulateur.
le registre dinstruction (qui contient linstruction en cours)
le compteur ordinal (adresse de linstruction en memoire) Ce compteur change au cours de
la realisation dune instruction pour pointer sur la prochaine instruction `a executer, la majorite des instructions ne font quincrementer ce compteur, les instructions de branchement
realisent des operations plus complexes sur ce compteur : affectation, incrementation ou
decrementation plus importantes.
le registre dadresse
les registres de donn
ees qui sont utilises pour lire ou ecrire une donnee `a une adresse specifiee
en memoire.
les registres d
etat du processeur : (actif, mode (user/system), retenue, vecteur dinterruptions,
etc)
les registres d
etat du processus droits, adresses, priorites, etc
Ces registres forment le contexte dunit
e centrale dun processus. A tout moment, un processus est caracterise par ces deux contextes : le contexte dunite centrale qui est compose des memes
donnees pour tous les processus et le contexte qui depend du code du programme execute. Pour
46
fonction de traitement
horloge
clockintr
disques
diskintr
console
ttyintr
autres peripheriques
devintr
appel system
sottintr
autre interruption
otherintr
pouvoir executer un nouveau processus, il faut pouvoir sauvegarder le contexte dunite centrale
du processus courant (mot detat), puis charger le nouveau mot detat du processus `a executer.
Cette operation delicate realisee de facon materielle est appelee commutation de mot d
etat.
Elle doit se faire de facon non interruptible ! Cette Super instruction utilise 2 adresses qui sont
respectivement :
ladresse de sauvegarde du mot detat
ladresse de lecture du nouveau mot detat
Le compteur ordinal faisant partie du mot detat, ce changement provoque lexecution dans le
nouveau processus.
Cest le nouveau processus qui devra realiser la sauvegarde du contexte global. En general cest
le noyau qui realise cette sauvegarde, le noyau nayant pas un contexte du meme type.
Le processus interrompu pourra ainsi reprendre exactement o`
u il avait abandonne.
Les fonctions setjmp/longjmp permettent de sauvegarder et de reinitialiser le contexte dunite
central du processus courant, en particulier le pointeur de pile.
6.8
Les interruptions
Une interruption est une commutation de mot detat provoquee par un signal produit par le
materiel.
Ce signal etant la consequence dun evenement exterieur ou interieur, il modifie letat dun indicateur qui est reguli`erement teste par lunite centrale.
Une fois que le signal est detecte, il faut determiner la cause de linterruption. Pour cela on utilise
un indicateur, pour les differentes causes, On parle alors du vecteur dinterruptions.
Trois grands types dinterruptions :
externes (independantes du processus) interventions de loperateur, pannes,etc
d
eroutements erreur interne du processeur, debordement, division par zero, page fault etc
(causes qui entraine la realisation dune sauvegarde sur disque de limage memoire core
dumped en general)
appels syst`
emes demande dentree-sortie par exemple.
Suivant les machines et les syst`emes un nombre variable de niveaux dinterruption est utilise.
Ces differentes interruptions ne realisent pas necessairement un changement de contexte complet du processus courant.
Il est possible que plusieurs niveaux dinterruption soient positionnes quand le syst`eme les
consulte. Cest le niveau des differentes interruptions qui va permettre au syst`eme de selectionner
linterruption `a traiter en priorite.
Lhorloge est linterruption la plus prioritaire sur un syst`eme Unix.
`
6.9. LE PROBLEME
DES CASCADES DINTERRUPTIONS
Systme
traitement
dinterruption
Processus 1
47
Processus 2
interruption
Sauvegarde
du contexte
du Processus 1
traitement
Chargement
du contexte
du processus 2
Acquittement
Commutations dtat
6.9
Le probl`
eme des cascades dinterruptions
Si pendant le traitement dune interruption, une autre interruption se produit, et que ceci se
rep`ete pendant le traitement de la nouvelle interruption, le syst`eme ne fait plus progresser les
processus ni les interruptions en cours de traitement ...
Il est donc necessaire de pouvoir retarder ou annuler la prise en compte dun ou plusieurs
signaux dinterruptions. Cest le role des deux mecanismes de masquage et de d
esarmement
dun niveau dinterruption. Masquer, cest ignorer temporairement un niveau dinterruption.
Si ce masquage est fait dans le mot detat dun traitement dinterruption, `a la nouvelle commutation detat, le masquage disparat ; les interruptions peuvent de nouveau etre prises en compte.
Desarmer, cest rendre le positionnement de linterruption caduque. (Il est clair que ceci ne peut
sappliquer aux deroutements).
6.9.1
Nous nous placons dans le cas dun syst`eme qui utilise un mecanisme de swap pour gerer la
memoire ; nous etudierons ensuite le cas des syst`emes de gestion paginee de la memoire (les couples
detats 3,5 et 4,6 y sont fusionnes).
6.9.2
Listes des
etats dun processus
48
Retour au
mode utilisateur
Excution
en mode noyau
gestion
interruption
premption
exit
zombie
9
sleep
Prempt
ordonancement
du processus
Examiner
les signaux
3
Prt et en mmoire
wakeup
Endormi
en mmoire
Examiner
et traiter
les signaux
mmoire
suffisante
4
swapout
swapout
swapin
centrale
swap
Cration
fork
8
mmoire
insuffisante
Endormi
6
en zone de swap
wakeup
5
Prt
en zone de swap
6.10
Lecture du diagramme d
etat.
Le diagramme des transitions detat permet de decrire lensemble des etats possibles dun
processus. Il est clair que tout processus ne passera pas necessairement par tous ces differents
etats.
La naissance dun processus a lieu dans letat 8 apr`es lappel syst`eme fork execute par un
autre processus. Il devient au bout dun certain temps pret `a sexecuter. Il passe alors dans
letat execute en mode noyau o`
u il termine sa partie de lappel syst`eme fork. Puis le processus
termine lappel syst`eme et passe dans letat execute en mode utilisateur. Passe une certaine
periode de temps (variable dun syst`eme `a lautre), lhorloge peut interrompre le processeur. Le
processus rentre alors en mode noyau, linterruption est alors realisee avec le processus en mode
noyau.
Au retour de linterruption, le processus peut etre pr
eempt
e (etant reste tout son quantum de
temps sur le cpu), cest `a dire, il reste pret `a sexecuter mais un autre processus est elu. Cet etat
7 est logiquement equivalent `a letat 3, mais il existe pour materialiser le fait quun processus ne
peut etre preempte quau moment o`
u il retourne du mode noyau au mode utilisateur. Quand un
processus preempte est reelu, il retourne directement en mode utilisateur.
Un appel syst`eme ne peut etre preempte. On peut detecter en pratique cette r`egle, en effet
6.11. UN EXEMPLE DEXECUTION
49
6.11
Un exemple dex
ecution
Placons-nous dans la situation suivante : lensemble de la memoire est occupe par des processus,
mais, le processus le plus prioritaire est un processus dans letat 5, soit : pret `a sexecuter en
zone de swap. Pour pouvoir executer ce processus, il faut le placer dans letat 3, soit : pret `a
sexecuter en memoire. Pour cela le syst`eme doit liberer de la memoire (faire de la place), en
faisant passer des processus des etats 3 ou 4 en zone de swap (swapout) donc les faire passer dans
les etats 5 et 6.
Cest au swappeur de realiser les deux operations :
Selectionner une victime (le processus le plus approprie), pour un transfert hors memoire
centrale (swapout).
realiser ce transfert.
une fois quune place suffisante est liberee, le processus qui a provoque le swapout est charge
en memoire (swapin).
Le processus a un controle sur un nombre reduit de transitions : il peut faire un appel syst`eme,
realiser un exit, realiser un sleep, les autres transitions lui sont dictees par les circonstances.
Lappel `a exit() fait passer dans letat zombie, il est possible de passer `a letat zombie sans
que le processus ait explicitement appele exit() (`a la reception de certains signaux par exemple).
Toutes les autres transitions detat sont selectionnees et realisees par le noyau selon des r`egles bien
precises. Une de ces r`egles est par exemple quun processus en mode noyau ne peut etre preempte3 .
Certaines de ces r`egles sont definies par lalgorithme dordonnancement utilise.
6.12
La table des processus est dans la memoire du noyau. Cest un tableau de structure proc
(<sys/proc.h>). Cette structure contient les informations qui doivent toujours etre accessibles
par le noyau.
etat se reporter au diagramme, ce champ permet au noyau de prendre des decisions sur les
changements detat `a effectuer sur le processus.
adresse de la zone u
adresses taille et localisation en memoire (centrale, secondaire). Ces informations permettent de
transferer un processus en ou hors memoire centrale.
UID proprietaire du processus, permet de savoir si le processus est autorise `a envoyer des signaux
et `a qui il peut les envoyer.
PID,PPID lidentificateur du processus et de son p`ere. Ces deux valeurs sont initialisees dans
letat 8, creation pendant lappel syst`eme fork.
ev`
enement un descripteur de lev`enement attendu quand le processus est dans un mode endormi.
Priorit
es Plusieurs param`etres sont utilises par lordonnanceur pour selectionner lelu parmi les
processus prets.
vecteur dinterruption du processus ensemble des signaux recus par le processus mais pas
encore traites.
3 Exercice
: Donner un exemple.
50
divers des compteurs utilises pour la comptabilite (pour faire payer le temps CPU utilise) et
que lon peut manipuler par la commande alarm, des donnees utilisees par limplementation
effective du syst`eme, etc.
6.13
La zone u
La zone u de type struct user definie dans <sys/user.h> est la zone utilisee quand un processus sexecute que ce soit en mode noyau ou mode utilisateur. Une unique zone u est accessible
`a la fois : celle de lunique processus en cours dexecution (dans un des etats 1 ou 2).
Contenu de la zone u :
pointeur sur la structure de processus de la table des processus.
uid r
eel et effectif de lutilisateur qui determine les divers privil`eges donnes au processus, tels
que les droits dacc`es `a un fichier, les changements de priorite, etc.
Compteurs des temps (users et system) consommes par le processus
Masque de signaux Sur syst`eme V sous BSD dans la structure proc
Terminal terminal de controle du processus si celui-ci existe.
erreur stockage de la derni`ere erreur rencontree pendant un appel syst`eme.
retour stockage de valeur de retour du dernier appel syst`eme.
E/S les structures associees aux entrees-sorties, les param`etres utilises par la biblioth`eque standard, adresses des buffers, tailles et adresses de zones `a copier, etc.
. et / le repertoire courant et la racine courante (c.f. chroot())
la table des descripteurs position variable dun implementation `a lautre.
limites de la taille des fichiers de la memoire utilisable etc 41 (c.f. ulimit en Bourne shell et limit
en Csh ).
umask masque de creation de fichiers.
6.14
Acc`
es aux structures proc et user du processus courant
Les informations de la table des processus peuvent etre lues grace `a la commande shell ps. Ou
par des appels syst`eme. Par contre, les informations contenues dans la zone u ne sont accessibles
que par une reponse du processus lui-meme (en progammation objet, on dit que ce sont des variables dinstances privees), do`
u les appels syst`eme suivants :
times, chroot, chdir, fchdir, getuid, getgid, ..., setuid, ..., ulimit, nice, brk,
sbrk.
Qui permettent de lire ou de changer le contenu des deux structures.
6.14.1
#include <sys/times.h>
clock_t times(struct tms *buffer);
times remplit la structure pointee par buffer avec des informations sur le temps machine utilise dans les etat 1 et 2.
La structure? :
struct tms {
clock_t
clock_t
tms_utime;
tms_stime;
/* user time */
/* system time */
tms_cutime;
tms_cstime;
51
contient des temps indiques en microsecondes 10-6 secondes, la precision de lhorloge est par
defaut sur les HP9000 700/800 de 10 microsecondes.
6.14.2
Changement du r
epertoire racine pour un processus.
#include <unistd.h>
int chroot(const char *path);
permet de definir un nouveau point de depart pour les references absolues (commencant par
/). La reference .. de ce repertoire racine est associee `a lui-meme, il nest donc pas possible de
sortir du sous-arbre defini par chroot. Cet appel est utilise pour rsh et ftp, et les comptes pour
invites.
Les appels suivants permettent de changer le repertoire de travail de reference . et donc
linterpretation des references relatives :
int chdir(char *ref);
int fchdir(int descripteur);
6.14.3
R
ecup
eration du PID dun processus
#include <unistd.h>
pid_t
getpid(void);
pid_t
getpgrp(void);
pid_t
getppid(void);
pid_t
getpgrp2(pid_t pid);
Lappel getpid() retourne le PID du processus courant, getppid le PID du processus p`ere,
getpgrp le PID du groupe du processus courant, getpgrp2 le PID du groupe du processus pid (si
pid=0 alors equivalent `a getpgrp).
6.14.4
52
6.15
#include <ulimit.h>
long ulimit(int cmd,...);
La commande cmd est
UL GETFSIZE retourne le taille maximum des fichiers en blocs.
UL SETFSIZE positionne cette valeur avec le deuxi`eme argument.
UL GETMAXBRK valeur maximale pour lappel dallocation dynamique de memoire : brk.
Ces valeurs sont heritees du processus p`ere.
La valeur FSIZE (taille maximum des fichiers sur disques en blocs) peut etre changee en ksh
avec ulimit [n].
6.15.1
#include <unistd.h>
int brk(const void *endds);
void *sbrk(int incr);
Les deux appels permettent de changer la taille du processus. Ladresse manipulee par les deux
appels est la premi`ere adresse qui est en dehors du processus. Ainsi on realise des augmentations
de la taille du processus avec des appels `a sbrk et on utilise les adresses retournees par sbrk pour
les appels `a brk pour reduire la taille du processus. On utilisera de preference pour les appels
`a sbrk des valeurs de incr qui sont des multiples de la taille de page. Le syst`eme realisant des
deplacement du point de rupture par nombre entier de pages (ce qui est logique dans un syst`eme de
memoire pagine). A ne pas utiliser en conjonction avec les fonctions dallocation standard malloc,
calloc, realloc, free.
6.15.2
Permet de changer la valeur de nice utilisee par le processus. Si lon a des droits privilegies la
valeur peut etre negative. La valeur de nice est toujours comprise entre -20 et +20 sous linux. Seul
le super utilisateur pouvant utiliser une valeur negative.
#include <unistd.h>
int nice(int valeur);
La commande shell renice priorite -p pid -g pgrp -u user permet de changer le nice
dun processus actif.
6.15.3
Lappel umask permet de specifier quels droits doivent etre interdits en cas de creation de
fichier. cf. 5.1
#include <sys/stat.h>
mode_t umask(mode_t mask);
la valeur retournee est lancienne valeur.
`
6.16. LAPPEL SYSTEME
FORK
6.16
53
Lappel syst`
eme fork
lappel syst`eme fork permet le creation dun processus clone du processus courrant.
pid_t
fork(void);
6.17
Lappel syst`
eme exec
#include <unistd.h>
extern char **environ;
int execl( const char *path, const char *arg0, ...,NULL);
int execv(const char *path, char * const argv[]);
int execle( const char *path, const char *arg0, ...,NULL,
int execve(const char *file, char * const argv[], char * const envp[]);
int execlp( const char *file,const char *arg0, ... , NULL );
int execvp(const char *file, char * const argv[]);
Informations conservees par le processus : PID PPID PGID ruid suid (pour leuid cf le
setuidbit de chmod ), nice, groupe dacc`es, catalogue courant, catalogue /, terminal de
controle, utilisation et limites des ressources (temps machine, memoire, etc), umask, masques
des signaux, signaux en attente, table des descripteurs de fichiers, verrous, session.
Quand le processus execute dans le nouvel executable la fonction :
main(int argc, char **argv,char **envp)
argv et env sont ceux qui ont ete utilises dans lappel de execve.
Les differents noms des fonction exec sont des mnemoniques :
l liste darguments
v arguments sont forme dun vecteur.
p recherche du fichier avec la variable denvironnement PATH.
e transmission dun environnement en dernier param`etre, en remplacement de lenvironnement
courant.
54
Chapitre 7
7.1
Le partage de lunit
e centrale
Ce partage doit etre fait non seulement entre les processus utilisateurs mais aussi entre les
differentes taches du syst`eme, scheduler, entrees-sorties, gestion des interruptions, etc.
Nous demandons de plus `a lalgorithme dordonnancement de nous assurer lexclusion mutuelle et labsence de famine, qui sont les points-clefs de la plupart des probl`emes dordonnancement. Linvention dun algorithme dordonnancement se base en generale sur des remarques
statistique sur le comportement des processus :
Le couple UC/ES (cpu/io), les processus ont tendance `a basculer constamment entre des
phases dentrees-sorties et des phases de calcul sur lunite centrale.
Les processus consommant de longues periodes dU.C. sont proportionnellement rares.
55
56
200
150
100
50
0
1
12
16
20
24
A court terme
E/S
U.C.
7.1.1
Famine
Notre premi`ere tache est daffecter une ressource (lUC par exemple) `a un unique processus `a
la fois (exclusion mutuelle) et sassurer de labsence de famine.
famine : un processus peut se voir refuser lacc`es `a une ressource pendant un temps indetermine,
il est dit alors que le processus est en famine.
Un syst`eme qui ne cree pas de cas de famine : fournira toujours la ressource demandee par un
processus, au bout dun temps fini.
Si on prend le cas des peripheriques (tels que les disques) lordonnancement peut se faire de
facon simple avec par exemple une file dattente (FIFO).
Pour lunite centrale on va devoir utiliser des structures de donnees plus complexes car nous
allons avoir besoin de gerer des priorites. Cest par exemple, autoriser lexistence de processus qui
evitent la file dattente. La structure de donnees utilisee peut parfaitement etre une file, une liste,
un arbre ou un tas, ceci en fonction de lelement-clef de notre algorithme de selection (age, priorite
simple, priorite `a plusieurs niveaux, etc).
Cette structure de donnees doit nous permettre dacceder `a tous les processus prets (eligibles).
7.1.2
Strat
egie globale
7.2. ORDONNANCEMENT SANS PREEMPTION.
57
Si on utilise trop de temps (1 milli-seconde) pour selectionner cet elu, le taux utile decrot tr`es
rapidement (ici on perd 9% du temps dunite centrale).
Par contre lordonnancement `a long terme peut etre plus long car il a lieu moins souvent (toutes
les secondes par exemple). La conception de lordonnanceur `a long terme est faite dans loptique
dobtenir un ordonnanceur `a court terme rapide.
7.1.3
Crit`
eres de performance
Les crit`
eres de performance des algorithmes dordonnancement
Taux dutilisation de lunite centrale
Debit
Temps reel dexecution
Temps dattente
Temps de reponse
Ces cinq crit`
eres sont plus ou moins mutuellement exclusifs.
Les comparaisons des differents algorithmes se fait donc sur une selection de ces crit`eres.
7.2
Ordonnancement sans pr
eemption.
7.3
Les algorithmes pr
eemptifs
58
7.3.1
7.3.2
Les algorithmes `
a queues multiples
Nous supposons que nous avons un moyen de differencier facilement les processus en plusieurs
classes de priorite differentes (cest le cas sous UNIX o`
u nous allons differencier les taches syst`eme,
comme le swappeur, des autres taches).
Pour selectionner un processus, le scheduler parcourt successivement les queues dans lordre
decroissant des priorites.
Un exemple de queues organisees en fonction du contenu des processus :
les processus syst`emes
les processus interactifs
les processus edition
les processus gros calcul
les processus des etudiants
pour quun processus etudiant soit execute il faut que toutes les autres files dattente soient vides ...
Une autre possibilite est de partager les quantums de temps sur les differentes queues.
Il est aussi possible de realiser differents algorithmes de scheduling sur les differentes queues :
Round Robin sur les processus interactifs
FCFS sur les gros calculs en tache de fond.
7.4
Le syst`eme dordonnancement des processus sous UNIX (BSD 4.3 et system V4) utilise plusieurs files dattente qui vont materialiser des niveaux de priorite differents et `a linterieur de ces
differents niveaux de priorite, un syst`eme de tourniquet.
7.4.1
Le scheduler parcourt les listes une par une de haut en bas jusqu`a trouver une liste contenant
un processus eligible. Ainsi tant quil y a des processus de categorie superieure `a executer les autres
processus sont en attente de lunite centrale.
interruptibles
59
swapper
non
interruptibles
Disk I/O
Attentes de :
Interne au Noyau
Buffer
Inode
tty input
tty output
enfants
priorit limite
niveau 0
Utilisateurs
niveau 1
niveau N
7.4.2
Evolution de la priorit
e
P cpu
+ 2 P nice
4
cette valeur est tronquee `a lintervalle PUSER..127. En fonction de cette valeur le processus
est place dans une des listes correspondant `a son niveau courant de priorite.
Ceci nous donne une priorite qui diminue lineairement en fonction de lutilisation de lunite
centrale (il advient donc un moment o`
u le processus devient le processus le plus prioritaire !).
P nice est une valeur specifiee par le programmeur grace `a lappel syst`eme nice. Elle varie entre
-20 et +20 et seul le super utilisateur peut specifier une valeur negative.
P cpu donne une estimation du temps passe par un processus sur lunite centrale. A chaque click
dhorloge, la variable p cpu du processus actif est incrementee. Ce qui permet de materialiser la
60
consommation dunite central du processus. Pour que cette valeur ne devienne pas trop penalisante
sur le long terme (comme pour un shell) elle est attenuee toute les secondes grace `a la formule
suivante :
P cpu =
2 load
P cpu + P nice
2 load + 1
la valeur de load (la charge) est calculee sur une moyenne du nombre de processus actifs
pendant une minute.
Pour ne pas utiliser trop de ressources, les processus qui sont en sommeil (sleep) voient leur
P cpu recalcule uniquement `a la fin de leur periode de sommeil grace `a la formule :
P cpu =
2 load
2 load + 1
sleep time
P cpu
la variable sleep time etant initialisee `a zero puis incrementee une fois par seconde.
7.4.3
La priorit
e des processus en mode syst`
eme d
epend de laction `
a r
ealiser.
PSWAP 0 priorite en cours de swap
PINOD 10 priorite en attendant une lecture dinformation sur le syst`eme de fichiers
PRIBIO 20 priorite en attente dune lecture/ecriture sur disque
PZERO 25 priorite limite
PWAIT 30 priorite dattente de base
PLOCK 35 priorite dattente sur un verrou
PSLEP 40 priorite dattente dun ev`enement
PUSER 50 priorite de base pour les processus en mode utilisateur
Le choix de lordre de ces priorites est tr`es important, en effet un mauvais choix peut entraner
une diminution importante des performances du syst`eme.
Il vaut mieux que les processus en attente dun disque soient plus prioritaires que les processus
en attente dun buffer, car les premiers risquent fort de liberer un buffer apr`es leur acc`es disque
(de plus il est possible que ce soit exactement le buffer attendu par le deuxi`eme processus). Si la
priorite etait inverse, il deviendrait possible davoir un interblocage ou une attente tr`es longue si
le syst`eme est bloque par ailleurs.
De la meme facons, le swappeur doit etre le plus prioritaire et non interruptible Si un
processus est plus prioritaire que le swappeur et quil doit etre swappe en memoire ...
En Demand-Paging le swappeur est aussi le processus qui realise les chargements de page, ce
processus doit etre le plus prioritaire.
Chapitre 8
La m
emoire
8.0.4
les m
emoires
8.0.5
La m
emoire centrale
La memoire est un tableau `a une dimension de mots machines (ou doctets), chacun ayant une
adresse propre. Les echanges avec lexterieur se font en general par des lectures ou des ecritures `a
des adresses specifiques.
Le syst`eme Unix est multi-tache,ceci pour maximiser lutilisation du cpu. Cette technique
pose comme condition obligatoire que la memoire centrale soit utilisee et/ou partagee entre les
differentes taches.
Les solutions de gestion de la memoire sont tr`es dependantes du materiel et ont mis longtemps
`a evoluer vers les solutions actuelles. Nous allons voir plusieurs approches qui peuvent servir dans
des situations particuli`eres .
La memoire est le point central dans un syst`eme dexploitation, cest `a travers elle que lunite
centrale communique avec lexterieur.
Mmoire
volatile
Registres
Mmoire cache
Mmoire centrale
Disques
Bandes magntiques
Mmoire
permanente
CHAPITRE 8. LA MEMOIRE
62
TYPE DE
MEMOIRE
TAILLE
(Octets)
TEMPS DACCES
(secondes)
CACHE
103-104
10-8
10
10-7
MEMOIRE
CENTRALE
106-107
COUT RELATIF
PAR BIT
DISQUE
108-109
10-3-10-2
10-2-10-3
BANDE
108-109
10-102
10-4
64Kilos octets
utilisateurs
FFFF
8.1. ALLOCATION CONTIGUE
63
0
le noyau
(moniteur)
Registre
Barrire
un programme
utilisateur
FFFF
8.1
8.1.1
Allocation contigu
e
Pas de gestion de la m
emoire
8.1.2
Le moniteur r
esidant
On cherche `a proteger le noyau des interferences possibles de la part des utilisateurs. Pour cela,
toute adresse dinstruction ou de donnee manipulee par un programme utilisateur est comparee `a
un registre barri`ere (fence register).
Tant que ladresse est superieure `a la barri`ere, ladresse est legale, sinon ladresse est une
reference illegale au moniteur et une interruption est emise (invalid adress).
Cette methode demande que pour tout acc`es `a la memoire une verification de la validite de
ladresse soit realisee. Ceci ralentit toute execution dun acc`es memoire. (Paterson donne comme
exemple de ralentissement des temps de 980 nanosecondes sans verification et 995 nanosecondes
avec verification). Globalement ce temps supplementaire peut etre oublie.
8.1.3
Le registre barri`
ere
8.1.4
Le registre base
Le mecanisme suivant est une notion plus utile et plus ergonomique pour decrire la zone
dadressage dun programme, et utile pour resoudre le probl`eme de deplacement des programmes
en memoire (relocation).
En effet, du fait que lon utilise un registre barri`ere, les adresses utilisables de la memoire ne
commencent plus `a 0000, alors que lutilisateur veut continuer `a utiliser des adresses logiques qui
commencent `a 0000.
CHAPITRE 8. LA MEMOIRE
64
Registre
Barrire
unit
centrale
A < Barrire
non
mmoire
oui
Intruption
Registre
Base
1400
unit
centrale
mmoire
+
0346
1746
0
le noyau
(moniteur)
Registre
Barrire
un programme
utilisateur
FFFF
8.1. ALLOCATION CONTIGUE
65
Moniteur
Barrire
1 swap out
P1
Zone
utilisateur
P2
2 swap in
8.1.5
Le swap
Il est possible avec les registres barri`ere ou les registres de base decrire des syst`emes temps
partage, en utilisant le mecanisme de swap (echange).
Swapper, cest echanger le contenu de la memoire centrale avec le contenu dune memoire
secondaire. Par extension swapper devient laction de deplacer une zone memoire de la memoire
vers le support de swap (en general un disque) ou reciproquement du peripherique de swap vers
la memoire.
Le syst`eme va realiser cet echange `a chaque changement de contexte. Les syst`emes de swap
utilisent une memoire secondaire qui est en general un disque mais on peut utiliser dautre supports
secondaires plus lents ou plus rapides comme des bandes ou memoires secondaires (non accessibles
par lunite de traitement).
8.1.6
Le co
ut du swap
Sur un tel syst`eme, le temps de commutation de taches est tr`es important. Il est donc necessaire
que chaque processus reste possesseur de lunite de traitement un temps suffisamment long pour
que le ralentissement d
u au swap ne soit pas trop sensible. Que ce passe-t-il sinon ? Le syst`eme
utilise la majeure partie de ses ressources `a deplacer des processus en et hors memoire centrale.
Lunite de traitement nest plus utilisee au maximum ...
8.1.7
Pour ameliorer les mecanismes de swap, on remarque que le temps de swap est proportionnel `a
la taille des donnees `a deplacer. Pour ameliorer les performances, il faut donc introduire la notion
CHAPITRE 8. LA MEMOIRE
66
Bas
unit
centrale
A < Bas
Haut
non
A > Haut
oui
Interruption
non
mmoire
oui
Interruption
8.1.8
Swap et ex
ecutions concurrentes
Une autre approche tr`es efficace est de realiser le swap pendant lexecution dun autre processus.
Mais avec le syst`eme de registres de relocation cest dangereux. En effet nous ne pouvons pas
assurer quun processus utilisateur donne ne va pas ecrire dans les adresses reservees `a un autre
processus.
8.1.9
Contraintes
Le swap introduit dautres contraintes : un processus doit etre en preempte actif pour etre
swappe, cest `a dire netre en attente daucune entree-sortie. En effet, si P1 demande une E/S et
pendant cette demande il y a echange de P1 et P2, alors la lecture demandee par P1 a lieu dans
les donnees de P2.
8.1.10
Soit ne jamais swapper de processus en attente dentrees-sorties. Soit realiser toutes les entreessorties dans des buffers internes au noyau (solution UNIX), ce qui a pour co
ut une recopie memoire
a memoire supplementaire par E/S. Les transferts entre le noyau et le processus ayant lieu uni`
quement quand le processus est en memoire.
8.1.11
Les probl`
emes de protection
Nous venons dapercevoir des probl`emes de protection entre un processus et le noyau. Si lon
autorise plusieurs processus `a resider en memoire en meme temps, il nous faut un mecanisme de
protection inter-processus.
Deux methodes sont couramment utilisees : les extensions du registre barri`ere et du registre de
base (relocation).
8.1.12
8.2. ORDONNANCEMENT EN MEMOIRE
DES PROCESSUS
Base
limite
unit
centrale
67
non
A > limite
mmoire
oui
Interruption
Moniteur
300k
500k
600k
p1
p2
0
300k
500k
600k
800k
1000k
1200k
Moniteur
300k
p1
p2
500k
600k
p3
p4
p3
1200k
300k
p1
p2
2100k
Initial
500k
600k
Moniteur
p1
p2
p4
1000k
p3
1200k
1500k
1500k
1900k
Moniteur
p4
p4
1900k
2100k
Dplacement :
600k
2100k
2100k
Dplacement :
400k
p3
Dplacement :
200k
8.2
Ordonnancement en m
emoire des processus
Les choix de limplementation des mecanismes dadressage influence enormement lordonnancement des processus.
Nous travaillons dans le cas dun syst`eme de traitement par lots cest `a dire en temps partage
mais les processus restent en memoire tout le temps de leur execution. Sil ny a plus de place le
processus est mis en attente (i.e. non charge en memoire).
Nous devons resoudre le probl`eme suivant : il nous faut un algorithme pour choisir dynamiquement, parmi les blocs libres de la memoire centrale, celui qui va recevoir le nouveau processus
(algorithme dallocation de memoire `a un processus). On reconnat en general trois methodes :
First-fit Le premier bloc suffisamment grand pour contenir notre processus est choisi.
Best-fit Le plus petit bloc suffisamment grand pour contenir notre processus est choisi.
Worst-fit Le bloc qui nous laisse le plus grand morceau de memoire libre est choisi (le plus grand
bloc).
De nombreuse experiences pratiques et des simulations ont montre que le meilleur est first-fit
puis best-fit et que ces deux algorithmes sont beaucoup plus efficaces que worst-fit. Compactage
On cherche `a ameliorer ces mecanismes en defragmentant la memoire cest `a dire en deplacant les
processus en memoire de facon `a rendre contigues les zones de memoire libre de facon `a pouvoir
les utiliser.
CHAPITRE 8. LA MEMOIRE
68
0
Moniteur
Moniteur
40k
40k
P5
P5
90k
90k
100k
P4
P4
160k
170k
P3
190k
200k
Zone contigu
de 66k
P3
230k
256k
256k
0
Moniteur
Moniteur
40k
100k
40k
P1
P1
100k
0
Moniteur
Moniteur
40k
Moniteur
40k
40k
100k
90k
100k
P5
P1
100k
P4
P4
P4
P2
200k
200k
P3
230k
256k
170k
170k
170k
200k
200k
200k
P3
230k
P3
230k
256k
256k
P3
230k
256k
P3
230k
256k
8.3
Allocation non-contigu
e
8.3.1
8.3.2
8.3. ALLOCATION NON-CONTIGUE
69
Adresse
physique
Adresse
logique
unit
centrale
mmoire
p
f
page 0
page 1
page 2
page 3
mmoire
logique
0
1
2
3
1
4
3
7
0
1 page 0
2
3 page 2
4 page 1
5
6
7 page 3
mmoire
physique
8.3.3
Comment prot
eger la m
emoire pagin
ee
8.3.4
La m
emoire segment
ee
Nous venons de voir que les adresses logiques utilisees par le programmeur sont differentes des
adresses physiques.
La memoire segmentee est une organisation de la memoire qui respecte le comportement usuel
des programmeurs, qui generalement voient la memoire comme un ensemble de tableaux distincts
contenant des informations de types differents. Un segment pour chaque type : donnees, code, table
des symboles, librairies etc. Ces differentes zones ayant des tailles variees, et parfois variables au
cours du temps (le tas par exemple).
CHAPITRE 8. LA MEMOIRE
70
Table des segments
Adresse
logique
unit
centrale
Adresse
physique
d<l
mmoire
oui
non
interruption erreur dadresse
Chapitre 9
La m
emoire virtuelle
Les methodes de gestion memoire que nous venons de voir ont toutes un defaut majeur qui est
de garder lensemble du processus en memoire, ce qui donne :
un co
ut en swap important
Impossibilite de creer de tr`es gros processus.
Les methodes de memoire virtuelle permettent dexecuter un programme qui ne tient pas enti`erement
en memoire centrale !
Nous avons commence par presenter des algorithmes de gestion de la memoire qui utilisent le
concept de base suivant :
lensemble de lespace logique adressable dun processus doit etre en memoire pour pouvoir executer
le processus.
Cette restriction semble `a la fois raisonnable et necessaire, mais aussi tr`es dommageable car
cela limite la taille des processus `a la taille de la memoire physique.
Or si lon regarde des programmes tr`es standards, on voit que :
il y des portions de code qui g`erent des cas tr`es inhabituels qui ont lieu tr`es rarement (si ils
ont lieu)
les tableaux, les listes et autres tables sont en general initialises `a des tailles beaucoup plus
grandes que ce qui est reellement utile
Certaines options dapplication sont tr`es rarement utilisees
Meme dans le cas o`
u le programme en entier doit resider en memoire, tout nest peut-etre pas
absolument necessaire en meme temps.
Avec la memoire virtuelle, la memoire logique devient beaucoup plus grande que la memoire
physique.
De nombreux avantages :
Comme les utilisateurs consomment individuellement moins de memoire, plus dutilisateurs peuvent
travailler en meme temps. Avec laugmentation de lutilisation du CPU et de debit que cela implique (mais pas daugmentation de la vitesse).
Moins dentrees-sorties sont effectuees pour lexecution dun processus, ce qui fait que le processus sexecute (temps reel) plus rapidement.
9.0.5
Les overlays
Une des premi`eres versions dexecutables partiellement en memoire est celle des overlay qui
est lidee de charger successivement des portions disjointes et differentes de code en memoire,
executees lune apr`es lautre.
Les differentes passes dun compilateur sont souvent realisees en utilisant un overlay (preprocesseurs,
pass1, pass2, pour les compilateurs C).
71
CHAPITRE 9. LA MEMOIRE
VIRTUELLE
72
Les overlay necessitent quelques adaptations de lediteur de liens et des mecanismes de relocation.
9.0.6
Le chargement dynamique
Un autre syst`eme couramment utilise dans les logiciels du marche des micros est le chargement
dynamique. Avec le chargement dynamique, une fonction nest chargee en memoire quau moment
de son appel. Le chargement dynamique demande que toutes les fonctions soient repositionnables
en memoire de facon independante.
A chaque appel de fonction on regarde si la fonction est en memoire sinon un editeur de liens
dynamique est appele pour la charger.
Dans les deux cas (overlay et chargement dynamique), le syst`eme joue un role tr`es restreint, il
suffit en effet davoir un bon syst`eme de gestion de fichiers.
Malheureusement, le travail que doit realiser le programmeur pour choisir les overlays et/ou
installer un mecanisme de chargement dynamique efficace est non trivial et requiert que le programmeur ait une parfaite connaissance du programme.
Ceci nous am`ene aux techniques automatiques.
9.1
Demand Paging
La methode de Demand Paging est la plus repandue des implementations de memoire virtuelle, elle demande de nombreuse capacites materielles.
Nous partons dun syst`eme de swap o`
u la memoire est decoupee en pages. Comme pour le
swap, quand un programme doit etre execute nous le chargeons en memoire (swap in) mais au lieu
de faire un swap complet, on utilise un swappeur paresseux (lazy swapper).
Un swappeur paresseux charge une page uniquement si elle est necessaire.
Que ce passe-t-il quand le programme essaie dacceder `a une page qui est hors memoire ?
le materiel va traduire ladresse logique en une adresse physique grace `a la table des pages.
tant que les pages demandees sont en memoire, le programme tourne normalement, sinon si
la page est contenue dans lespace des adresses logiques mais nest pas chargee, il y a une
page fault.
En general, une erreur dadresse est d
ue `a une tentative dacc`es `a une adresse exterieure
(invalide). Dans ce cas, le programme doit etre interrompu, cest le comportement normal dun
syst`eme de swap.
Mais il est possible avec un swappeur paresseux que la page existe mais ne soit pas en memoire
centrale, do`
u les etapes suivantes dans ce cas :
On peut faire demarrer un processus sans aucune page en memoire. La premi`ere Page Fault
aurait lieu `a la lecture de la premi`ere instruction (linstruction netant pas en memoire).
Il faut realiser une forme speciale de sauvegarde de contexte, il faut garder une image de letat
du processus qui vient deffectuer une Page Fault mais de plus il faudra redemarrer (reexecuter)
linstruction qui a place le processus dans cet etat, en effet il est possible que linstruction ne se
soit pas termine par manque de donnees.
Le syst`eme dexploitation a ici un role important, cest lui qui va realiser le chargement de la
page manquante puis relancer le processus et linstruction.
Les circuits necessaires `a la methode de Demande Paging sont les memes que ceux que lon
utilise pour un syst`eme de swap pagine, cest-`a-dire une memoire secondaire et un gestionnaire de
pages (table des pages).
Par contre, la partie logicielle est beaucoup plus importante.
Enfin il faut que les instructions soient interruptibles, ce qui nest pas toujours le cas sur
tous les processeurs et ce qui est fondamental, comme nous allons le voir sur des exemples :
add A,B in C
73
3 la page existe
en zone de swap
noyau
1 rfrence
2 interruption
load M
6 relancer
linstruction table des
pages
disque
de
swap
5 mise jours
de la table des
page du P.
mmoire
4 swap in
de la page
fautive ...
9.1.1
Efficacit
e
CHAPITRE 9. LA MEMOIRE
VIRTUELLE
74
temps de latence du peripherique
commencer le transfert
75
Remarquons que dans ce cas-l`a notre temps de transfert est double, comme il faut `a la fois lire
une page et sauvegarder une page sur disque (le temps de transfert disque est ce qui est le plus
co
uteux dans la gestion dune erreur de page).
Il est possible de realiser des syst`emes de demand segments, mais le lecteur avise remarquera
rapidement les probl`emes poses par la taille variable des segments.
9.2
9.2.1
Le remplacement optimal
Utiliser comme victime la page qui ne sera pas utilisee pendant le plus longtemps.
Soit pour notre suite :
7xx 70x 701 201 - 203 - 243 - -203 - - 201 - - - 701 - soit seulement 9 fautes de page.
Mais cet algorithme nest valable que dans un cas o`
u lon connat `a lavance les besoins, ce
qui nest generalement pas le cas.
9.2.2
CHAPITRE 9. LA MEMOIRE
VIRTUELLE
76
9.2.3
Moins r
ecemment utilis
ee LRU.
9.2.4
Lalgorithme de la deuxi`
eme chance
Un bit associe `a chaque page est positionne `a 1 `a chaque fois quune page est utilisee par un
processus. Avant de retirer une page de la memoire, on va essayer de lui donner une deuxi`eme
chance. On utilise un algorithme FIFO plus la deuxi`eme chance :
Si le bit dutilisation est `a 0, la page est swappee hors memoire (elle na pas ete utilisee depuis la
derni`ere demande de page).
Si le bit est `a 1, il est positionne a zero et lon cherche une autre victime. Ainsi cette page ne
sera swappee hors memoire que si toutes les autres pages ont ete utilisees, et utilisent aussi leur
deuxi`eme chance.
On peut voir ceci comme une queue circulaire, o`
u lon avance sur les pages qui ont le bit `a 1
(en le positionnant `a zero) jusqu`a ce que lon trouve une page avec le bit dutilisation `a zero.
9.2.5
Plus fr
equemment utilis
e MFU
9.2.6
77
Le bit de salet
e (Dirty Bit)
Remarquons que si il existe une copie identique sur disque (zone de swap) dune page de
memoire, il nest pas necessaire dans le cas dun swapout de sauvegarder la page sur disque, il
suffit de la liberer.
Le bit de salete permet dindiquer quune page est (ou nest plus) conforme `a la page en zone de
swap.
Ce bit de proprete est utilise dans les autres algorithmes, on choisit entre deux victimes possibles
la plus propre, cest-`a-dire celle qui ne necessite pas de swapout.
9.3
Probl`
emes d
ecroulement Si le nombre de pages allouees `a un processus non-prioritaire tombe
en dessous de son minimum vital, ce processus est constamment en erreur de page : il passe tout
son temps `a realiser des demandes de pages. Ce processus doit etre alors ejecte enti`erement en
zone de swap et reviendra plus prioritaire quand il y aura de la place.
Un exemple de bonne et mauvaise utilisation des pages (rappel les compilateurs c allouent les
tableaux sur des plages dadresse croissante contig
ues int m[A][B] est un tableau de A tableaux
de B entiers) :
/* bonne initialisation */
int m[2048][2048];
main()
{int i,j;
for(i=0;i<2048;i++)
for(j=0;j<2048;j++)
m[i][j] = 1;
}
ce processus acc`ede a une nouvelle page toute les 2048 affectation.
/* mauvaise initialisation */
int m[2048][2048];
main()
{int i,j;
for(i=0;i<2048;i++)
for(j=0;j<2048;j++)
m[j][i] = 1;
}
CHAPITRE 9. LA MEMOIRE
VIRTUELLE
78
9.4
Lappel fork et la m
emoire virtuelle
Nous avons vu que la primitive fork() realise une copie de limage memoire du processus p`ere
pour creer le processus fils. Cette copie nest pas integrale car les deux processus peuvent partager
des pages marquees en lecture seule, en particulier le segment du code est partage par les deux
processus (reentrance standard des processus unix).
Mais avec le syst`eme de demand-paging, on peut introduire une nouvelle notion qui est la
copie sur ecriture (copy on write). On ajoute `a la structure de page de la table des pages des
indicateurs de copie sur ecriture. Lidee est de realiser la copie de la page uniquement dans le
cas o`
u lun des processus qui peuvent y acc`eder realise une ecriture. Dans ce cas-l`a, la page est
recopiee avant lecriture et le processus ecrivain poss`ede alors sa propre page.
Linteret de ce mecanisme est surtout visible dans le cas tr`es frequent o`
u le fork est immediatement
suivi par un exec. En effet, ce dernier va realiser une liberation de toutes les pages, il est donc
inutile de les recopier juste avant cette liberation.
Le syst`eme BSD a introduit la premi`ere version de cette idee en partant de lappel syst`eme
vfork() qui lui permet le partage totale de toutes les pages entre le processus p`ere et le processus
fils sans aucune copie. Linteret est de pouvoir realiser rapidement un execve sans avoir `a recopier
lespace dadressage du processus p`ere.
9.5
Projection de fichiers en m
emoire
9.5. PROJECTION DE FICHIERS EN MEMOIRE
--r-r-x
rw
rwx
79
PROT_NONE
PROT_READ
PROT_READ|PROT_EXECUTE
PROT_READ|PROT_WRITE
PROT_READ|PROT_WRITE|PROT_EXECUTE
options indique si lon veut que les ecritures realisees dans les pages contenant la projection soient partagees (MAP SHARED), ou au contraire quune copie sur ecriture soit realisee
(MAP PRIVATE).
La fonction munmap permet de liberer la zone memoire dadresse adr et de longueur len.
Pour une autre forme de memoire partagee, voir le chapitre sur les IPC (sur le web).
Un exemple dutilisation de mmap pour copier un fichier :
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int fdin,fdout ;
struct stat statbuf ;
char *src,*dst ;
if (argc != 3)
{
fprintf(stderr,"usage : %s source destination ",argv[0]) ;
exit(-1) ;
}
if ((fdin = open(argv[1], O RDONLY)) < 0)
{
fprintf(stderr,"impossible d\ouvrir : %s en lecture ",argv[1]) ;
exit(-2) ;
}
if ((fdout = open(argv[2], O RDWR|O CREAT|O TRUNC,0666)) < 0)
{
fprintf(stderr,"impossible d\ouvrir : %s en ecriture ",argv[2]) ;
exit(-3) ;
}
if (fstat(fdin,&statbuf) < 0 )
{
fprintf(stderr,"impossible de faire stat sur %s ",argv[1]) ;
exit(-4) ;
}
if (lseek(fdout, statbuf.st size -1 , SEEK SET) == -1 )
{
fprintf(stderr,"impossible de lseek %s ",argv[2]) ;
exit(-5) ;
}
if (write(fdout,"",1) != 1)
{
fprintf(stderr,"impossible d\ecrire sur
%s ",argv[2]) ;
exit(-6) ;
}
CHAPITRE 9. LA MEMOIRE
VIRTUELLE
80
Attention, quand vous utilisez mmap cest de la memoire, mais cest a vous de gerer lallignement.
Exemple :
char *p = map(...);
int *q = p+1; // warning
*q = 1 ; // probl`
eme dallignement
9.6
Une foit que lon decider de faire des projection en memoire avec mmap il peut etre oportin de
faire appel `a la fonction madvise qui permet de donner un conseil au syst`eme en le prevenant par
avance de la facon dont vous aller utiliser le segement de memoire. En particulier allez vous lire
le fichier sequentiellement ou de facon alleatoire. Avez vous encore besoin du fichier apr`es lecture
etc. Biensur la fonction madvise ne se limite pas aux pages mappes mais cest sur celle ci quil est
le plus facile de prendre des decisions, les autres pages etant gerer dans la pile le tas et le code
zone plus delicates et moins bien cartographiees en generale (sic).
#include <sys/mman.h>
int madvise(void *start, size_t length, int advice);
La valeur du conseil advice :
MADV NORMAL Comportement par defaut.
MADV RANDOM prevoit des acces aux pages dans un ordre aleatoire.
MADV SEQUENTIAL prevoit des acces aux pages dans un ordre sequentiel.
MADV WILLNEED prevoit un acces dans un futur proche.
MADV DONTNEED Ne prevoit pas dacces dans un futur proche. Biensur si cest une mmap
vous pouvez aussi utiliser la commande munmap.
Biensur ce ne sont que des conseils le syst`eme les utilisera si il en a la possibilite, soit parce quil
y a du temps idle (sans activite) soit parce quil profitera des lectures groupees sur disque en
realisant des lectures en avance cas sequentiel. Il peut aussi profiter de lindication DONTNEED
pour prendre des decissions dans le code de remplacement de page.
9.7
81
Chargement dynamique
82
CHAPITRE 9. LA MEMOIRE
VIRTUELLE
Chapitre 10
10.1
Un tube est materialise par deux entrees de la table des ouvertures de fichiers, une de ces
entrees est ouverte en ecriture (lentree du tube), lautre en lecture (la sortie du tube). Ces deux
entrees de la table des fichiers ouverts nous donnent le nombre de descripteurs qui pointent sur
elles. Ces valeurs peuvent etre traduites comme :
nombre de lecteurs = nombre de descripteurs associes `a lentree ouverte en lecture.On ne peut
pas ecrire dans un tube sans lecteur.
nombre d
ecrivains = nombre de descripteurs associes `a lentree ouverte en ecriture. La nullite
de ce nombre definit le comportement de la primitive read lorsque le tube est vide.
10.2
Cr
eation de tubes ordinaires
Un processus ne peut utiliser que les tubes quil a crees lui-meme par la primitive pipe ou quil
a herites de son p`ere grace `a lheritage des descripteurs `a travers fork et exec.
#include <unistd.h>
int pipe(int p[2]);
On ne peut pas manipuler les descripteurs de tubes avec les fonctions et primitives : lseek,
ioctl, tcsetattr et tcgetattr, comme il ny a pas de peripherique associe au tube (tout est
83
CHAPITRE 10. TUBES ET TUBES NOMMES
84
processus A
pipe(p)
Dans le noyau
descripteurs
inodes en mmoire
p[0]
2 0
1 rd
p[1]
1 wr
ouvertures
de fichiers
inodes
p[0]
2 rd
2 0
p[1]
processus B
fils de A p[0]
2 wr
p[1]
85
ouvertures
processus A
dup2(1,p[1]) 1
close (p[0])
close (p[1])
1 rd
processus B
fils de A
1 wr
dup2(0,p[0])
close (p[0])
close (p[1])
Fig. 10.3 Redirection de la sortie standard de A dans le tube et de lentree standard de B dans
le tube, et fermeture des descripteurs inutiles
10.3
CHAPITRE 10. TUBES ET TUBES NOMMES
86
10.4
10.5
Un meme processus a deux acc`es `a un tube, un acc`es en lecture, un acc`es en ecriture et essaie
de lire sur le tube vide en mode bloquant le processus est bloque indefiniment dans la primitive
read.
Avec deux processus :
deux tubes entre les deux processus, tous les deux bloques en lecture ou tous les deux bloques en
ecriture, tous les deux en attente dune action de lautre processus.
10.6
Les tube nommes sont des tubes (pipe) qui existent dans le syst`eme de fichiers, et donc peuvent
etre ouverts grace `a une reference.
Il faut prealablement creer le tube nomme dans le syst`eme de fichiers, grace `a la primitive mknod
(mkfifo), avant de pouvoir louvrir avec la primitive open.
int mknod(reference, mode | S_IFIFO,0);
mode est construit comme le param`etre de mode de la fonction open.
En POSIX, un appel simplifie :
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *ref, mode_t mode);
On peut creer des FIFOs `a partir du shell grace `a
mkfifo [-p] [-m mode] ref ...
Louverture dun tube nomme se fait exclusivement soit en mode O RDONLY soit en mode
O WRONLY, ainsi le nombre de lecteur et decrivain peut etre comptabilise.
10.6. LES TUBES NOMMES
10.6.1
87
Il y a automatiquement synchronisation des processus qui ouvrent en mode bloquant un tube nomm
e.
Loperation douverture sur un tube nomme est bloquante en lecture.
Le processus attend quun autre processus ouvre la fifo en ecriture.
Louverture en ecriture est aussi bloquante, avec attente quun autre processus ouvre la fifo en
lecture. Louverture bloquante se termine de facons synchrone pour les deux processus.
Ainsi un unique processus ne peut ouvrire `a la fois en lecture et ecriture un tube nomme.
En mode non bloquant (O NONBLOCK, O NDELAY), seule louverture en lecture reussit
dans tous les cas. Louverture en ecriture en mode non bloquant dun tube nomme ne fonctionne
que si un autre processus a dej`a ouvert en mode non bloquant le tube en lecture, ou bien quil
est bloque dans lappel dune ouverture en lecture en mode bloquant. Ceci pour eviter que le
processus qui vient douvrir le tube nomme, necrive dans le tube avant quil ny ait de lecteur
(quun processus ait ouvert le tube en lecture) et ce qui engendrerait un signal SIGPIPE (tube
detruit), ce qui nest pas vrai car le tube na pas encore ete utilise.
10.6.2
Lutilisation de rm ou unlink ne fait que detruire la reference, le tube nest reellement detruit
que lorsque son compteur de liens internes et externes est nul.
Une fois que tous les liens par reference sont detruits, le tube nomme devient un tube ordinaire.
10.6.3
Une interface plus facile pour lancer un coprocessus est propose avec les primitives popen et
pclose.
88
Chapitre 11
Les signaux
Les signaux sont un mecanisme asynchrone de communication inter-processus.
Intuitivement, il sont comparables `a des sonneries, les differentes sonneries indiquant des ev`enements
differents. Les signaux sont envoyes `a un ou plusieurs processus. Ce signal est en general associe
`a un ev`enement.
Peu portables entre BSD et ATT, ils deviennent plus commodes `a utiliser et portables avec
la norme POSIX qui utilise la notion utile de vecteur de signaux et qui fournit un mecanisme de
masquage automatique pendant les procedures de traitement (comme BSD).
Un signal est envoye `a un processus en utilisant lappel syst`eme :
kill(int pid, int signal);
signal est un numero compris entre 1 et NSIG (defini dans <signal.h>) et pid le numero du
processus.
Le processus vise recoit le signal sous forme dun drapeau positionne dans son bloc de controle.
Le processus est interrompu et realise eventuellement un traitement de ce signal.
On peut considerer les signaux comme des interruptions logicielles, ils interrompent le flot normal dun processus mais ne sont pas traites de facon synchrone comme les interruptions materielles.
11.0.4
Certains signaux peuvent etre lances `a partir dun terminal grace aux caract`eres speciaux
comme intr, quit dont la frappe est transformee en lenvoi des signaux SIGINT et SIGQUIT.
Dautres sont d
us `a des causes internes au processus, par exemple : SIGSEGV qui est envoye en cas
derreur dadressage, SIGFPE division par zero (Floating Point Exception).
Enfin certains sont d
us `a des ev`enements comme la deconnection de la ligne (le terminal)
utilise : si le processus leader dun groupe de processus est deconnecte, il envoie `a lensemble des
processus de son groupe le signal SIGHUP (Hangup = raccrocher).
11.0.5
Cest dans le bloc de controle (BCP) de chaque processus que lon trouve la table de gestion
des signaux (attention, sous System V < V.4, la table de gestion des processus est dans la zone
u, cest `a dire dans lespace-memoire du processus).
Cette table contient, pour chaque signal defini sur la machine, une structure sigvec suivante :
{
bit pendant;
89
90
11.0.6
11.1
91
La gestion simplifi
ee avec la fonction signal
ZZZ : cette section est historique, utiliser la norme POSIX decrite plus loin.
ancien C : (*signal(sig, func))()
int sig;
int (*func)();
ANSI C :
11.1.1
Un exemple
Exemple pour rendre un programme insensible `a la frappe du caract`ere de controle intr sur le
terminal de controle du processus.
void got_the_blody_signal(int n) {
signal(SIGINT, got_the_blody_signal);
printf(" gotcha!! your (%d) signal is useless \n");
}
main() {
signal(SIGINT, got_the_blody_signal);
printf(" kill me now !! \n");
for(;;);
}
une version plus elegante et plus fiable :
signal(SIGINT, SIG_IGN);
11.2
Probl`
emes de la gestion de signaux ATT
Les phenom`enes suivants sont decrits comme des probl`emes mais la norme POSIX permet den
conserver certains, mais fournit aussi les moyens de les eviter.
1. un signal est repositionne `a sa valeur par defaut au debut de son traitement (handler).
#include <signal.h>
traitement() {
printf("PID %d en a capture un \n", getpid());
92
}
main() {
int ppid;
signal(SIGINT,traitement);
if (fork()==0)
{/* attendre que pere ait realise son nice() */
sleep(5);
ppid = getppid(); /* numero de pere */
for(;;)
if (kill(ppid,SIGINT) == -1)
exit();
}
/* pere ralenti pour un conflit plus sur */
nice(10);
for(;;) pause(); <- reception du premier signal
/* pause cest mieux quune attente active */
}
Si lon cherche `a corriger ce defaut, on repositionne la fonction traitement au debut du
traitement du signal. Ceci risque de nous placer dans une situation de depassement de pile :
en effet, dans le programme precedent, nous pouvons imaginer que le p`ere peut recevoir
un nombre de signaux arbitrairement grand pendant le traitement dun seul signal, do`
u
une explosion assuree de la pile (il suffit en effet que chaque empilement de la fonction
traitement soit interrompu par un signal)
traitement(){
signal(SIGINT,traitement);
->
signal SIGINT
printf("PID %d en a capture un \n",getpid());
}
On peut aussi ignorer les signaux pendant leur traitement, mais cela peut creer des pertes
de reception.
Enfin, la solution BSD/POSIX o`
u lon peut bloquer et debloquer la reception de signaux `a
laide du vecteur de masquage (sans pour autant nous assurer de la reception de tous les
signaux ! !). De plus, en POSIX, le traitement dun signal comporte une clause de blocage
automatique. On indique quels signaux doivent etre bloques pendant le traitement du signal,
grace `a un vecteur de masquage dans la structure sigaction.
Ceci est le comportement naturel de gestion des interruptions materielles : on bloque les
interruptions de priorite inferieure pendant le traitement dun interruption.
2. Seconde anomalie des signaux sous System V < V4 : certains appels syst`emes peuvent etre
interrompus et dans ce cas la valeur de retour de lappel syst`eme est -1 (echec). Il faudrait,
pour realiser correctement le mod`ele dune interruption logicielle, relancer lappel syst`eme en
fin de traitement du signal. (Sous BSD ou POSIX, il est possible de choisir le comportement
en cas dinterruption dun appel syst`eme grace `a la fonction siginterrupt, c-a-d relancer
ou non lappel syst`eme, un appel `a read, par exemple, peut facilement etre interrompu si il
necessite un acc`es disque).
3. Troisi`eme anomalie des signaux sous ATT : si un signal est ignore par un processus endormi,
celui-ci sera reveille par le syst`eme uniquement pour apprendre quil ignore le signal et doit
donc etre endormi de nouveau. Cette perte de temps est d
ue au fait que le vecteur des
signaux est dans la zone u et non pas dans le bloc de controle du processus.
`
11.2. PROBLEMES
DE LA GESTION DE SIGNAUX ATT
11.2.1
93
Le signal SIGCHLD
Le signal SIGCHLD (anciennement SIGCLD) est un signal utilise pour reveiller un processus
dont un des fils vient de mourir. Cest pourquoi il est traite differemment des autres signaux. La
reaction `a la reception dun signal SIGCHLD est de repositionner le bit pendant `a zero, et dignorer le signal, mais le processus a quand meme ete reveille pour cela. Leffet dun signal SIGCHLD
est donc uniquement de reveiller un processus endormi en priorite interruptible.
Si le processus capture les signaux SIGCHLD, il invoque alors la procedure de traitement
definie par lutilisateur comme il le fait pour les autres signaux, ceci en plus du traitement par
defaut.
Le traitement normal est lie `a la primitive wait qui permet de recuperer la valeur de retour
(exit status) dun processus fils. En effet, la primitive wait est bloquante et cest la reception du
signal qui va reveiller le processus, et permettre la fin de lexecution de la primitive wait.
Un des probl`emes de la gestion de signaux System V est le fait que le signal SIGCHLD est
recu (raised) au moment de la pose dune fonction de traitement.
Ces proprietes du signal SIGCHLD peuvent induire un bon nombre derreurs.
Par exemple, dans le programme suivant nous positionnons une fonction de traitement dans
laquelle nous repositionnons la fonction de traitement. Comme sous System V, le comportement
par defaut est repositionne pendant le traitement dun signal. Or le signal est leve `a la pose de la
fonction de traitement, do`
u une explosion de la pile.
#include <stdio.h>
#include <unistd.h> /* ancienne norme */
#include <signal.h>
void hand(int sig) {
signal(sig, hand);
printf("message qui nest pas affiche\n");
}
main() {
if (fork()) { exit(0); /* creation dun zombi */ }
signal(SIGCHLD, hand);
printf("ce printf nest pas execute\n");
}
Sur les HP, un message derreur vous informe que la pile est pleine : stack growth failure.
Deuxi`eme exemple :
#include <signal.h>
#include <sys/wait.h>
int pid, status;
void hand(int sig) {
printf(" Entree dans le handler \n");
system("ps -l");
/* affichage avec etat zombi du fils */
if ((pid = wait(&status)) == -1) /* suppression du fils zombi */
{
perror("wait handler ");
return ;
94
pid: %d
}
main() {
signal(SIGCHLD,hand); /* installation du handler */
if (fork() == 0)
{
/* dans le fils */
sleep(5);
exit(2);
}
/* dans le pere */
if ((pid = wait(&status)) == -1) /* attente de terminaison du fils */
{
perror("wait main ");
return ;
}
printf(" wait main pid: %d
status %d \n", pid, status);
}
resultat :
Entree dans le handler
F S UID
PID PPID C PRI NI
ADDR
1 S 121 6792 6667 0 158 20 81ac180
1 S 121 6667 6666 0 168 20 81ac700
1 Z 121 6793 6792 0 178 20 81bda80
1 S 121 6794 6792 0 158 20 81ac140
1 R 121 6795 6794 4 179 20 81bd000
wait handler pid: 6793
status 512
wait main: Interrupted system call
SZ WCHAN
TTY TIME COMD
6 49f5fc ttys1 0:00 sigchld
128 7ffe6000 ttys1 0:00 tcsh
0
ttys1 0:00 sigchld
78 4a4774 ttys1 0:00 sh
43
ttys1 0:00 ps
(2 * 256)
A la mort du fils, Le p`ere recoit le signal SIGCHLD (alors quil etait dans le wait du main),
puis le handler est execute, et ps affiche bien le fils zombi. Ensuite cest le wait du handler qui
prend en compte la terminaison du fils. Au retour du handler, lappel a wait du main retourne -1,
puisquil avait ete interrompu par SIGCHLD.
11.3
La primitive
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int indicateur);
sauvegarde un environnement dexecution, cest `a dire un etat de la pile, et si indicateur est
non nul, sauvegarde le masque de signaux courant. La valeur de retour de cette fonction est zero
quand on fait une sauvegarde, et sinon depend du param`etre valeur de la fonction siglongjmp.
int siglongjmp(sigjmp_buf env, int valeur);
La primitive siglongjmp permet de reprendre lexecution `a lendroit sauvegarde par sigsetjmp
dans la variable env.
Deux remarques : env doit avoir ete initialise par sigsetjmp, les valeurs de pile placees audessus de lenvironnement repris sont perdues. Lenvironnement de pile doit encore exister dans
la pile au moment de lappel, sinon le resultat est indetermine.
11.4
95
main()
{
int mask ;
struct sigvec s1,s2;
s1.sv_handler = gots1;
s1.sv_mask = sigmask(SIGUSR1);
sigvec(SIGUSR1, &s1, NULL);
s2.sv_handler = gots2;
s2.sv_mask = sigmask(SIGUSR2);
sigvec(SIGUSR2, &s2, NULL);
printf(" sans masquage de SIGUSR2: ")
raise(SIGUSR1);
printf(" \n avec masquage de SIGUSR2: " );
s1.sv_mask = sigmask(SIGUSR2);
sigvec(SIGUSR1, &s1, NULL);
raise(SIGUSR1);
}
Nous donne les affichages suivant :
sans masquage de SIGUSR2: got
avec masquage de SIGUSR2: got
s2(31) got
s1(30) got
s1(30)
s2(31)
Sous BSD, pas de fonction de manipulation propre des groupes de signaux (on regroupe les
signaux par des conjonctions de masques).
Le probl`eme de linterruption des appels syst`eme par les signaux est corrige par la fonction :
int
le drapeau flag prend comme valeur 0 ou 1, ce qui signifie que les appels syst`emes interrompus
par un signal seront :
soit relances avec les memes param`etres.
soit retourneront la valeur -1, et dans ce cas la valeur de errno est positionnee `a EINTR.
Certaines fonctions comme readdir utilisent des variables statiques, ces fonctions sont dites
non reentrantes. Il faut eviter dappeler ce type de fonctions dans un handler de signal, dans le cas
o`
u lon fait dej`a appel `a la fonction dans le reste du processus. De la meme facon la variable errno
est unique. Si celle-ci est positionnee dans le main mais quun signal arrive avant son utilisation,
une primitive appelee dans le handler peut en changer la valeur ! (ce probl`eme de reentrance sera
vu plus en detail avec les processus multi-activites).
11.4.1
Lappel pause
96
pause(void);
cette primitive est le standard UNIX dattente de la reception dun signal quelconque, BSD
propose la primitive suivante :
sigpause(int sigmask)
qui permet lattente dun groupe specifique de signaux, attention les signaux du masque sont
debloques (c.f. sigprocmask).
11.5
La norme POSIX
La norme POSIX ne definit pas le comportement dinterruption des appels syst`emes, il faut le
specifier dans la structure de traitement du signal.
sigemptyset(sigset_t *ens)
sigfillset(sigset_t *ens)
sigaddset(sigset_t *ens, int sig)
sigdelset(sigset_t *ens, int sig)
/* raz */
/* ens = { 1,2,...,NSIG} */
/* ens = ens + {sig} */
/* ens = ens - {sig } */
/* sig appartient `
a ens ?*/
11.5.1
Loperation op :
SIG SETMASK affectation du nouveau masque, recuperation de la valeur de lancien masque.
SIG BLOCK union des deux ensembles nouv et anc
SIG UNBLOCK soustraction anc - nouv
On peut savoir si un signal est pendant et donc bloque grace `a la fonction :
int sigpending(sigset_t *ens);
retourne -1 en cas dechec et 0 sinon et lensemble des signaux pendants est stocke `a ladresse
ens.
11.5.2
97
sigaction
11.5.3
En plus de lappel pause, on trouve sous POSIX lappel int sigsuspend(const sigset t
*ens) ; qui permet de realiser de facons atomique les actions suivantes :
linstallation du masque de blocage defini par ens (qui sera repositionne `a sa valeur dorigine)
`a la fin de lappel,
mise en attente de la reception dun signal non bloque.
98
Chapitre 12
12.1
Caract
eristiques dun verrou
12.2
Le mode op
eratoire des verrous
Le mode operatoire joue sur le comportement des primitives read et write. Les verrous dun
fichier sont soit consultatifs, soit imp
eratifs (NON-POSIX) 1 .
Dans le premier mode advisory (consultatif), la presence dun verrou nest testee qu`a la pose
dun verrou, la pose sera refusee sil existe un verrou de portee non disjointe et que lun des deux
verrous est exclusif.
1 En effet le mode imp
eratif nest pas POSIX, et donc par d
efaut nest pas mise en oeuvre sur les disque sous
linux.
99
100
Dans le second mode mandatory, la presence de verrous est testee pour la pose mais aussi pour
les appels syst`emes read et write.
Dans le mode consultatif, les verrous nont deffet que sur les processus jouant effectivement
le jeu, cest-`a-dire, posant des verrous sur les zones du fichiers sur lesquels ils veulent realiser une
lecture (verrou partage) ou une ecriture (verrou exclusif).
Dans le mode imperatif, les verrous ont un impact sur les lectures/ecritures de tous les processus :
sur les verrous de type partage (F RDLCK), toute tentative decriture (appel syst`eme write)
par un autre processus est bloquee ;
sur les verrous de type exclusif (F WRLCK), toute tentative de lecture ou decriture (read
et write) par un autre processus est bloquee.
Pour rendre lutilisation imperative il faut sous linux monter le disque avec loption -o mand.
Puis il faut utiliser la commande chmod pour positionner le SETGID bit, soit chmod g+s fichier
en shell soit la meme chose en C : si lon a le descripteur d dune ouverture sur le fichier
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
...
struct stat buf
fstat(d, &buf);
fchmod(d,buf.st_mode |
S_ISGID);
12.3
{
l_type;
l_whence;
l_start;
l_len;
l_pid;
/*
/*
/*
/*
/*
F_RDLCK, F_WRLCK,F_UNLCK */
SEEK_SET,SEEK_CUR,SEEK_END */
position relative a l_whence */
longueur de lintervalle */
PID du processus propri
etaire */
le champ l type
F RDLCK verrou partage
F WRLCK verrou exclusif
F UNLCK deverrouillage
Les manipulations de verrous se font avec la primitive fcntl, cest-`a-dire par le biais dun
descripteur. Pour poser un verrou partage, ce descripteur doit pointer sur une ouverture en lecture.
De meme, il faut un descripteur sur une ouverture en ecriture pour un verrou de type exclusif
.
Pour decrire la portee du verrou que lon veut poser, on utilise la meme syntaxe que pour la
primitive lseek, le debut de lintervalle est whence+l start :
l whence = SEEK SET whence = 0
l whence = SEEK CUR whence = offset courrant
l whence = SEEK END whence = taille du fichier.
101
La longueur du verrou est definie par le champ l len. Si cette valeur est nulle, le verrou va
jusqu`a la fin du fichier (meme si le processus change cette fin). Remarque : il est possible de poser
un verrou dont la portee est superieure `a la taille du fichier.
Le champ l pid contient le pid du processus proprietaire du verrou, ce champ est rempli par
fcntl dans le cas dun appel consultatif (F GETLK).
12.4
102
Chapitre 13
Algorithmes Distribu
es &
Interblocages
Ce chapitre introduit les probl`emes lies `a la gestion de processus concurrents. Le probl`eme
`a resoudre est le partage de ressources entre differents processus asynchrones. Les I.P.C. et les
verrous sont deux types doutils permettant le partage asynchrone de ressources entre processus.
13.1
exemples
13.1.1
Les m
efaits des acc`
es concurrents
Lexemple le plus simple est une variable enti`ere partagee par deux processus ou threads, ou
bien manipule par une fonction asyncrone comme un handler de signal. Supposont que lon definise
deux fonctions de manipulation de la variable :
int getValue();
void setValue(int );
Pour incrementer la variable, il suffit dexecuter setValue(getValue()+1) ; mais decomposont
en int tmp=getValue() ; setValue(tmp+1) ; ce qui ne change pas grand chose tmp etant simplement allouee sur la pile dans le premier cas. Regardont lexecution suivant du code par deux
thread :
int tmp1=getValue();
| int tmp2= getValue();
setValue(tmp1+1);
| setValue(tmp2+1);
Que cest il passe ?
la variable na ete incrementee quune fois !
Le cas dun signal le code c de prog
#include <stdio.h>
#include <signal.h>
int nbi; // nbre dincrementation acc`
es atomique
int partage; // nbr dincr
ementation acc`
es non atomique
int getValue() { return partage; }
103
& INTERBLOCAGES
CHAPITRE 13. ALGORITHMES DISTRIBUES
104
int
main(int c, char *argv[])
{
struct sigaction sig;
long diff = 0;
sig.sa_handler= handler;
sig.sa_flags = 0;
sigaction(SIGUSR1, &sig, NULL);
fprintf(stderr,"sigusr1= %d\n",SIGUSR1);
fprintf(stderr,"%d %d\n", nbi,partage);
for(;;)
{
int tmp=getValue();
setValue(tmp+1);
nbi++;
if ((partage != nbi) && (diff!= nbi-partage))
{ diff = nbi-partage; fprintf(stderr,"%d\n", nbi-partage); }
}
}
13.1.2
Exclusion mutuelle
Probl`eme : il y a une rivi`ere que lon peut traverser par un gue fait de pierre alignees, o`
u
il nest pas possible de se croiser, et il nest pas possible de faire demi-tour. Comment doit-t-on
organiser le passage ?
Solutions :
1. regarder avant de traverser
2. si deux personnes arrivent en meme temps sur chaque rive,
si elles avancent en meme temps interblocage
si elles attendent en meme temps interblocage
3. Un rem`ede : un cote prioritaire famine. En effet si le cote OUEST est prioritaire et quun
flot continu de personnes arrive de ce cote, les personnes `a lEST sont bloquees indefiniment.
4. Une solution : alterner les priorites.
Pour des ressources syst`eme comme les fichiers, le partage nest pas gere par le SGF. Il faut
donc un mecanisme de partage : les verrous, qui permettent un partage dynamique et partiel (portions de fichiers). Pour un partage entre utilisateurs, on utilise plutot des outils comme SCCS, RCS.
13.2
105
13.3
D
efinition de linterblocage (deadlock)
13.4
Quatre conditions n
ecessaires `
a linterblocage.
13.5
Les graphes dallocation de ressources permettent de decrire simplement les probl`emes dinterblocage.
G = (N,T) N = P U R
P : ensemble des processus
R : ensemble des ressources
T est inclus dans RXP U PXR
Soit le couple (x,y) appartenant `a T,
si (x,y) appartient `a RXP, cela signifie que la ressource x est utilisee par le processus y.
si (x,y) appartient `a PXR, cela signifie que le processus x demande la ressource y.
106
& INTERBLOCAGES
CHAPITRE 13. ALGORITHMES DISTRIBUES
Chapitre 14
S
ecurit
e et S
uret
e de
fonctionnement
Comme pour une habitation il faut que votre syst`eme offre deux chose importante, dune part
que la vie dans lhabitation soit sur, pas de risque pour les utilisateurs ni pour les elements materiel.
Feux , indondation, enfermement, tremblement de terre etc. Cest la su
rete de fonctionnement.
Dautre par lhabitation est protegee ainsi que ses habitants contre des attaques plus ou moins
malveillantes. La porte du jardin est fermee pour eviter que des animaux deteriore le jardin. Lhabitation est munie de systeme de verouillage pour se proteger contre un cambriollage. Cest la
securite.
La s
urete de fonctionnement est un element stategique qui doit etre gerer par la direction
informatique en fonction de contraintes operationnelles. La securite est le probl`eme de tout le
monde. Pour que la securite fonctionne, il faut que toutes les personnes ayant un acc`es `a une
ressource soient conscient du degre de securite associe `a la ressource. La strategie de securite doit
bien sur etre definie par la direction informatique mais cest un travail collectif (installation dune
serure na pas deffet si tout le monde laisse la porte ouverte).
14.1
107
ET SURET
DE FONCTIONNEMENT
CHAPITRE 14. SECURIT
E
E
108
14.2
G
en
eralit
es sur le contr
ole dacc`
es
ERALIT
SUR LE CONTROLE
`
14.2. GEN
ES
DACCES
109
Objets
Fichier
1
Sujets
Lire
Processus
Processus
Processus
Segment
1
Executer
Segment
2
Processus
2
Lire
Ecrire
Editeur
Entrer
Lire
Ecrire
Entrer
Lire
Ecrire
Executer
Entrer
Entrer
14.2.1
On formalise le syst`eme comme un ensemble dentites actives, les sujets, un ensemble dentites
accessibles, les objets. Le mod`ele de protection definit quels sujets ont acc`es `a quels objets et
comment (modalites dacc`es).
On parle alors de droit dacc`es, definis par le couple (objet, modalites)
Exemple : (fichier, lire)
Le mod`ele doit fixer `a tout instant les droits dacc`es dont dispose chaque processus. Cet ensemble de droits est le domaine de protection du processus. Voire un exemple de matrice dacc`es
dans la figure 14.2
14.2.2
Il est souhaitable que la matrice dacc`es puisse evoluer dynamiquement. En effet, un meme
processus peut avoir, au cours de son existence, des besoins variables afin que chaque module
110
ET SURET
DE FONCTIONNEMENT
CHAPITRE 14. SECURIT
E
E
qui compose un processus ne mette pas en danger des ressources non utilisees. Par exemple : un
module de lecture de donnees, un module de calcul, un module dimpression. On va donc executer
chaque module dans un domaine de protection le plus reduit possible.
Cest le principe du moindre privil`ege : un programme ne peut endommager un objet auquel
il na pas acc`es !
Pour mettre en place ces domaines dynamiques, une possibilite est de changer les droits dacc`es
du processus au cours de son execution. Une autre possibilite est dajouter aux objets le type
domaine et de controler les acc`es `a la matrice. Ledition de cases de la matrice devient une
operation protegee.
14.2.3
14.3
Le cheval de Troie
Un utilisateur fait souvent appel `a un certain nombre de programmes quil na pas ecrit luimeme (heureusement), un editeur par exemple. Ce programme peut etre un cheval de Troie : il va
profiter des droits donnes par lutilisateur pour consulter, copier, modifier ou alterer des donnees
auxquelles il nest pas cense acceder.
14.4
Le confinement
Le probl`eme ici est tout simplement le fait que le programme ne manipule pas de donnees de
lutilisateur mais simplement enregistre ses param`etres dappels (les utilisateurs `a qui vous envoyez
du courrier par exemple). Le probl`eme du confinement est donc de vous proteger contre ce type
dextraction dinformations (ce qui peut par exemple etre utilise en bourse pour connaitre votre
comportement dachat).
14.5
les m
ecanismes de contr
ole
Acc`es hierarchiques
UNIX (4)/ MULTICS (8) / VMS
Listes dacc`es
UNIX/MULTICS
Capacites
Les capacites sont des triplets (utilisateur, droits, pointeur). La manipulation des capacites est realisee de facon protegee. Le pointeur nest pas directement utilisable par lutilisateur
de la capacite. La capacite donne le droit dacc`es `a certains utilisateurs dune certaine ressource.
Pour quun autre utilisateur puisse utiliser votre ressource, vous devez lui donner une capacite.
Changer de protection revient `a changer de C-liste.
La notion de domaine se materialise par une simple indirection sur une autre C-liste.
Comme les capacites donnent un acc`es sans controle aux objets, la protection des capacites
doit etre absolue. Elle est donc realisee de facon materielle.
1
2
Domaine
Domaine
Domaine
Sujets
Lire
Ecrire
Lire
Fichier
1
Lire
Ecrire
Segment
2
Processus i
Lire
Ecrire
Executer
Executer
Segment
1
Objets
Entrer
Entrer
Entrer
Entrer
Editeur
Domaine i
Processus
2
Entrer
Entrer
Entrer
Domaine Domaine
1
2
Objet
ET SURET
DE FONCTIONNEMENT
CHAPITRE 14. SECURIT
E
E
112
Nom
Code Editeur
Editeur
Executer
Proc
Lire,Executer
Fic1
Lire
Fic2
Lire,Ecrire
Code Procedure
Fichier
Fichier
14.5.1
Les C-listes sont des objets dun type nayant quun droit dentree, la C-liste contenant le droit
reel.
Cette technique sur les C-listes permet dimplanter facilement le principe de moindre privil`ege.
Les mecanismes dacc`es memoire modernes permettent aisement de realiser les capacites.
Un probl`eme important est la revocation
En effet, une fois que vous avez donne une capacite, lacc`es est definitivement donne. Pour
regler ce probl`eme, on ne fournira pas la capacite dacc`es `a un objet mais `a un domaine, et on
detruira ce domaine si lon veut de nouveau interdire lacc`es `a lobjet. On cree deux capacites en
chaine et lon detruit celle que lon poss`ede quand ont veut retirer lacc`es.
113
Proc
Entrer
Objet
C-liste1
Entrer
.
.
.
Objet O
O Lire,Ecrire
Objet
Copie
O Lire,revoquer
Lire
O
O Lire,Ecrire
Copies
O
Lire
Lire
Fig. 14.7 Transmission dune capacite
ET SURET
DE FONCTIONNEMENT
CHAPITRE 14. SECURIT
E
E
114
Objet O
O Lire,Ecrire
Objet
Copie
O Lire,revoquer
Lire
Lire
Copies
Revocation
Lire
Fig. 14.8 Revocation dune capacite
14.6
115
Les ACL
Les ACL (access control lists) sont une extension des modes de protection standard dUNIX.
Les ACL sont des droits que lon definit en plus des 9 bits de protection classiques, ils permettent
en particulier dautoriser lacc`es ou de le refuser, `a un utilisateur donne, ou `a un groupe donne.
Deux commandes permettent de manipuler les ACL, ce sont chacl et lsacl.
La syntaxe de la commande shell chacl :
chacl (dr.staff,r-x)(zipstein.%,r-x)(%.licence,---) proj
qui donne sur le fichier proj les droits de lecture et decriture `a lutilisateur dr du groupe
staff et `a lutilisateur zipstein quelque soit son groupe et qui refuse cet acc`es aux utilisateurs
du groupe licence.
chacl (binome.%,rwx)(%.@,--x)(%.%,---) catalogue projet
qui donne le droit dacc`es total `a lutilisateur binome (quelque soit son groupe), permet le
parcours du repertoire aux membres du groupe proprietaire et refuse lacc`es `a tous les autres utilisateurs.
Deux symboles speciaux :
% pour nimporte qui (utilisateur ou groupe)
@ pour le proprietaire ou le groupe proprietaire
On retrouve aussi les autres syntaxes de chmod par exemple :
chacl %.%=r fichier
ou
chacl @.%=5 fichier
Attention les acl sont detruits par la commande chmod et la commande chacl ne permet pas
de positioner les autres bits definis dans linode ; seuls les 9 bits de protections sont positionnables
par chacl.
Pour positionner les droits standard et des acl, il faut donc realiser en succession un chmod
puis un chacl.
On utilisera :
chacl (prof.%,rwx) catalogue projet
pour les projets de C ou de syst`eme.
La commande lsacl [fichiers] permet de connatre les acl associes aux fichiers, remarquer
qu`a linverse de /bin/ls cette commande na pas de param`etres par defaut.
14.6.1
ET SURET
DE FONCTIONNEMENT
CHAPITRE 14. SECURIT
E
E
116
);
Un bon exercice : recrire lsacl de facon quil fonctionne dune mani`ere similaire `a /bin/ls.
Utilisation de la commande script pour montrer le comportement des acl.
Script started on Fri May 5 10:33:20 1995
$ lsacl *
(dr.%,rw-)(%.staff,---)(%.%,---) fich
(dr.%,rw-)(%.staff,---)(%.%,---) file
(dr.%,rwx)(%.staff,---)(%.%,---) projet
$ chacl (prof.%,rwx) fich
$ lsacl *
(prof.%,rwx)(dr.%,rw-)(%.staff,---)(%.%,---) fich
(dr.%,rw-)(%.staff,---)(%.%,---) file
(dr.%,rwx)(%.staff,---)(%.%,---) projet
$ chacl (%.staff,rx) fich
$ lsacl *
(prof.%,rwx)(dr.%,rw-)(%.staff,r-x)(%.%,---) fich
(dr.%,rw-)(%.staff,---)(%.%,---) file
(dr.%,rwx)(%.staff,---)(%.%,---) projet
$ chacl (illouz.staff= fich
$ lsacl fich
(illouz.staff,---)(prof.%,rwx)(dr.%,rw-)(%.staff,r-x)(%.%,---) fich
$ chacl (prof.%,rx) . ..
$ su prof
Password:
$ cat fich
$ touch fich
$ chacl (dr.staff,x) fich
chacl: file "fich": Not owner (errno = 1)
$ lsacl *
(illouz.staff,---)(prof.%,rwx)(dr.%,rw-)(%.staff,r-x)(%.%,---) fich
(dr.%,rw-)(%.staff,---)(%.%,---) file
(dr.%,rwx)(%.staff,---)(%.%,---) projet
$ exit # du su
$ exit # du script
script done on Fri May
14.6.2
5 10:37:18 1995
117
118
ET SURET
DE FONCTIONNEMENT
CHAPITRE 14. SECURIT
E
E
Chapitre 15
Dans ce chapitre, nous voulons presenter le probl`eme des attentes actives sur plusieurs descripteurs.
Lexemple le plus frequent est celui dun serveur web, le serveur doit gerer simultanement un
tr`es grand nombre de flux dentree et de flux de sortie et de flux de controle (les information de
contr
ole des sockets).
15.1.1
Il est possible dutiliser des entree-sorties non bloquantes mais cest loing detre la solution
optimal car notre processus vas realiser de nombreux appels syst`eme inutile dautant plus si dans
le cas dun serveur avec des comportements de clients tr`es alleatoires. Le co
ut en ressources de
cette attente active est extremement cher, et doit etre evite dans le cas dune machine en temps
partage.
15.1.2
Utiliser les m
ecanismes asynchrones
On peut utiliser des entrees-sorties asynchrones et demander au noyau de nous prevenir par un
signal qui informe de larrivee de donnees sur un descripteur. Ce signal est SIGIO, mais ce nest
valable que sur les descripteurs qui sont des peripheriques. De plus ce mecanisme ne designe pas
le descripteur sur lequel sest faite larrivee de caract`eres, do`
u de nouvelles pertes de temps d
ues
aux appels realises inutilement en mode non bloquant.
15.2
Les outils de s
election
La solution la plus efficase vient de syst`emes de selection qui prend un param`etre un ensemble
de descripteurs, et qui permet tester si lun de ses descripteurs est pr`es `a satisfaire un appel syst`eme
read ou write. Cet appel est bloquant jusqu`a larrivee de caract`eres sur un des descripteurs de
lensemble. Ainsi il ny pas de consomation de ressource processus inutile, le travail est fait `a un
niveau plus bas (dans le noyau) de facon plus economique en ressources.
15.2.1
La primitive select
La premi`ere implementation dun outil de selection sous Unix est lappel syst`eme select, malheureusement sa syntaxe est devenu inadapte pour cituations ou le nombre de descipteur utilise
par le programme est tr`es grand ce qui peut arriver facilement avec un serveur de fichier. Nous
fournissont `a la primitive select :
119
CHAPITRE 15. MULTIPLEXER DES ENTREES-SORTIES
120
Les descripteurs que nous voulons scruter. (lindice du plus grand descripteur qui nous
interesse dans la table des descripteurs du processus)
Les conditions de reveil sur chaque descripteur (en attente de lecture, ecriture, ev`enement ?)
Combien de temps nous voulons attendre.
La fonction retourne pour chaque descripteur sil est pret en lecture, ecriture, ou si lev`enement
a eu lieu, et aussi le nombre de descripteur prets. Cette information nous permet ensuite dappeler
read ou write sur le(s) bon(s) descripteur(s).
#include
#include
#include
<sys/types.h>
<sys/time.h>
<unistd.h>
delai->tv sec > 0 && delai->tv usec >0 Semi bloquant, attente jusqu`a ce quun descripteur soit pret ou que le delai en secondes plus microsecondes soit ecoule.
Les trois pointeurs (readfds, writefds, et exceptfds) sur des ensembles de descripteurs sont
utilises pour indiquer en entree les situations qui nous interessent. Cest `a priori (cela peut varier
avec limplementation) des tableaux de bits avec un bit pour chaque descripteur du tableau de
descripteurs du processus. Lentier maxfd est la position du dernier bit significatif de ce tableau
de bits.
Les seules facons de manipuler ces ensembles de descripteurs sont :
Allocation :fd\_set *fd=(fd\_set*)malloc(sizeof(fd\_set));
Creation
Affectation
Utilisation dune des quatre macros suivantes :
FD ZERO(fd set fdset) RAZ de lensemble.
FD SET(int fd, fd set *fdset) Positionne le bit fd a 1.
FD CLR(int fd, fd set *fdset) Positionne le bit fd `a 0
FD ISSET(int fd, fd set *fdset) vrai si le bit fd est `a 1 dans lensemble.
Un descripteur est considere comme pret en lecture si un appel read dessus ne sera pas bloquant. De meme, un descripteur est considere comme pret en ecriture si un appel write ne sera pas
bloquant. Les exceptions / ev`enements sont definis pour les lignes de communication qui acceptent
les messages hors bande comme les sockets en mode datagramme.
15.2. LES OUTILS DE SELECTION
15.2.2
121
La primitive poll
La primitive poll fournit un service proche de select avec une autre forme dinterface. Cette
interface est adaptee quand le nombre de descripteurs ouvert par le processsus est tr`es grand mais
que lon ne sinter`esse qua un petit nombre de ceux-ci.
#include <stropts.h>
#include <poll.h>
int poll(struct pollfd fdarray[],
unsigned long nfds,
int
timeout
);
struct pollfd
int
short
short
};
{
fd;
events;
revents;
Ici on specifie la liste de descripteurs (dans un tableau) et ce que lon veut g`eter sur chacun
deux.
La valeur de retour est -1 en cas derreur, 0 si le temps dattente timeout est ecoule, ou un
entier positif indiquant le nombre de descripteurs pour lesquels la valeur du champ revents a ete
modifiee.
Les ev`enements sont ici :
Pour les ev`enements de events :
POLLIN Donnees non prioritaire peuvent etre lues.
POLLPRI Donnees prioritaire peuvent etre lues.
POLLOUT Donnees non prioritaire peuvent etre ecrites, les messages de haute priorite peuvent
toujours etres ecrits.
Pour les revents (valeurs de retour de la primitive poll) :
POLLIN,POLLPRI les donnees sont l`a.
POLLOUT lecriture est possible
POLLERR Une erreur a eu lieu.
POLLHUP La ligne a ete coupee.
POLLNVAL Descripteur invalide.
Le mode de blocage de la primitive poll depend du param`etre timeout
timeout == INFTIM Bloquant, INFTIM est defini dans stropts.h.
timeout == 0 Non bloquant.
timeout > 0 Semi bloquant, attente de timeout micro secondes.
Un Exemple Attente de donnees sur ifd1 et ifd2, de place pour ecrire sur ofd, avec un
delai maximum de 10 seconds :
#include <poll.h>
struct pollfd fds[3] ;
int ifd1, ifd2, ofd, count ;
fds[0].fd = ifd1 ;
fds[0].events = POLLIN ;
fds[1].fd = ifd2 ;
fds[1].events = POLLIN ;
fds[2].fd = ofd ;
CHAPITRE 15. MULTIPLEXER DES ENTREES-SORTIES
122
fds[2].events = POLLOUT ;
count = poll(fds, 3, 10000) ;
if (count == -1) {
perror("poll failed") ;
exit(1) ;
}
if (count==0)
printf("Rien \n") ;
if (fds[0].revents & POLLIN)
printf("Donn
ees a lire sur ifd%d\n", fds[0].fd) ;
if (fds[1].revents & POLLIN)
printf("Donn
ees a lire sur ifd%d\n", fds[1].fd) ;
if (fds[2].revents & POLLOUT)
printf("De la place sur fd%d\n", fds[2].fd) ;
15.2.3
Le p
eriph
erique poll
Dans le cas de serveur travaillant avec un tr`es grand nombre de descripteurs (plueirus dizaine
de milliers de descripteurs) les deux syntaxes poll et select sont inefficaces. Soit dans le cas
deselect car le nombre de descripteurs scrutes par le noyau est tr`es grand alors quun tr`es faible
par dentre eux sont inutilise. Soit dans le cas de poll car il faut manipuler avant chaque appel
un tr`es grand tableau et que le syst`eme doit relire ce tableau a chaque appel.
Pour resoudre ce probl`eme une nouvelle interface a ete mise au point /dev/poll. Cette interface
permet de creer un peripherique poll dans lequel il suffit decrire pour ajouter un descripteur a
la liste des descipteurs que le noyau doit scruter. Et il suffit decrire de nouveau pour retirer un
descripteur.
Epoll est un patch du noyau !1
1. Il faut verifier la presence depoll sur votre syst`eme, ouvrer le peripherique /dev/epoll en
mode O RDWR, sinon retour a select et poll kdpfd = open("/dev/epoll",O_RDWR);
2. Definiser le nombre maximal maxfd de descipteurs scrutables #include <linux/eventpoll.h> \ldots ioctl(epol
3. Allouer un segment de memoire partage avec char *map = (char *)mmap(NULL, EP MAP SIZE(maxfds,
PROT READ | PROT WRITE, MAP PRIVATE, epoll fd, 0))
4. Maintenant vous pouvez ajouter des descipteurs
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN | POLLOUT | POLLERR | POLLHUP;
pfd.revents = 0;
if (write(kdpfd, &pfd, sizeof(pfd)) != sizeof(pfd)) {
/* gestion derreur */
}
5. Recupere les evenements
struct pollfd *pfds;
struct evpoll evp;
for (;;) {
evp.ep_timeout = STD_SCHED_TIMEOUT;
evp.ep_resoff = 0;
nfds = ioctl(kdpfd, EP_POLL, &evp);
1 Il
existe deux version une version /Dev/poll et une version /dev/epoll qui faut utiliser car plus efficasse.
15.3. UNE SOLUTION MULTI-ACTIVITES
123
15.2.4
Une extension readv, writev de read et write permet en un seul appel syst`eme de realiser
lecriture de plusieurs zones memoire non contigues, ce qui permet daccelerer certaines entreessorties structurees. Mais aussi de mieux organiser les appels syst`eme dans notre cas.
#include <sys/types.h>
#include <sys/uio.h>
ssize_t readv(int fd, const struct iovec iov[], int iovl);
ssize_t writev(int fd, const struct iovec iov[], int iovl);
struct iovec {
void *iov_base ;
int
iov_len;
};
15.3
Lutilisation de plusieurs activites (threads, voir chapitre 16) permet de realiser plusieurs appels
de read en simultane, le premier read qui se debloque entraine lexecution de lactivite le realisant,
ainsi le co
ut dattente sur les descripteurs est minimal le syst`eme signalant imediatement `a la thread
levenement. Le seul probl`eme est davoir a gerer cette multiplicite dactivites, ce qui est dans le
cas dun simple echange bidirectionel est raisonable il suffit de deux activites independantes.
Pour un serveur de fichier cette solutions multi-activite peut ne pas supporter la monte en
charge le nombre de threads etant limite plus rapidement que celui des descripteurs (a ma connaissance ont peut creer au plus 10000 threads sous linux et xp)
Pour une situation plus complexe comme un serveur de partage de donnees, des mecanismes
dexclusion mutuelle entre activites devront etre mis en oeuvre, ce qui peut compliquer inutilement
le probl`eme. La solution avec un seul processus gerant rapidement des requetes multiples sur
plusieurs flux etant plus simple a realiser.
124
Chapitre 16
16.0.1
Description
Un processus est compose des parties suivantes : du code, des donnees, une pile, des descripteurs
de fichiers, des tables de signaux. Du point de vue du noyau, transferer lexecution `a un autre
processus revient `a rediriger les bons pointeurs et recharger les registres du processeur de la pile.
Les divers threads dun meme processus peuvent partager certaines parties : le code, les donnees,
les descripteurs de fichiers, les tables de signaux. En fait, ils ont au minimum leur propre pile, et
partagent le reste.
16.0.2
fork et exec
Apr`es un fork, le fils ne contient quune seule activite (celle qui a execute le fork). Attention aux variables dexclusion mutuelle (qui font partie de lespace dadressage partage) qui sont
125
126
Donnes de la Tache
rpertoire de travail
umask
Descripteurs
Accs aux tables de pages
* programme
* donnes globales
* pile globale
Propritaires
Scheduling
Donnes de Registres
laThread 1 Pile noyau
Scheduling
Donnes de Registres
laThread 2 Pile noyau
Scheduling
Donnes de Registres
laThread 3 Pile noyau
Fig. 16.1 Organisation memoire, partage des fonctions entre le processus et les activites
127
conservees apr`es le fork() et dont le contenu ne varie pas. Ainsi si une activite a pris le semaphore
avant le fork(), si lactivite principale cherche `a prendre ce semaphore apr`es le fork() elle sera
indefiniment bloquee.
Apr`es un exec, le processus ne contient plus que la thread qui a execute lune des six commandes
exec. Pas de probl`eme avec les semaphores comme lespace dadressage a change.
16.0.3
clone
Sous linux (et rarement sous les syst`emes Unix) il existe un appel syst`eme un peut special. Cet
appel syst`eme realise un dedoublement du processus comme fork dou son nom de clone. Cet
appel syst`eme permet de preciser exactement ce que lon entend partager entre le processus p`ere
et le processus fils.
Elements partageables :
ppid Creation dun fr`ere au lieux dun fils.
FS Partage de la structure dinformation liee au syst`eme de fichier (., /, umask),
FILES Partage de la table des descripteurs,
SIGHAND Partage de la table des gestionnaires de Signaux, mais pas des masques de signaux,
PTRACE Partage du crochet (hook) de debug voire lappel ptrace.
VFORK Partage du processeur ! le processus p`ere est bloque tantque le fils na pas execute soit
exit soit execve, cest `a dire quil sest detache de tout les element partageable du processus
p`ere (sauf les FILEs),
VM Partage de la memoire virtuelle, en particulier les allocations et desallocations par mmap et
munmap sont visibles par les deux proccessus.
pid Les deux processus ont le meme numero.
THREAD Partage du groupe de thread, les deux processus sont ou ne sont pas dans le meme
groupe de threads.
16.0.4
pthread[_objet]_operation[_np]
o`
u
objet designe si il est present le type de lobjet auquel la fonction sapplique. Les valeurs possibles
de objet peuvent etre
cond pour une variable de condition
mutex pour un semaphore dexclusion mutuelle
op
eration designe loperation a realiser, par exemple create, exit ou init
le suffixe np indique, si il est present, quil sagit dune fontion non portable, cest-`a-dire Hors
Norme.
16.0.5
pthread[_objet]_t
avec objet prenant comme valeur cond, mutex ou rien pour une thread.
128
16.0.6
Identification dune pthread : le TID de type pthread t obtenu par un appel `a la primitive :
pthread_t pthread_self(void);
pour le processus proprietaire
pid_t getpid(void);
En POSIX, le fait de tuer la thread de numero 1 a pour effet de tuer le processus ainsi que
toutes les autres threads eventuelles du processus.
Pour tester legalite de deux pthreads on utilise
int pthread_equal(pthread_t tid1, pthread_t tid2);
16.0.7
Cr
eation et terminaison des activit
es
Cr
eation
int pthread_create (pthread_t
pthread_attr_t
void
void
);
*p_tid,
attr,
*(*fonction) (void *arg),
*arg
16.1
Synchronisation
16.1. SYNCHRONISATION
129
Thread 2
access
open
Lecture
incorrecte
Fig. 16.2 Changement de la valeur errno par une autre thread
16.1.1
Le mod`
ele fork/join (Paterson)
16.1.2
Le probl`
eme de lexclusion mutuelle sur les variables g
er
ees par
le noyau
Il est necessaire davoir plusieurs variables errno, une par activite. En effet cette variable
globale pourrait etre changee par une autre activite. Voir plus loin comment definir des variables
globales locales `a chaque activite.
16.1.3
Les s
emaphores dexclusion mutuelle
130
16.1.4
Utilisation des s
emaphores
Operation P :
Un appel `a la fonction
pthread_mutex_lock (pthread_mutex_t *pmutex);
permet `a une activite de realiser une operation P sur le semaphore. Si le semaphore est dej`
a
utilise, lactivite est bloquee jusqu`a la realisation de loperation V (par une autre activite) qui
lib`erera le semaphore.
Operation P non bloquante :
pthread_mutex_trylock (pthread_mutex_t *pmutex);
renvoie 1 si le semaphore est libre
0 si le semaphore est occupe par une autre activite
-1 en cas derreur.
Operation V :
Un appel `a la fonction
pthread_mutex_unlock(pthread_mutex_t *pmutex);
realise la liberation du semaphore designe.
16.1.5
Les conditions (
ev`
enements)
Les conditions permettent de bloquer une activite sur une attente dev`enement. Pour cela
lactivite doit posseder un semaphore, lactivite peut alors liberer le semaphore sur lev`enement,
cest-`a-dire : elle lib`ere le semaphore, se bloque en attente de lev`enement, `a la reception de
lev`enement elle reprend le semaphore.
Initialisation dune variable de type pthread_cond_t
int pthread_cond_init (pthread_cond_t *p_cond, pthread_condattr_t attr);
Lattente sur une condition
int pthread_cond_wait (pthread_cond_t *p_cond, pthread_mutex_t *p_mutex);
Trois etapes
1. liberation sur semaphore *p mutex
2. activite mise en sommeil sur lev`enement
3. reception de lev`enement, recuperation du semaphore
La condition est independante de levenement et nest pas necessairement valide `a la reception
(cf. exemple).
Exemple, le programme suivant :
pthread_mutex_t m;
pthread_cond_t cond;
int
condition = 0;
void *ecoute(void *beurk)
{
pthread_mutex_lock(m);
sleep(5);
while (!condition)
pthread_cond_wait(cond, m);
16.1. SYNCHRONISATION
131
pthread_mutex_unlock(m);
pthread_mutex_lock(print);
printf(" Condition realisee\n");
pthread_mutex_unlock(print);
}
main()
{
pthread_t lathread;
pthread_create(lathread, pthread_attr_default, ecoute, NULL);
sleep(1);
pthread_mutex_lock(m);
condition = 1;
pthread_mutex_unlock(m);
pthread_cond_signal(cond);
}
Un autre exemple dutilisation de condition avec deux threads qui utilisent deux tampons pour
realiser la commande cp, avec une activite responsable de la lecture et lautre de lecriture. Les
conditions permettent de synchroniser les deux threads. Ici nous utilisons la syntaxe NeXT/MACH.
#include <sdtio.h>
#include <fcntl.h>
#import <mach/cthreads.h>
enum { BUFFER_A_LIRE = 1, BUFFER_A_ECRIRE = -1 };
mutex_t
lock1;
condition_t cond1;
char
int
int
int
buff1[BUFSIZ];
nb_lu1;
etat1 = BUFFER_A_LIRE;
ds, dd;
/* descripteurs source et destination */
lire()
/* activite lecture */
{
for(;;) { /* lecture dans le buffer 1 */
mutex_lock(lock1);
while (etat1 == BUFFER_A_ECRIRE)
condition_wait(cond1, lock1);
nb_lu1 = read(ds, buff1, BUFSIZ);
if (nb_lu1 == 0)
{
etat1 = BUFFER_A_ECRIRE;
condition_signal(cond1);
mutex_unlock(lock1);
break;
}
etat1 = BUFFER_A_ECRIRE;
condition_signal(cond1);
mutex_unlock(lock1);
132
}
ecrire()
{
for(;;)
{ /* ecriture du buffer 1 */
mutex_lock(lock1);
while (etat1 == BUFFER_A_LIRE)
condition_wait(cond1, lock1);
if (nb_lu1 == 0)
{
mutex_unlock(lock1);
exit(0);
}
write(dd, buff1, nb_lu1);
mutex_unlock(lock1);
etat1 = BUFFER_A_LIRE;
condition_signal(cond1);
}
}
main()
{
ds
dd
lock1
cond1
=
=
=
=
open(argv[1], O_RDONLY);
open(argv[2], O_WRONLY|O_TRUNC|O_CREAT, 0666);
mutex_alloc();
condition_alloc();
cthread_fork((cthread_fn_t)lire, (any_t)0);
ecrire(); /* la thread principale realise les ecritures */
}
16.2
16.2.1
Lordonnancement des activites DCE base sur POSIX est tr`es similaire `a lordonnancement
des activites sous MACH. Deux valeurs permettent de definir le mode dordonnancement dune
activite :
la politique et la priorite.
Pour manipuler ces deux valeurs, il vous faut creer un objet attribut dactivite (pthread_attr) en
appelant pthread_attr_create(), puis changer les valeurs par defaut avec les fonctions decrites
plus loin et creer la pthread avec cet objet pthread_attr. Ou bien la pthread peut elle-meme
changer ses deux valeurs, priorite et politique.
Les fonctions sont :
#include <pthread.h>
pthread_attr_setsched(pthread_attr_t *attr, int politique);
Les differentes politiques possibles sont :
SCHED FIFO La thread la plus prioritaire sexecute jusqu`a ce quelle bloque. Si il y a plus
dune pthread de priorite maximum, la premi`ere qui obtient le cpu sexecute jusqu`a ce
quelle bloque.
` UNE THREAD
16.3. LES VARIABLES SPECIFIQUES
A
133
SCHED RR Round Robin. La thread la plus prioritaire sexecute jusqu`a ce quelle bloque. Les
threads de meme priorite maximum sont organisees avec le principe du tourniquet, cest-`adire quil existe un quantum de temps au bout duquel le cpu est preempte pour une autre
thread (voire Chapitre 6 sur les Processus).
SCHED OTHER Comportement par defaut. Tous les threads sont dans le meme touniquet, il
ny a pas de niveau de priorite, ceci permet labsence de famine. Mais les threads avec une
politique SCHED FIFO ou SCHED RR peuvent placer les threads SCHED OTHER en situation de
famine.
SCHED FG NP (option DCE non portable) Meme politique que SCHED OTHER mais lordonnanceur peut faire evoluer les priorites des threads pour assurer lequite.
SCHED BG NP (option DCE non portable) Meme politique que SCHED FG NP, mais les threads
avec une politique SCHED FIFO ou SCHED RR peuvent placer les threads SCHED BG NP en situation de famine.
pthread_attr_setprio(pthread_attr_t *attr, int prio);
La priorite varie dans un intervalle defini par la politique :
PRI OTHER MIN <= prio <= PRI OTHER MAX
PRI FIFO MIN <= prio <= PRI FIFO MAX
PRI RR MIN <= prio <= PRI RR MAX
PRI FG MIN NP <= prio <= PRI FG MAX NP
PRI BG MIN NP <= prio <= PRI BG MAX NP
Ces deux fonctions retournent 0 en cas de succ`es et -1 sinon. La valeur de errno indiquant si
lerreur est une question de param`etres ou de permission.
Les deux fonctions que lon peut appeler sur une pthread pour changer sa priorite ou sa
politique sont :
pthread_setprio(pthread_t *unepthread, int prio);
pthread_setsched(pthread_t *unepthread, int politique, int prio);
Il est possible de connatre la priorite ou la politique dune pthread ou dun objet pthread attr
avec :
pthread_attr_getprio(pthread_attr_t *attr,int prio);
pthread_attr_getsched(pthread_attr_t *attr,int politique);
pthread_getprio(pthread_t *unepthread, int prio);
pthread_getsched(pthread_t *unepthread, int politique);
16.3
Les variables sp
ecifiques `
a une thread
Avec un processus multi-threads, nous sommes dans une situation de partage de donnees.
Toutes les donnees du processus sont `a priori manipulables par toutes les threads. Or certaines
donnees sont critiques et difficilement partageables. Premi`erement ce sont les donnees de la biblioth`eque standard. Pour les fonctions de la biblioth`eque standard, on peut resoudre le probl`eme
en utilisant un semaphore dexclusion mutuelle pthread_mutex_t pour POSIX.
Mais certaines variables ne peuvent etre protegees. Cest le cas de la variables errno, comme
nous lavons vu precedemment. Pour cette variable, la solution est davoir une variable par thread.
Ainsi le fichier <errno.h> est modifie et contient :
extern int *_errno();
#define errno (*_errno())
La valeur errno est obtenue par une fonction qui retourne la valeur de errno associee `a la
thread qui fait lappel `a errno .
134
16.3.1
Principe g
en
eral des donn
ees sp
ecifiques, POSIX
Lidee des donnees specifique est de creer un vecteur pour chaque donnee specifique. Ainsi
pour des donnees specifique statiques, chaque thread poss`ede son propre exemplaire. Les donnees
specifiques sont identifiees par des cles de type pthread_key_t.
16.3.2
Cr
eation de cl
es
La creation dune cle est liee `a la creation dun tableau statique (variable globale), initialise `a
NULL `a la creation. La fonction
#include <pthread.h>
int pthread_keycreate (pthread_key_t *p_cle,
void
(*destructeur)(void *valeur));
permet la creation du tableau, 0 succ`es et -1 echec. La structure pointee par p_cle nous
permettra dacc`eder aux valeurs stockees, la cle est evidemment la meme pour toutes les threads. Le
param`etre destructeur de type pointeur sur fonction prenant un pointeur sur void en param`etre
et renvoyant void, donne ladresse dune fonction qui est executee `a la terminaison de la thread
(ce qui permet de faire le menage). Si ce pointeur est nul, linformation nest pas detruite `a la
terminaison de lactivite.
16.3.3
Lecture/
ecriture dune variable sp
ecifique
La fonction
#include <pthread.h>
int pthread_getspecific (pthread_key_t *p_cl
e, void **pvaleur);
permet la lecture de la valeur qui est copie `a ladresse pvaleur retourne 0 ou -1 selon que
lappel `a reussi ou non. La fonction
#include <pthread.h>
int pthread_setspecific (pthread_key_t *p_cl
e, void *valeur);
permet lecriture `a lemplacement specifie de valeur retourne 0 ou -1 selon que lappel a reussit
ou non.
16.4
Certaines fonctions standardes comme ttyname() ou readdir() retourne ladresse dune zone
statique. Plusieurs threads en concurrence peuvent donc nous amener `a des situations incoherentes.
La solution des semaphores dexclusion etant co
uteuse, ces fonctions sont reecrites pour la biblioth`eque de thread de facon `a etre reentrantes.
Attention les probl`emes de reentrance peuvent avoir lieu en utilisant des appels syst`emes non
reentrant dans les handlers de signaux ! Ceci sans utiliser de threads !
Chapitre 17
Clustering
Le clustering sont des techniques lies a lutilisation de grappes dordinateurs utilise comme
un super ordinateur avec plusieurs processeurs. Lobjectif est le RAIP : Redundant Array of
Inexpensive PROCESSOR.
la station de trvail individuelle vielli a grande vitesse, une facon de recycler ceux qui sont en
peu trop vieux (mais pas encore trops vieux) est de les rassembler dans votre premier cluster. De
ces PC nous allons tirer un super calculateur, bien sur il est toujours plus rapide dachetter un
G5 si on en a les moyens, pour les mainframes (je laffirme vous nen avez pas les moyens ou alors
vous en avez deja plusieurs...)1 .
Il existe differentes techniques de clustering pour different objectifs :
Tol
erence au pannes Google, le cluster est organise pour assurer la redondance des unite de
calcul pour assurer la continuite de service.
Super calculateur Earth Simulator,Plusieurs processeurs travaillant en meme temps permet
doptenir un super calculateur `a peu de frais, comme les processeurs qui compose chaque
noeud sont bon marche. IL faut que le probl`eme sy pr`ete cest le cas des calculs meteorologiques
et des calculs de simulation `a grande echelle.
Mont
e en charge Google, Le probl`eme pour une application nest pas toujours un probl`eme
de puissance de calcul parfois ce qui posse probl`eme cest la quantite dentrees sorties
qui faut assurer. Vous pouvez dailleurs facilement tester cette propriete en realisant un
petit programme qui sans saturer lunite central sature compl`etement les entrees sorties
while :;do; { cp grosfichier /tmp/$PID } &; done
Ainsi le clustering a essentiellement pour objectif dutiliser le dicton lunion fait la force pour
resoudre une difficulte de calcul.
17.1
Pour plus dinformation le vous conseil le site suivant qui vous donnera de bonnes references.
http://www-igm.univ-mlv.fr/~dr/Xpose2001/vayssade/
1 Cest evident si vous avez les moyens dacheter un mainframe vous avez les moyens dachetter un super-cluster
haut de gamme.
135
136
Chapitre 18
Bibliographie
J.-M. Rifflet. La programation sous UNIX. Ediscience, 1993. Le manuel de reference.
A.Tanenbaum. Syst`emes dexploitation, sysyt`emes centralises, syst`emes distribues. Inter-Editions,
1994. Cours general sur les syt`emes dexploitation.
M. Bach. The design of the UNIX operating system. 1986. Prentice-Hall, Englewood Cliffs,
N.J. ISBN 0-13-201757-1
J. Beauquier & B. Berard Syst`emes dexploitation concepts et algorithmes. 1991. McGraw-Hill.
ISBN 2-7042-1221-X
W.R. Stevens, UNIX Network Programming. 1990 Prentice-Hall, Englewood Cliffs, N.J.
W.R. Stevens, Advanced Programming in the UNIX Environnement Addison-Wesley ISBN 0201-56317-7
18.1
Webographie
137
Index
/dev/epoll, 156
/dev/null, 105
/dev/poll, 156
/dev/pty, 110
/dev/tty, 104
introduction, 41
ioctl, 111
isatty, 103
kill, 113, 114
listen, 177
mkfifo, 100
mknod, 100
mmap, 92
munmap, 92
nice, 60
open, 41
pause, 120, 121
pipe, 97
poll, 155
putmsg, 173
putpmsg, 173
read, 44, 99
recv, 178
recvfrom, 178
recvmsg, 178
sbrk, 60
select, 153
send, 178
sendmsg, 178
sendto, 178
setgid, 59
setpgid, 105
setsid, 104
setsockopt, 179
setuid, 59
sigaction, 121
siginterrupt, 119
siglongjmp, 118
signal, 115
sigpause, 120
sigprocmask, 120
sigsetjmp, 118
sleep, 57
socket, 175
socketpair, 176
tcdrain, 110
tcflush, 110
tcgetattr, 109
tcgetgrp, 106
tcgetsid, 106
acc`es direct, 34
acc`es sequentiel, 34
Allocation contigue, 77
appels syst`emes
exit, 38
accept, 178
brk, 60
cfgetispeed, 110
cfgetospeed, 110
cfsetispeed, 110
cfsetospeed, 110
chdir, 59
chroot, 59
close, 46
connect, 177
creat, 44
dup, 45
dup2, 46
exec, 51
execle, 61
execlp, 61
execv, 61
execve, 50, 61
execvp, 61
exit, 57
fchdir, 59
fcntl, 46
fork, 50, 51, 56, 61
getgrp2, 105
getmsg, 173
getpeername, 179
getpgrp, 59, 105
getpgrp2, 59
getpid, 59
getppid, 59
getsid, 106
getsockname, 179
getsockopt, 179
htonl, 179
138
INDEX
tcsetattr, 109
tcsetpgrp, 106
times, 58
ttyname, 104
ulimit, 60
umask, 60
write, 44, 100
arri`ere plan, 105
Best-fit, 81
biblioth`eques, 5
boot bloc, 10
buffer cache, 25
bufferisation, 35
bufferiser, 25
chargement dynamique, 86
compactage, 81
desarmer, 55
Demand Paging, 86
Demand-Paging, 68
droits, 7
exclusion mutuelle, 63
famine, 63
FCFS, 65
ffs, 17
fichier, 7
inodes, 9
ordinaires, 8
physiques, 8
speciaux, 8
fifo, 100
FILE, 31
First-fit, 81
groupe, 7, 10
handler, 114
HotSwap, 182
inodes, 9, 11
interruption, 54
intr, 104, 113
lazy swapper, 86
load, 68
longjmp, 114
Metadisque, 182
masquer, 55
mkfifo, 100
noyau, 5
139
ordonnancement, 63, 82
overlays, 85
page fault, 86
pages, 82
pendant, 114
physique, 103
pile, 50
pointeur de fichier, 34
preemption, 65
premier plan, 105
priorite, 67
proc, 22
processus, 49
$DATA$, 50
$TEXT$, 50
etats, 55, 57
accumulateur, 53
changement de contexte, 53
commutation de mot detat, 53, 54
compteur ordinal, 53
context, 53
creation, 49
decomposition, 49
format de fichier, 50
mode dun, 55
mot detat, 53
niveau dinterruption, 54
struct proc, 49
recouvrement, 50
swapin, 57
swapout, 57
table des processus, 51
table des regions par processus, 51
struct user, 49
zone u, 51, 58
proprietaire, 7, 10
protocole, 175
pseudo-terminaux, 103, 110
quit, 104, 113
reference, 7
RAID, 181
redirection, 32
registre barri`ere, 77
registre base, 77
Round Robin, 66
SIGHUP, 104, 113
SIGINT, 113
signaux, 113
kill, 113
SJF, 65
140
static, 104
stdio.h, 31
stdlib
atexit, 38
clearerr, 39
exit, 38
fclose, 36
feof, 33, 39
fflush, 36
fopen, 32
fread, 33
freopen, 32, 35
fseek, 34
ftell, 35
fwrite, 33
mkdir, 39
perror, 39
printf, 31
remove, 37
rename, 37
rewind, 35
rmdir, 39
scanf, 31
setbuf, 37
setbuffer, 37
setlignebuf, 37
setvbuf, 36
stderr, 31
stdin, 31
stdout, 31
system, 38
tmpfile, 33
tmpnam, 33
Xalloc, 51
super bloc, 10
susp, 104, 113
swap, 79, 85
synchronisation, 101
Syst`eme de Gestion de Fichiers, 7
tas, 50
terminal de controle, 104
termios, 106
tubes, 97
tubes nommes, 100
Worst-fit, 81
INDEX