Chapter2 1
Chapter2 1
Plan
Complément en c
Concepts fondamentaux
Création des processus
Les tubes
Les signaux
2
Un premier programme en C
/* Un programme qui affiche bonjour. */
#include <stdio.h> //standard input/output library, ou stdio
int main()
{ printf("Bonjour.\n");
return 0; //termine l’exécution du main et retourne un résultat de 0 }
Variables
o Toute variable a un type, qui spécifie la taille et l’interprétation de la mémoire
associée à la variable
#include <stdio.h>
int main()
{ int i; i = 1;
printf("La variable i vaut %d.\n", i);
i = 2;
printf("La variable i vaut maintenant %d.\n", i);
i = i + 1;
printf("La variable i vaut enfin %d.\n", i);
return 0;
}
Sortie formatée
o L’instruction printf permet de formater et d’écrire des données sur la sortie
standard
o printf("Le carré de %d est %d.\n", i, i * i);
Entrées
o L’instruction scanf permet de lire une valeur à partir de l’entrée standard
#include <stdio.h>
int main()
{
int i;
printf("Entrez un nombre: ");
scanf("%d", &i);
printf("Vous avez entré %d dont le carré est %d.\n", i, i * i);
return 0;
}
4
Conditionnelles simples
o La conditionnelle if est une structure de contrôle. Elle consiste du mot clé if
suivi d’une condition entre parenthèses et de deux branches séparées par le
mot clé else. Si la condition est vraie, c’est la première branche qui est
exécutée ; sinon, c’est la deuxième.
#include <stdio.h>
int main()
{
int i;
printf("Entrez un nombre: ");
scanf("%d", &i);
if(i <= 5) {
printf("Inférieur ou égal à 5.\n");
} else {
printf("Pas inférieur ou égal à 5.\n");
}
return 0;
}
Conditionnelles imbriquées
o Une conditionnelle peut aussi apparaître au sein d’une des deux branches
d’une autre conditionnelle.
#include <stdio.h>
int main()
{
int i;
printf("Entrez un nombre: ");
scanf("%d", &i);
if(i <= 5) {
printf("Inférieur ou égal à 5.\n");
} else {
printf("Pas inférieur ou égal à 5.\n");
}
return 0;
}
6
Boucles définies
o Une boucle est une structure de contrôle qui sert à exécuter le même bloc de
code de multiples fois
o Une boucle définie, ou boucle for, est une boucle dont l’exécution est
contrôlée par un compteur de boucle dont la valeur varie entre deux valeurs
connues avant d’entrer dans la boucle
o for(e1 ; e2 ; e3 ) bloc
• l’expression e1, dite initialisation, est exécutée ;
• le test e2 est évalué; s’il est faux, on sort de la boucle, et l’exécution de la
boucle est terminée ;
• le corps de la boucle est exécuté ;
• l’expression e3 est exécutée ;
• on recommence à l’étape 2.
int main()
{ int i;
for(i = 1; i <= 10; i = i + 1)
{ printf("J'ai collé %d timbres.\n", i);
printf("Il m'en reste %d.\n", 10 - i);
}
}
Quelques abréviations
o l’expression i++ est équivalente à i = i + 1 ;
o l’expression i-- est équivalente à i = i - 1 ;
o l’expression i += c est équivalente à i = i + c ;
o l’expression i -= c est équivalente à i = i - c.
Terminaison prématurée à l’aide de return
o Il est parfois nécessaire d’interrompre l’exécution d’une boucle de façon prématurée,
#include<stdio.h>
int main()
{ int i; double x, somme;
somme = 0.0;
for(i = 0; i < 4; i = i + 1) {
scanf("%lf", &x);
if(x > -1.0E10 && x < 1.0E-10) {
printf("Division par zéro !\n"); return 1; //on utilise aussi Break
}
somme = somme + 1.0 / x;
}
printf("La somme des inverses est %lf.\n", somme);
return 0;
}
8
Les directives
o Figurent sur les lignes commençant par #
#include <stdio.h>
#define MAXTAB 5
int min(int tab[],int nb)
{
int i, min=tab[0];
for (i=1; i<nb; i++)
if (tab[i] < min) min = tab[i];
return min;
}
int main()
{
int tab[MAXTAB] = { 106, 20, 34, 4, 15};
printf("Le minimum est : %d\n", min(tab,MAXTAB));
}
10
Les structures
o L’accès aux champs d’une structure s’effectue directement pas l’opérateur
« . » : var1.a1 pour accéder au champ a1 de la variable var1
11
12
Pointeurs
o un pointeur est un couple (adresse en mémoire, type de donnée)
o exemple : un pointeur sur un entier est donc l’adresse d’un entier dans la
mémoire
o déclaration d’une variable de type pointeur : type_pointé *ptr ; où ptr est une
variable qui contient l’adresse en mémoire d’un objet du type_pointé
o on acède à la valeur de l’objet pointé par ptr en utilisant l’opérateur
d’indirection * (*ptr)
o l’opérateur de prise d’adresse & permet d’accéder à l’adresse d’un objet
13
14
Les arguments de la ligne de commande: syntaxe
o On peut écrire de nouvelles commandes qui peuvent être appelées avec des
paramètres
o La fonction main() s’écrit de la manière suivante :
15
16
Concepts fondamentaux
17
Processus Linux/Unix
o Un processus est une instance d'un programme en train de s’exécuter, une
tâche.
o Il possède un numéro unique sur le système pid
o Chaque processus appartient à un utilisateur et un groupe et à les droits qui
leur sont associés
o Sous shell, un processus est créé pour exécuter chacune des commandes
o Le shell est le processus père de toutes les commandes.
18
Le multitâche sous Unix/Linux
o Unix est un système multitâches: il peut exécuter plusieurs progs à la fois
o Le shell crée un nouveau processus pour exécuter chaque commande
o Différence entre processus et programme :
• le programme est une description statique
• le processus est une activité dynamique (il a un début, un déroulement et
une fin, il a un état qui évolue au cours du temps)
o Par exemple, l’exécution d’un programme et la copie d’un fichier sur disque
Exemple
o xclock: lancement d’un processus en 1ier plan (foreground )
o ctl+c: l’arrêt définitif d un processus
o xclock&: lancement d’un processus en 2ieme plan (background )
o ^z: un signal qui suspend l'exécution sans détruire le processus correspondant
o bg: pour afficher les processus en BG
o fg: pour afficher les processus en FG
19
20
o Exemple
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
printf("processus %d, groupe %d\n", getpid(), getpgrp());
while(1) ;
}
21
o Exemple
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
printf("processus %d, groupe %d\n", getpid(), getpgrp());
while(1) ;
}
22
23
La commande ps:
o PID (process identificator) : c'est le numéro du processus.
o TT : indique le terminal dans lequel a été lancé le processus. Un point
d'interrogation signifie que le processus n'est attaché à aucun terminal (par
exemple les démons).
o STAT : indique l'état du processus :
• R : actif ( running)
• S : non activé depuis moins de 20 secondes (sleeping)
• I : non activé depuis plus de 20 secondes (idle)
• T : arrêté (suspendu)
• Z : zombie
o TIME : indique le temps machine utilisé par le programme (et non pas le
temps depuis lequel le processus a été lancé !).
24
La commande ps: options
o a (all) : donne la liste de tous les processus, y compris ceux dont vous n'êtes
pas propriétaire.
o g (global, général...) : donne la liste de tous les processus dont vous êtes
propriétaire.
o u (user, utilisateur) : donne davantage d'informations (nom du propriétaire,
heure de lancement, pourcentage de mémoire occupée par le processus, etc.).
o x : affiche aussi les processus qui ne sont pas associés à un terminal.
o w : le tronque pas à 80 caractères (peut être utilisée plusieurs fois pour
tronquer plus loin)
o agux : est en fait souvent utilisé pour avoir des informations sur tout les
processus.
Commande top
o affiche les mêmes informations, mais de façon dynamique : elle indique en
fait par ordre décroissant le temps machine des processus, les plus
gourmands en premier.
25
26
Autres commandes
o ps : liste des processus et de leurs caractéristiques
o htop : liste dynamique des processus et de ce qu'ils consomment
o pgrep : récupération d'une liste de processus par expression régulière
o pidof : récupération du pid d'un processus recherché
o fuser : informations sur les file descriptor d'un processus
o lsof : idem
o pmap : afficher le mapping mémoire d'un processus
o strace : liste les appels système du processus
o ltrace : liste les appels de fonction de bibliothèques dynamiques du processus
o pstack : affiche la pile d'appel du processus
o gdb : pour tout savoir et même modifier l'action d'un processus.
o kill : envoyer un signal à un processus connaissant son pid
o killall : envoie un signal à tous les processus portant un certain nom
o pkill : envoie un signal aux processus matchant une expression régulière
o ctrl-z : envoie le signal STOP au processus en avant plan du shell en cours
o fg, bg : envoie le signal CONT à un processus stoppé du shell en cours
27
28
Soit ex un fichier de commandes exécutable.
1er cas : on tape $ ex, voici ce qui se passe :
1. le shell lit la commande ex
2. il se duplique au moyen de la fonction fork ; il existe alors un shell père et un
shell fils
3. grâce à la fonction exec, le shell fils recouvre son segment de texte par celui
de ex qui s'exécute.
4. le shell père récupère le pid du fils retourné par fork ()
5. à la fin de l'exécution de ex, le shell père reprend son exécution.
La fonction wait lui permet de connaître son achèvement : wait (&etat) retourne le
pid du processus fils à son achèvement (etat : entier).
29
2ème cas : on tape ex&, mais n'accède pas à l'entrée standard réservée au shell),
voici ce qui se passe :
o 1. à 4. comme ci-dessus
o 5. le shell père reçoit le pid du fils, émet un prompt, puis reprend son activité
sans attendre la fin du fils
30
La norme Posix (Portable Operating System Interface) définit un nombre
relativement petit d'appels système pour la gestion de processus :
o pid_t fork() : Création de processus fils.
o int execl(), int execlp(), int execvp(), int execle(), int execv() : Les services
exec() permettent à un processus d'exécuter un programme (code) différent.
31
int main( )
{ int return_value ;
/* retourne 127 si le shell ne peut pas s'exécuter, retourne -1 en cas d'erreur, autrement retourne
le code de la commande */
return_value = system("ls -l") ; return return_value ;
}
32
On peut lancer un programme à l’intérieur d’un autre programme et ainsi créer un
nouveau processus en utilisant la bibliothèque system.
#include <stdlib.h>
Int system (const char *string)
#include <stdio.h>
#include <stdlib.h>
int main ()
{
printf ( "executer ps avec system\n") ;
system ("ps ax");
printf ("c'est fait\n");
exit(0);
}
33
34
La primitive Fork()
35
Identifiant de processus
o Chaque processus possède un identifiant, son pid
o La fonction getpid retourne le pid du processus actif
o La fonction getppid retourne le pid du processus père
36
Création d’un processus
o Après l'appel système fork(), la valeur de pid reçoit la valeur 0 dans le
processus fils mais elle est égale à l'identifiant du processus fils dans le
processus père
o Le processus créé (fils) est un clone (copie conforme) du processus créateur
(père). Le père et le fils ne se distinguent que par le résultat rendu par fork()
• pour le père : le numéro du fils (ou –1 si création impossible), pour le fils
:0
37
38
Exemple
#include<stdio.h>
#include<sys/times.h>
Int main()
{
int pid;
Char quisuisje=‘’le pere’’;
Pid=fork();
If (pid==0)
{ Quisuisje=‘’le fils’’;
Printf(‘’ je suis le %s ’’, quisuisje );
}
else
{
Printf(‘’ je suis le %s ’’, quisuisje );
Wait(NULL);
}
Return 0;
}
39
Création de processus
40
Création de processus
41
Création de processus
42
Création de processus
43
Création de processus
44
Création de processus
45
46
Création d’un processus: 1 programme, 2 processus, donc 2 mémoires virtuelles, 2
jeux de données
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main ()
{ int i ;
if (fork() != 0) {
printf("je suis le père, mon PID est %d\n", getpid());
i = 3;
} else {
printf("je suis le fils, mon PID est %d\n", getpid());
i = 5;
}
printf("pour %d, i = %d\n", getpid(), i);
}
47
48
Création d’un processus
49
50
Le système Linux repose sur ce concept arborescent
51
Un processus père peut attendre la fin d’un ou plusieurs fils en utilisant wait() ou
waitpid(). Tant que son père n’a pas pris connaissance de sa terminaison par l’une
de ces primitives, un processus terminé reste dans un état dit zombi.
• Un processus zombi ne peut plus s’exécuter, mais consomme encore des
ressources. Il faut éviter de conserver des processus dans cet état.
52
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main ()
{
if (fork() != 0) {
printf("je suis le père, mon PID est %d\n", getpid());
while (1) ; /* boucle sans fin sans attendre le fils */
} else {
printf("je suis le fils, mon PID est %d\n", getpid());
sleep(2) /* blocage pendant 10 seconds*/;
printf("fin du fils\n");
exit(0);
}
}
53
Zombie
54
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main ()
{ pid_t fils; int statut;
if (fork() != 0) {
printf("je suis le père, mon PID est %d\n", getpid());
fils = wait(&statut);
if (WIFEXITED(statut)) {
printf("%d : mon fils %d s'est terminé avec le code %d\n", getpid(), fils,
WEXITSTATUS(statut)); }
exit(0);
} else {
printf("je suis le fils, mon PID est %d\n", getpid());
sleep(2) /* blocage pendant 10 seconds*/;
printf("fin du fils\n");
exit(1);
}
}
55
56
La primitive exec :
o sert à faire exécuter un nouveau programme par un processus
o elle est souvent utilisée immédiatement après la création d’un processus
o son effet est de “recouvrir” la mémoire virtuelle du processus par le nouveau
programme et de lancer celui-ci en lui passant des paramètres spécifiés dans la
commande.
Diverses variantes d’exec existent selon le mode de passage des paramètres
(tableau, liste, passage de variables d’environnement).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main ()
{
if (fork() == 0) { execl("bin/ls", "ls", "-a", NULL); }
else {wait(NULL);}
exit(0);
}
57
Exemple 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{ pid_t v;
v=fork();
if(v==0) printf("Je suis le fils avec pid %d\n" , getpid () ) ;
else if (v > 0)
printf ("Je suis le pere avec pid %d\n" , getpid () ) ;
else
printf ("Erreur dans la creation du fils \n" ) ;
}
58
Exemple 2
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
59
Exemple 2
o Après l'exécution de « exemple2.c» on obtient le résultat suivant
60
Exemple 2
o Pour faire perdre du temps au processus on ajoute les deux lignes:
for ( j = 1 ; j <100000 ; j ++)
for ( k = 1 ; k <100000 ; k++) ;
61
62
Exemple 3
o Deux exécutions du programme montrent que les processus père et fils sont
concurrents :
station > cc exemple3.cc exemple3
station > ./exmple3
ici processus pere, le pid 12339.
ici processus fils, le pid 12340.
Fin du Process 12340 avec a = 30.
Fin du Process 12339 avec a = 120.
63
int main ( )
{ int i , n=5; pid_t pid ;
for ( i = 1 ; i <n ; i ++)
{ if ( ( pid=fork ( ) ) == -1) break ;
if (pid == 0 )
printf (" Processus %d avec pere %d , i=%d\n" , getpid ( ) , getppid ( ) , i ) ;
}
return 0;
}
64
Exemple 4
65
Exemple 4
66
Exemple 4
o En supposant que le shell a toujours un pid de 759, et que le processus associé
à fork a un pid de 874, on devrait obtenir l'arbre suivante:
67
Exemple 4
o Malheureusement, ce ne sera pas le cas, puisque encore une fois des
processus pères meurent avant que leur fils ne puissent afficher leurs
messages :
68
void exit (int etat)
o La fonction provoque la terminaison du processus avec le code de retour etat
(0 = bonne fin). Si le père est un shell, il récupère etat dans la variable $?
o Si le père est en attente sur wait, il est réveillé et reçoit le code de retour du
fils.
o Il faut souligner qu'un processus peut se terminer aussi par un arrêt forcé
provoqué par un autre processus avec l'envoi d'un signal du type kill().
69
70
Appel système: pid =wait (status)
o pid est l'identifiant du processus fils et status est l'adresse dans l'espace
utilisateur d'un entier qui contiendra le status de exit() du processus fils.
o Ces appels système permettent au processus père d'attendre la fin d'un de ses
processus fils et de récupérer son status de fin.
o Ainsi, un processus peut synchroniser son exécution avec la fin de son
processus fils en exécutant l'appel système wait().
#include <sys/wait.h>
int wait (int *status);
int waitpid(int pid, int *status, int options);
71
Le processus appelant est mis en attente jusqu'à ce que l'un de ses fils termine.
Quand cela se produit, il revient de la fonction. Si status est différent de 0, alors 16
bits d'information sont rangés dans les 16 bits de poids faible de l'entier pointé par
status.
Ces informations permettent de savoir comment s'est terminé le processus selon les
conventions suivantes :
o Si le fils est stoppé, les 8 bits de poids fort contiennent le numéro du signal
qui a arrêté le processus et les 8 bits de poids faible ont la valeur octale 0177.
o Si le fils s'est terminé avec un exit(), les 8 bits de poids faible de status sont
nuls et les 8 bits de poids fort contiennent les 8 bits de poids faible du
paramètre utilisé par le processus fils lors de l'appel de exit().
o Si le fils s'est terminé sur la réception d'un signal, les 8 bits de poids fort de
status sont nuls et les 7 bits de poids faible contiennent le numéro du signal
qui a causé la fin du processus.
72
Exemple 5
int main()
{
pid_t v;
v=fork();
if(v==0)
printf("Je suis le fils avec pid %d\n" , getpid () ) ;
else if (v > 0) {
printf("Je suis le pere avec pid %d\n" , getpid () ) ;
printf("J'attends que mon fils se termine\n" ) ;
wait(NULL) ;
}
else
printf ("Erreur dans la creation du fils \n" ) ;
exit(0);
}
73
Exemple 6
int main ( )
{ int i , n=5; pid_t pid ;
for ( i = 1 ; i <n ; i ++)
{ if ( ( pid=fork ( ) ) == -1) break ;
if (pid == 0 ) printf (" Processus %d avec pere %d , i=%d\n" , getpid ( ) , getppid ( ) , i ) ;
}
// attendre la fin des fils
while (wait (NULL) >= 0 ) ;
return 0;
}
74
Le mécanisme exit+wait permet
o au processus fils de retourner une information codée sur 8 bits au processus
père
o au processus père d’attendre la terminaison du fils
75
Les tubes
76
Définition d’un tube
o moyen de transmettre un flot d'octets entre des processus
77
78
Exemple d’un tube
o Un tube est un flux de données permettant l'échange unidirectionnel de
données entre deux processus s'exécutant sur une même machine
79
80
Création d’un tube: syntaxe
81
Lecture : syntaxe
o lit count octets depuis le descripteur fd et les range dans le buffer pointé par
buf
o renvoie le nb d’octets effectivement lus (0 en fin de fichier) et avance la tête
de lecture de ce nombre
o renvoie -1 en cas d’échec
82
Lecture : fonctionnement
o Si le nb d’écrivains est nul alors la fonction retourne 0
o Si la lecture est bloquante (par défaut) et que le tube est vide, le processus est
mis en attente jusqu’à ce qu’une écriture se produise dans le tube
o L’indicateur O_NONBLOCK peut etre utilisé pour rendre la lecture non
bloquante (dans ce cas -1 est renvoyé si le tube est vide)
o Si l’indicateur O_NDELAY est positionné et que le tube est vide, alors la
fonction retourne 0
Ecriture : syntaxe
o écrit count octets dans le tube désigné par le descripteur fd depuis le buffer
pointé par buf
o renvoie le nombre d’octets effectivement emis
o retourne 0 si aucune écriture n’est réalisée
o renvoie -1 en cas d´échec
83
Ecriture: fonctionnement
o Si le nombre de lecteurs est nul, un signal est envoyé au processus écrivain
qui se termine
o Si l’écriture est bloquante et que le tube est plein, le processus est bloqué en
attendant qu’il se vide
o Si l’écriture est non bloquante, le processus écrit les caractères qu’il peut
écrire (maximum PIPE_BUF) et retourne une valeur correspondante
Fermeture
o La primitive close() doit être utilisée sur le descripteur qu’on désire fermer
• close(filedesc[0]) ferme le tube en lecture
• close(filedesc[1]) ferme le tube en écriture
o Une fois fermé, on ne peut plus récupérer le descripteur
84
Fonctionnement de la procédure écriture-lecture
o Le processus père crée un tube de communication sans nom en utilisant l'appel
système pipe()
o Le processus père crée un ou plusieurs fils en utilisant l'appel système fork()
o Le processus écrivain ferme l'accès en lecture du tube
o De même, le processus lecteur ferme l'accès en écriture du tube
o Les processus communiquent en utilisant les appels système write() et read()
o Chaque processus ferme son accès au tube lorsqu'il veut mettre fin à la
communication via le tube
85
86
Père parle au fils
o le père ferme fd[0] et écrit sur fd[1]
o le fils ferme fd[1] et lit depuis fd[0]
#include<sys/types.h>
#include<unistd.h>
#include <stdio.h>
int main() {
const int Nbuff=1000; char buff[Nbuff]; int pF ,
dFic[2];
pipe(dFic);
if ((pF = fork()) > 0) { // pere
close(dFic[0]); write(dFic[1],"Salut",5);
}
else if (pF == 0) { // fils
close(dFic[1]); int n = read(dFic[0] , buff, Nbuff-1);
buff[n] = '\0'; printf("buffer=%s\n",buff);
}
return 0;
}
87
int main() {
const int Nbuff=1000; char buff[Nbuff]; int pF ,
dFic[2];
pipe(dFic);
if ((pF = fork()) > 0) { // pere
close(dFic[1]); int n = read(dFic[0] , buff, Nbuff-1);
buff[n] = '\0'; printf("buffer=%s\n",buff);
}
else if (pF == 0) { // fils
close(dFic[0]); write(dFic[1],"Salut",5);
}
return 0;
}
88
Exemple: le processus père crée un tube de communication pour communiquer
avec son
#define R 0 processus fils.
#define W 1
int main()
{ int fd[2]; char message [100]; // pour recup. un msg
int nboctets ; char* phrase = "message envoye au pere par le fils ";
pipe(fd); // creation d' un tube sans nom
if (fork()==0) // création d' un processus fils
{ close (fd[R]) ; // Le fils ferme le descripteur non utilise de lecture
write (fd[W], phrase, strlen(phrase) + 1 ) ; // depot dans le tube du message
close (fd[W]) ; // fermeture du descripteur d ' ecriture
}
else
{ close(fd[W]) ; // Le pere ferme le descripteur non utilise d' écriture
// extraction du message du tube
nboctets = read(fd[R], message, 100);
printf ( "Lecture %d octets : %s\n", nboctets, message);
close (fd[R]) ; // fermeture du descripteur de lecture
}
return 0 ;
}
89
Exercice
o On veut créer deux processus qui échangent des entiers de la manière suivante
o Le père crée un tube
o Le père crée un fils
o Le fils lit une suite d’entiers au clavier terminée par Ctrl-D
o Il en fait la somme
o Il l’écrit dans le tube au père
o Le père lit la somme dans le tube puis l’affiche
90
On souhaite maintenant que le fils envoie tous les entiers lus au père, c’est le père
qui est chargé de faire la somme avant de l’afficher
91
92
Comment créer un pipe entre deux processus fils: ls –al | tr a-z A-Z. Donner le code
des fonctions sunsource() et rundest()
93
94
Modifier le programme du ring pour mettre en ouvre la commande suivante:
ls -al / | tr a-z A-Z
95
96
97
Les signaux
98
Un signal est l’équivalent logiciel des interruptions matérielles
Technique habituelle : frappe de touches particulières (Ctrl-C, DEL ...) qui envoie
un signal au processus éditeur ; ce dernier récupère le signal et interrompt le
chargement
Les signaux sont identifiés par des nombres entiers : 1 ... NSIG
99
100
101
102
Rappel:
o 2 façons d'envoyer un signal à un processus :
• En ligne de commande :
• Un caractère de contrôle :
103
104
Exemple 1
#include <unistd.h>
#include <stdio.h>
#include<signal.h>
//#include <stdlib.h>
#include <sys/wait.h>
int main() {
int pid,statut;
if ((pid=fork())==0)
while(1) sleep(1);
else {
sleep(10); statut = kill(pid,0);
if (statut == -1) printf("Fils %d inexistant \n",pid);
else {
printf("Signal SIGKILL envoye a %d\n",pid);
kill(pid,SIGKILL);
pid = waitpid(pid,&statut,WUNTRACED);
printf("Le fils %d s'est termine\n",pid);
}
}
}
105
o Cet appel système sert a modifier l’action effectuée à la réception d’un signal
o La fonction retourne 0 normalement, -1 en cas de problème
o signum désigne le signal concerné
o newact est le nouveau comportement
o oldact permet de sauvegarder l’ancien comportement
106
La structure de comportement sigaction
o sa_handler indique l’action a effectuer (SIG DFL par défaut, SIG IGN pour
ignorer ou un pointeur vers une fonction définissant le comportement)
o sa_mask fournit un masque de signaux a bloquer
o sa_flags spécifie un ensemble d’attributs qui modifie le comportement du
gestionnaire de signaux
107
Exemple 2
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int cpt=0;
void comportement(int sig) {
if (sig == SIGUSR1) cpt ++;
else if (sig == SIGINT) {
printf ("nombre signaux recus : %d\n",cpt+1);
exit(0);
}
}
int main() {
struct sigaction action;
action.sa_handler=comportement;
sigaction(SIGUSR1,&action,NULL);
sigaction(SIGINT,&action,NULL);
while (1);
}
108
Exemple 2
• Terminal1
• Terminal 2
109
Exemple 3
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
• Terminal1: ./Ex3
Salut
Input: salut
• Terminal 2: kill -SIGKILL npid
110
Introduction aux systèmes et aux réseaux (S. Krakowiak, Grenoble), Source de
nombreux transparents présentés ici.
http://sardes.inrialpes.fr/~krakowia/Enseignement/L3/SR-L3.html
Cours du Mr J. Chroboczek, 2013
Cours de Y. PAGNOTTE, Systèmes d'exploitation et programmation système
Luigi Logrippo, Ordonnancement Processus, slides. http://w3.uqo.ca/luigi/
http://perso.univ-rennes1.fr/pascal.gentil/docs/unix/unix.fichiers.html#cat1
http://upsilon.cc/~zack/teaching/1314/progsyst/#index1h2
Karim Sehaba, Systèmes et Architectures, http://perso.univ-lr.fr/ksehaba/
Vincent Granet, Introduction à Linux, Polytech’Nice-Sophia
Sylvain CHERRIER, Cours Linux,
A. Queudet, Cours Systèmes d'exploitation, Univ. Nantes
C. F Zucke, cours Systèmes d'exploitation
Gestion des processus, Telecom-ParisTech BCI Informatique
111