Processus
Processus
Processus
Chapitre II :
Amine DHRAIEF
Rappel : Les Processus
11/02/18 OS II 2
Rappel : Les Processus
●
Un processus est souvent définit comme étant un programme en
exécution.
– Un processus est plus que le code du programme (text section)
●
Un processus inclus une représentation de l'activité en cours du
programme :
– Le contenu des registres du processeur tel que le program counter (PC) (un
registre qui contient l’adresse mémoire de l’instruction en cours/prochaine
selon les architectures des CPUs)
– une pile d’exécution qui contient des données provisoires (tels que la
fonction, les paramètres, des adresses de retour, et les variables locales),
– une section de données (data section), qui contient les variables globales.
– un tas (heap) qui est un mémoire allouée dynamiquement lors de l'exécution
processus.
11/02/18 OS II 3
Rappel : Les Processus
Representation d'un
processus en mémoire
11/02/18 OS II 4
Rappel : Les Processus
●
Le programme n'est pas en soi un processus !
– un programme est une entité passive, comme un fichier contenant
une liste d'instructions
– alors qu'un processus est une entité active avec un ensemble de
ressources associées.
→ Un programme devient un processus lorsqu'un fichier exécutable
est chargé en mémoire.
●
Même si deux processus peuvent être associés à un même
programme, ils sont néanmoins considérés comme deux
séquences d'exécution séparées.
– Chacune d'elles est un processus distinct, et bien que les sections de
texte sont équivalentes, les data section, la pile, le tas sont différents.
11/02/18 OS II 5
Rappel : Les Processus
●
Chaque processus est
représenté dans le système
d'exploitation par un bloc de
contrôle de processus (Process
Control Block - PCB) appelé
aussi un task-control block
●
Le système d’exploitation
maintient dans une table
appelée «table des processus»
– les informations sur tous les
processus créés (une entrée par
processus : PCB).
11/02/18 OS II 6
Rappel : Les Processus
11/02/18 OS II 7
Rappel : Les Processus
11/02/18 OS II 8
Rappel : Les Processus
Appel systéme fork()
●
Le parallélisme Unix bas niveau est fourni
par le noyau qui duplique un processus
lorsqu’on invoque l’appel-système fork() .
●
Les deux processus sont alors strictement
identiques, et seule la valeur de retour de
fork() permet de les distinguer.
11/02/18 OS II 9
Rappel : Les Processus
Comment faire un processus ?
●
Un nouveau processus est créé par fork() du système appelant.
●
Le nouveau processus comprend une copie de l'espace
d'adressage du processus original.
– Ce mécanisme permet au processus parent de communiquer facilement avec
son processus enfant.
●
Les deux processus (le parent et l'enfant) poursuivre l'exécution à
l'instruction après le fork(), avec une différence:
– le code retour du fork() est égal à zéro pour le nouveau (enfant)
processus,
– alors que le PID (non nulle) de l'enfant est retourné au processus père.
11/02/18 OS II 10
Rappel : Les Processus
Comment faire un processus ?
●
L'appel-système fork() est déclaré dans <unistd.h> : pid_t fork(void);
●
DEUX valeurs de retour en cas de succès:
– Dans le processus père : valeur de retour = le PID du fils,
– Dans le processus fils : valeur de retour = zéro.
●
Sinon
– erreur : valeur de retour = -1.
●
Afin d'obtenir le numéro du processus, il suffit de faire l'appel système
getpid(), ou getppid() pour obtenir le numéro du père.
– PID (Process IDentifier)
– PPID : numéro du processus père (Parent Process Identifier)
11/02/18 OS II 11
Rappel : Les Processus
Naissance d’un processus
exemple
11/02/18 OS II 12
Rappel : Les Processus
Mort naturelle et Zombie
●
Un processus peut se terminer normalement ou
anormalement.
●
Dans le premier cas, l'application est abandonnée à la
demande de l'utilisateur, ou la tâche à accomplir est finie.
●
Dans le second cas, un dysfonctionnement est
découvert, qui est si sérieux qu'il ne permet pas au
programme de continuer son travail
11/02/18 OS II 13
Rappel : Les Processus
Mort naturelle d’un processus
●
Un programme peut se finir de plusieurs manières. La plus simple est de
revenir de la fonction main( ) en renvoyant un compte rendu d'exécution
sous forme de valeur entière.
●
Cette valeur est lue par le processus père, qui peut en tirer les
conséquences adéquates.
– Par convention, un programme qui réussit à effectuer son travail renvoie une valeur
nulle, tandis que les cas d'échec sont indiqués par des codes de retour non nuls (et qui
peuvent être documentés avec l'application).
●
Il est possible d'employer les constantes symboliques EXIT_SUCCESS ou
EXIT_FAILURE définies dans <stdlib.h>.
– Ceci a l'avantage d'adapter automatiquement le comportement du programme, même
sur les systèmes non-Posix, où ces constantes ne sont pas nécessairement 0 et 1.
11/02/18 OS II 14
Rappel : Les Processus
Orphelin et Zombie
●
Processus orphelins
– si un processus père meurt avant son fils ce dernier
devient orphelin.
●
Processus zombie
– Si un fils se termine tout en disposant toujours d'un PID
celui-ci devient un processus zombie
– Le cas le plus fréquent : le processus s’est terminé mais
son père n’a pas (encore) lu son code de retour.
11/02/18 OS II 15
Rappel : Les Processus
Applications
11/02/18 OS II 16
Exercice #1
1)Répondre par OUI ou NON en justifiant vos
réponses.
1)Un processus est une entité produite après
compilation
2)Un processus est une entité produite après
chargement d’un binaire en mémoire
3)Le pseudo-parallélisme impose aux processus de
se connaître mutuellement
11/02/18 OS II 17
Correction Exercice #1
●
1. Un processus est une entité produite après compilation
– Non, car un processus est une image d’un programme en exécution
●
2. Un processus est une entité produite après chargement d’un
binaire en mémoire
– Oui, car une fois terminé le chargement d’un programme en mémoire un
processus est créé
●
3. Le pseudo-parallélisme impose aux processus de se connaître
mutuellement
– Non, car en pseudo-parallélisme les processus perdent la main au profit du
système d’exploitation qui allouera le CPU pour un processus éligible
11/02/18 OS II 18
Exercice #2
●
Préciser le nombre de processus créer par les
programmes ci-dessous :
Code1 Code 2 Code 3
11/02/18 OS II 19
Correction Exercice #2
code 1
●
8 processus sont crées :
– L'exécution du programme crée un P1
processus P1.
– A la lecture de la première instruction
fork() , P1 se duplique et crée alors P2. P2 P3 P5
Les deux processus continuent
l'exécution à partir de la ligne incluse ;
– A la lecture de la seconde instruction P4 P6 P7
fork(), P1 se duplique et crée P3 tandis
que P2 crée P4.
– Les quatre processus continuent
P8
l’exécution a partir de la ligne incluse ;
– A la lecture de la troisième instruction
fork(), P1 se duplique et crée P5, P2
11/02/18 crée P6, P3 crée P7 et P4 crée OSP8
II 20
Correction Exercice #2
code 2
●
3 processus sont crées:
– L'exécution du programme crée un P1
processus P1.
– A la lecture de la première instruction fork(),
P1 se duplique et crée alors P2. P1 est le
processus parent, P2 le processus enfant. P2 P3
11/02/18 OS II 23
Exercice #3
●
1- Lancer le programme ci-dessous avec les
arguments 10 20. Que constatez-vous ?
Donnez une explication.
●
2- Lancer le programme ci-dessous avec les
arguments 10 0. Que constatez-vous ? Donnez
une explication.
11/02/18 OS II 24
Correction Exercice #3
●
1- Le père meurt avant son fils, le fils devient
orphelin
●
2- Le fils meurt avant son père, le père est en
sommeil, il ne lit pas le code de retour de son
fils. Le fils devient zombie.
11/02/18 OS II 25
LE MULTITHREADING
11/02/18 OS II 26
Présentation
●
Le concept de processus se traduit par deux
caractéristiques:
2)Ordonnancement / exécution :
●
L'exécution d'un processus suit un chemin d'exécution (une trace)
●
Un processus a un état ( Ready, Running,…)
●
Une priorité
●
Est ordonnancé par l'OS
11/02/18 OS II 27
Présentation
(2) Environnement
CPU PROCESSUS
(3) Environnement
Mémoire
11/02/18 OS II 28
Présentation
●
Ces deux caractéristiques sont totalement
indépendantes
– Dans les OS modernes elle agissent sur des entités
différentes.
●
La propriété de ses ressources → processus
●
Ordonnancement / exécution :→ threads
11/02/18 OS II 29
Le Multithreading
11/02/18 OS II 30
Le Multithreading
●
Le mot thread peut se traduire par « fil
d'exécution », c'est-à-dire un déroulement
particulier du code du programme qui se
produit parallèlement à d'autres entités en
cours de progression.
●
Les threads sont généralement présentés en
premier lieu comme des processus allégés
ne réclamant que peu de ressources pour
les changements de contexte.
11/02/18 OS II 31
Le Multithreading
●
Il faut ajouter à ceci un point important : les
différents threads d'une application
partagent un même espace d'adressage en
ce qui concerne leurs données.
●
La vision du programmeur est d'ailleurs
plus orientée sur ce dernier point que sur la
simplicité de commutation des tâches.
11/02/18 OS II 32
Le Multithreading
Monothread Multithread
11/02/18 OS II 33
Le Multithreading
●
En première analyse, on peut imaginer les threads comme des
processus partageant les mêmes données statiques et dynamiques.
11/02/18 OS II 34
Le Multithreading
●
Les threads ne sont intéressants que dans
les applications assurant plusieurs tâches en
parallèle.
●
Si chacune des opérations effectuées par un
logiciel doit attendre la fin d'une opération
précédente avant de pouvoir démarrer, il est
totalement inutile d'essayer une approche
multithread.
11/02/18 OS II 35
Définition
●
Un thread est l’unité de base de l'utilisation du CPU, il comporte
– Un identifiant de thread,
– Un program counter (ou compteur ordinal)
– Un ensemble de registres,
– et une pile.
●
Il partage avec les autres threads appartenant au même processus
– la section de code,
– la section de données,
– et d'autre ressources du système d'exploitation, telles que les fichiers ouverts et les
signaux.
●
Un processus traditionnel (poids lourd) a un seul thread.
– Si un processus a plusieurs threads, il peut effectuer plus d'une tâche à la fois.
11/02/18 OS II 36
Définition
11/02/18 OS II 37
Motivation
●
De nombreux logiciels qui s'exécutent sur
nos PC/MAC sont multi-threadé. Une
application est généralement mis en œuvre
comme un processus distinct avec plusieurs
threads de contrôle.
●
Un thread du navigateur Web peut avoir la
gestion de l’affichage alors qu'un autre
thread récupère les données du réseau.
11/02/18 OS II 38
Avantage
●
Réactivité: Rendre une application Multithreadé peut
permettre à une partie de continuer à fonctionner même si
une autre partie est bloqué ou effectue une opération longue
●
Partage des ressources: Les processus peuvent se
partager des ressources grâce à des techniques telles que la
mémoire partagée ou la transmission de messages. Ces
techniques doivent être explicitement implémenté par le
programmeur. Cependant, les threads partagent la mémoire
et les ressources du processus auxquels ils appartiennent
par défaut.
11/02/18 OS II 39
Avantage
●
Économie: Alloué de la mémoire et de ressources pour la
création des processus est coûteux. Vu que les threads
partagent les ressources du processus auxquels elle ils
appartiennent, il est plus économique de créer et d’
exécuter des commutations de contexte .
●
Scalabilité (passage à l’échelle): Les avantages du
multithreading peuvent être considérablement augmenté
dans une architecture multiprocesseur, où les threads
peuvent s'exécuter en parallèle sur des processeurs
différents
11/02/18 OS II 40
Le parallélisme
●
On distingue deux types de parallélisme:
– Task parallelism (le parallélisme par flot
d'instructions également nommé parallélisme de
traitement ou de contrôle) : plusieurs instructions
différentes sont exécutées simultanément
●
Machines MIMD (Multiple Instructions, Multiple Data).
●
Exemple : la somme des éléments d'un tableau de taille N
– Sur une machine single-core : un seul thread effectue la somme de
[0] à [N-1]
– Sur une machine dual-core : un thread A effectue la somme de [0] à
[N/2 -1] et un second thread B effectue la somme de [N/2] à [N-1].
11/02/18 OS II 42
Le parallélisme
●
Task parallelism
– Implique la distribution des tâches (threads) entre les différents cœurs.
– Chaque thread effectuant une tâche particulière
– Differents threads peuvent agir sur les mêmes données ou sur des
données différentes.
●
Exemple : statistique sur un tableau
– Thread A → Somme
– Thread B → Min
– Thread C → Max
– Thread D → Moyenne
11/02/18 OS II 43
Exemple de Programmation Multithreadé avec
Pthread
11/02/18 OS II 44
Rappel sur les pointeurs
●
le langage C permet de manipuler des adresses par
l'intermédiaire de variables nommées "pointeurs".
●
Considérons les instructions :
int * ad ;
int n ;
n = 20 ;
ad = &n ;
*ad = 30 ;
11/02/18 OS II 45
Rappel sur les pointeurs
int * ad ;
●
* est un opérateur qui désigne le contenu de
l'adresse qui le suit.
11/02/18 OS II 46
Rappel sur les pointeurs
ad = &n ;
20
11/02/18
ad OS II
n 47
Rappel sur les pointeurs
*ad = 30 ;
11/02/18
ad OS II
n 48
UTILISATION DE POINTEURS SUR
DES FONCTIONS
●
En C, comme dans la plupart des autres
langages, il n'est pas possible de placer le
nom d'une fonction dans une variable.
●
En revanche, on peut y définir une variable
destinée à "pointer sur une fonction", c'est-
à-dire à contenir son adresse.
11/02/18 OS II 49
Paramétrage d'appel de fonctions
●
Considérez cette déclaration :
int (* adf) (double, int) ;
●
Elle spécifie que :
– (* adf) est une fonction à deux arguments (de type double
et int) fournissant un résultat de type int,
●
donc que :
– adf est un pointeur sur une fonction à deux arguments
(double et int) fournissant un résultat de type int.
11/02/18 OS II 50
Paramétrage d'appel de fonctions
● Si, par exemple, fct1 et fct2 sont des fonctions
ayant les prototypes suivants :
int fct1 (double, int) ;
int fct2 (double, int) ;
●
les affectations suivantes ont alors un sens :
adf = fct1 ;
adf = fct2 ;
– Elles placent, dans adf, l'adresse de la fonction
correspondante (fct1 ou fct2).
11/02/18 OS II 51
Paramétrage d'appel de fonctions
●
Dans ces conditions, il devient possible de programmer un "appel
de fonction variable" (c'est-à-dire que la fonction appelée peut
varier au fil de l'exécution du programme) par une instruction telle
que :
(* adf) (5.35, 4) ;
●
Celle-ci, appelle la fonction dont l'adresse figure actuellement
dans adf, en lui transmettant les valeurs indiquées (5.35 et 4).
Suivant le cas, cette instruction sera donc équivalente à l'une des
deux suivantes :
fct1 (5.35, 4) ;
fct2 (5.35, 4) ;
11/02/18 OS II 52
Fonctions transmises en argument
●
Supposez que nous souhaitions écrire une fonction permettant
de calculer l'intégrale d'une fonction quelconque suivant une
méthode numérique donnée. Une telle fonction que nous
supposerons nommée integ posséderait alors un en-tête de ce
genre :
float integ ( float(*f)(float), ..... )
●
Le premier argument muet correspond ici à l'adresse de la
fonction dont on cherche à calculer l'intégrale. Sa déclaration
peut s'interpréter ainsi :
– (*f)(float) est de type float
– (*f) est donc une fonction recevant un argument de type float et fournissant
un résultat de type float,
11/02/18 OS II 53
Fonctions transmises en argument
●
f est donc un pointeur sur une fonction recevant un argument
de type float et fournissant un résultat de type float
●
Notez bien qu'il ne faut surtout pas écrire f(x), car f désigne
ici un pointeur contenant l'adresse d'une fonction, et non pas
directement l'adresse d'une fonction
11/02/18 OS II 54
Fonctions transmises en argument
● L'utilisation de la fonction integ ne présente pas de difficultés
particulières. Elle pourrait se présenter ainsi :
main()
{
float fct1(float), fct2(float) ;
...
res1 = integ (fct1, .....) ;
...
res2 = integ (fct2, .....) ;
...
}
11/02/18 OS II 55
Exemple 1 de pointeur sur fonction
11/02/18 OS II 56
Exemple 2 de pointeur sur fonction
11/02/18 OS II 57
Exemple 2 de pointeur sur fonction
11/02/18 OS II 58
Création de threads
●
Il existe des appels système qui permettent dans un contexte
multithreadé de créer un nouveau thread, d'attendre la fin de
son exécution, et de mettre fin au thread en cours.
11/02/18 OS II 59
Création de threads
●
On se disciplinera donc pour employer
systématiquement la fonction
pthread_equal( ) lorsqu'on voudra
comparer deux identifiants de threads.
– Int pthread_equal (pthread_t thread_1,
pthread_t thread_2);
●
Cette fonction renvoie une valeur non nulle
s'ils sont égaux.
11/02/18 OS II 60
Création de threads
●
Lors de la création d'un nouveau thread, on emploie la
fonction pthread_create( ).
– Celle-ci donne naissance à un nouveau fil d'exécution, qui va démarrer en
invoquant la routine dont on passe le nom en argument.
– Lorsque cette routine se termine, le thread est éliminé.
– Cette routine fonctionne donc un peu comme la fonction main( ) des
programmes C.
– Pour cette raison, le fil d'exécution original du processus est nommé
thread principal (main thread).
●
Le prototype de pthread_create( ) est le suivant :
– int pthread_create (pthread_t * thread, pthread_attr_t
* attributs, void * (* fonction) (void * argument),
void * argument);
11/02/18 OS II 61
Création de threads
11/02/18 OS II 62
Création de threads
●
Le premier argument est un pointeur qui sera initialisé par la
routine avec l'identifiant du nouveau thread.
●
Le second argument correspond aux attributs dont on désire
doter le nouveau thread.
●
Le troisième argument est un pointeur représentant la fonction
principale du nouveau thread.
– Celle-ci est invoquée dès la création du thread et reçoit en argument le
pointeur passé en dernière position dans pthread_create( ).
– Le type de l'argument étant void *, on pourra le transformer en n'importe
quel type de pointeur pour passer un argument au thread
11/02/18 OS II 63
Terminaison des threads
●
Lorsque la fonction principale d'un thread se termine, celui-ci
est éliminé.
●
Cette fonction doit renvoyer une valeur de type void * qui
pourra être récupérée dans un autre fil d'exécution.
●
Il est aussi possible d'invoquer la fonction
pthread_exit( ), qui met fin au thread appelant tout en
renvoyant le pointeur void * passé en argument.
●
On ne doit naturellement pas invoquer exit( ), qui mettrait fin
à toute l'application et pas uniquement au thread appelant.
– void pthread_exit (void * retour);
11/02/18 OS II 64
Terminaison des threads
11/02/18 OS II 65
Suspension de l’exécution des threads
●
Pour récupérer la valeur de retour d'un thread terminé,
on utilise la fonction pthread_join( )
●
Celle-ci suspend l'exécution du thread appelant jusqu'à
la terminaison du thread indiqué en argument.
●
Elle remplit alors le pointeur passé en seconde position
avec la valeur de retour du thread fini.
– int pthread_join (pthread_t thread, void **
retour);
11/02/18 OS II 66
Suspension de l’exécution des threads
11/02/18 OS II 67
Obtenir l’identité d’un thread
11/02/18 OS II 68
Recap'
●
Création de threads
int pthread_create (pthread_t
*thread , pthread_attr_t *attr,
void *(*nomfonction), void *arg );
●
Le service pthread_create() crée un thread qui
exécute la fonction nomfonction avec
l’argument arg et les attributs attr.
– Les attributs permettent de spécifier la taille de la
pile, la priorité, la politique de planification, etc. Il y
a plusieurs formes de modification des attributs.
11/02/18 OS II 69
Recap'
●
Suspension de threads
int pthread_join(pthread_t thid,
void **valeur_de_retour);
●
pthread_join() suspend l’exécution d’un thread
jusqu’à ce que termine le thread avec
l’identificateur thid. Il retourne l’état de
terminaison du thread.
11/02/18 OS II 70
Recap'
●
Terminaison de threads
void pthread_exit(void
*valeur_de_retour);
●
pthread_exit() permet à un thread de terminer
son exécution, en retournant l’état de
terminaison
11/02/18 OS II 71
EXEMPLE1 DE CRÉATION DE
THREADS
●
Makefile
EXEC = exemple-pthread-create-1
CFLAGS = -O
LIBS = -lpthread
CC = gcc
all: exemple-pthread-create-1
exemple-pthread-create-1: exemple-pthread-create-1.o
$(CC) -o exemple-pthread-create-1 exemple-pthread-create-1.o $(LIBS)
exemple-pthread-create-1.o: exemple-pthread-create-1.c
$(CC) $(CFLAGS) -c exemple-pthread-create-1.c
11/02/18 OS II 72
EXEMPLE1 DE CRÉATION DE THREADS
11/02/18 OS II 73
EXEMPLE1 DE CRÉATION DE THREADS
11/02/18 OS II 74
Exemple1 PID du thread
11/02/18 OS II 75
Exemple1 PID du thread
11/02/18 OS II 76
Exemple2 PID du thread
11/02/18 OS II 77
Exemple2 PID du thread
11/02/18 OS II 78
Variables globales dans les threads
11/02/18 OS II 79
Variables globales dans les threads
11/02/18 OS II 80
Variables globales dans les threads
11/02/18 OS II 81
Variables globales dans les threads
●
Le même code en
commentant les sleep
et le pthread_join
● → PROBLÉME
D’ACCÈS
CONCURRENT ET DE
SYNCHRONISATION
11/02/18 OS II 82
Passage de paramètre entre des threads et une
fonction main (int)
int i = 42;
pthread_create(..., myfunc, (void *)&i);
.
.
.
void *myfunc(void *vptr_value) {
int value = *((int *)vptr_value);
.
.
.
}
11/02/18 OS II 83
Passage de paramètre entre des threads et une
fonction main (C-string)
char *str = "ESEN";
pthread_create(..., my_func, (void *)str);
.
.
.
11/02/18 OS II 84
Passage de paramètre entre des threads et une
fonction main (array)
Int tab[10];
pthread_create(..., my_func, (void *)tab);
.
.
.
11/02/18 OS II 85
EXEMPLE 2 DE CRÉATION DE THREADS
11/02/18 OS II 86
EXEMPLE 2 DE CRÉATION DE THREADS
11/02/18 OS II 87
EXEMPLE 3 DE CRÉATION DE THREADS
11/02/18 OS II 88
EXEMPLE 3 DE CRÉATION DE THREADS
11/02/18 OS II 89
EXEMPLE 3 DE CRÉATION DE THREADS
11/02/18 OS II 90
Passage d'une structure de donnée
11/02/18 OS II 91
Passage d'une structure de donnée
11/02/18 OS II 92
Passage d'une structure de donnée
11/02/18 OS II 93
EXEMPLE 4 DE CRÉATION DE THREADS
11/02/18 OS II 94
EXEMPLE 4 DE CRÉATION DE THREADS
11/02/18 OS II 95
EXEMPLE 4 DE CRÉATION DE THREADS
●
Cette application est très mal conçue car les
différents threads modifient la même variable
globale sans se préoccuper les uns des autres.
●
Et c'est justement l'essence même de la
programmation multithread d'éviter ce genre de
situation
11/02/18 OS II 96
Création de threads
●
Le programme suivant n'utilise qu'un seul thread
autre que le fil d'exécution principal ; il s'agit
simplement de vérifier le comportement des
fonctions pthread_join( ) et pthread_exit( ).
– pthread_join: attend la fin d’un thread
– pthread_exit: termine le thread appeleant
●
Nous sous-traitons la lecture d'une valeur au clavier
dans un fil d'exécution secondaire. Le fil principal
pourrait en profiter pour réaliser d'autres opérations.
11/02/18 OS II 97
11/02/18 OS II 98
Création de threads
11/02/18 OS II 99
The END
11/02/18 OS II 100