Communication par Signal - premiers pas



Documents pareils
Cours Programmation Système

Programmation système en C/C++

Cours 6 : Tubes anonymes et nommés

Introduction aux Systèmes et aux Réseaux

LEs processus coopèrent souvent pour traiter un même problème. Ces

Qu'est-ce qu'un processus: Définitions

3IS - Système d'exploitation linux - Programmation système

Exécutif temps réel Pierre-Yves Duval (cppm)

Introduction au langage C

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Les processus 2/54. Qu est-ce qu un processus? 3(6)/54. Se souvenir 1(1)/54. Le système de fichiers (exemple du disque dur)

Cours de S.E. les Signaux

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

Programmation système de commandes en C

Communication Interprocessus

Les processus. Système L3, /39

ENSP Strasbourg (Edition ) Les Systèmes Temps Réels - Ch. DOIGNON. Chapitre 3. Mise en œuvre : signaux, gestion du temps et multi-activités

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Les processus légers : threads. Système L3, /31

Le prototype de la fonction main()

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

COMPARAISONDESLANGAGESC, C++, JAVA ET

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Le traitement du temps

TRAVAUX PRATIQUES Programmation Système Langage C / Système UNIX. 2 e année Génie Informatique

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Programmation système I Les entrées/sorties

Un ordonnanceur stupide

OS Réseaux et Programmation Système - C5

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Java Licence Professionnelle CISII,

Playing with ptrace() for fun and profit

Les structures. Chapitre 3


École Polytechnique de Montréal. Département de Génie Informatique et Génie Logiciel. Cours INF2610. Contrôle périodique.

DUT Informatique Module Système S4 C Département Informatique 2009 / Travaux Pratiques n o 5 : Sockets Stream

J2SE Threads, 1ère partie Principe Cycle de vie Création Synchronisation

Unix : Programmation Système

Java Licence Professionnelle CISII,

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

Cours de Systèmes d Exploitation

Chapitre 4 : Outils de communication centralisés entre processus

Programmation système

Introduction à la programmation concurrente

Programmer en JAVA. par Tama

Synchro et Threads Java TM

Introduction à la Programmation Parallèle: MPI

1 Mesure de la performance d un système temps réel : la gigue

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Arguments d un programme

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Gestion des processus

Chapitre 2. Les processus. 2.1 Introduction. 2.2 les différents états d un processus

Conventions d écriture et outils de mise au point

Les structures de données. Rajae El Ouazzani

MISE A NIVEAU INFORMATIQUE LANGAGE C - EXEMPLES DE PROGRAMMES. Université Paris Dauphine IUP Génie Mathématique et Informatique 2 ème année

Programmation Système (en C sous linux) Rémy Malgouyres LIMOS UMR 6158, IUT département info Université Clermont 1, B.P.

Premiers Pas en Programmation Objet : les Classes et les Objets

Notions fondamentales du langage C# Version 1.0

Plan global. Programmation système II. Socket du domaine UNIX. Plan. Socket UNIX, Terminaux, Async IO, Mémoire, ELF.

Plan du cours. Historique du langage Nouveautés de Java 7

Rapport de fin de stage

as Architecture des Systèmes d Information

Bases de programmation. Cours 5. Structurer les données

Programmation client-serveur sockets - RPC

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

DNS Server RPC Interface buffer overflow. Céline COLLUMEAU Nicolas BODIN

Programmation C++ (débutant)/instructions for, while et do...while

TD3: tableaux avancées, première classe et chaînes

Problèmes liés à la concurrence

Archivage Messagerie Evolution pour usage HTML en utilisant Hypermail

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Exercice sur les Dockers

Programmation C. Apprendre à développer des programmes simples dans le langage C

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Simulation d un système de paiement par carte bancaire

REALISATION d'un. ORDONNANCEUR à ECHEANCES

Corrigés des premiers exercices sur les classes

Méthodes de programmation systèmes UE n NSY103. Notes de cours. Nombre d'heures : 55h (~ cours de 3 heures)

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Programmation Objet Java Correction

On appelle variable condition une var qui peut être testée et

Info0604 Programmation multi-threadée. Cours 5. Programmation multi-threadée en Java

INFO-F-105 Language de programmation I Séance VI

Introduction : les processus. Introduction : les threads. Plan

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Utilisation d objets : String et ArrayList

Programmation Classique en langage C

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

INTRODUCTION À LA PROGRAMMATION CONCURRENTE

Architecture d un système d exploitation

IV- Comment fonctionne un ordinateur?

Architecture des ordinateurs

Programmation en Java IUT GEII (MC-II1) 1

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Chapitre 4 : Exclusion mutuelle

Temps Réel. Jérôme Pouiller Septembre 2011

Transcription:

Communication par Signal - premiers pas Quelques remarques sur la gestion des signaux UNIX ================================================== Un premier problème se pose lorsque plusieurs exemplaires d un même signal sont reçus par un processus dans un lap de temps très court, typiquement le temps nécessaire à l execution de la routine associée au signal. Une premiere question est : mémorise-t-on l arrivée des différents signaux et si oui comment? La réponse pour les signaux "classiques" UNIX est : il existe un masque, avec un bit par signal, qui dit s il existe une occurrence du signal en attente (car un signal n arrive pas forcement alors que le processus est en execution et dans ce cas il faut bien pouvoir mémoriser le signal afin de démarrer le processus sur la routine associée au signal lorsqu il sera a nouveau élu par l ordonnanceur, sinon cela signifierait que le comportement d un processus, et donc le résultat de l execution d un programme, depend de l ordonnancement, ce qui serait fâcheux!). Un bit par signal cela signifie 0 ou 1, autrement dit on peut savoir s il existe 1 signal en attente (pending signal en anglais) ou pas. Consequence : si plusieurs signaux arrivent en même temps un seul sera mémorise! Il existe 2 solutions pour contourner cette limitation : arranger le programme pour éviter qu une telle situation ne se produise ou utiliser les signaux temps reel POSIX1b. Dans le cas des signaux temps reel un mot de 32 bits est associé à chaque signal, qui donne le nombre d occurrences du signal en attente. Une seconde question est : que se passe-t-il si un signal arrive alors que le processus est deja en train d exécuter la routine associée a un signal (éventuellement le même). Logiquement la prise en compte des signaux est immediate (principe des interruptions), ce qui signifie que l execution de la routine est interrompue afin de permettre l execution de la routine associée au signal le plus recent. Ce comportement peut avoir des consequences ennuyeuses. Imaginez le handler suivant : void routine (int n) { static int i=0 ; if (i == 0) i++ ; else i ; } Cette routine implémente une bascule 0/1. Imaginons maintenant qu elle soit associée a un signal et que 2 occurrences du signal soient reçues presque au même instant par le processus. Le second signal est reçu alors que i vaut 0 et que l execution de la routine vient d effectuer le test (i == 0), qui par consequent, aiguille le traitement sur l instruction i++. L execution de la routine est alors interrompue et la même routine est a nouveau exécutée en réponse a la reception du second signal. Puisque i vaut toujours 0 le test (i == 0) renvoie vrai et i est incrémente (i vaut désormais 1). Puis on reprend l execution de la routine interrompue qui en est a l instruction i++, ce qui a pour consequence de faire passer la valeur de i a 2. Ainsi on se retrouve avec une valeur de i qui est théoriquement impossible par programmation! Que faudrait-il faire afin d éviter une telle situation? Garantir l execution atomique de la routine, ce qui revient a bloquer les signaux pendant l execution d un handler. Le blocage des signaux est une operation courante, qui signifie que la prise en compte du signal est différée tant que le signal est bloque, autrement dit il n y a pas de perte de signaux dus au blocage, ils sont pris en compte des le déblocage. La fonction signal, si elle a pour avantage sa simplicité d utilisation, a l inconvenient de ne pas permettre le blocage des signaux. La norme POSIX1, qui définit le comportement de l API C pour la programmation système, stipule que les bibliothèques de gestion de signaux doivent permettre le blocage des signaux et même que ce blocage doit être effectue implicitement pendant l execution d un handler. Les fonctions

de la bibliothèque POSIX1 sont les primitives sigaction(), qui remplace signal(), et sigprocmask(), qui permet le blocage ou le déblocage de signaux a n importe quel moment. A noter que la norme POSIX precise également que les routines associées aux signaux le restent après prise en compte d un signal. La primitive signal() ne faisant pas partie d une normalisation, le comportement est laisse au choix du constructeur, ce qui peut rendre les applications non portables. Ainsi sous Linux la fonction signal ne restitue pas les handlers par défaut alors que sous Systeme V (Sun Solaris par exemple) c est le cas et la premiere instruction du handler est alors typiquement un appel a signal() afin d associer a nouveau le handler au signal. Exercice 1 : Déroutement d un signal Écrire un programme qui crée un fils. Le fils déroute les signaux SIGTERM et SIGKILL, puis s endort. Le pere lui envoie successivement ces deux signaux. Que constatez-vous? 1 #include<stdio.h> 2 #include<signal.h> 3 #include<unistd.h> 4 #include<errno.h> 5 6 void Handler(int sig) 7 { 8 struct sigaction action, actionant; 9 printf("<%d> Signal recu: %d\n", getpid(), sig); 10 sleep(10); 11 } 12 13 14 int main() 15 { 16 pid_t pid, ppid; 17 int retour; 18 struct sigaction action; 19 20 system("clear"); 21 printf("\t COMMUNICATION ENTRE PROCESSUS PAR SIGNAUX\n"); 22 printf("\t *****************************************\n"); 23 24 pid = fork(); 25 switch(pid) 26 { 27 case -1: 28 perror("fork"); 29 exit(-1); 30 case 0: 31 action.sa_handler = Handler; 32 if ((retour= sigaction(sigterm,&action,null))!= 0) 33 { 34 perror("sigaction SIGTERM"); 35 } 36 printf("le fils a deroute SIGTERM.\n");

37 sigaction(sigkill,&action,null); 38 if ((retour= sigaction(sigkill,&action,null))!= 0) 39 { 40 perror("sigaction SIGKILL"); 41 } 42 printf("le fils a deroute SIGKILL.\n"); 43 sleep(20); 44 break; 45 46 default: 47 sleep(3); 48 printf("le pere envoie SIGTERM %d au fils\n",sigterm); 49 if ((retour= kill(pid, SIGTERM)) == -1) 50 { 51 perror("kill SIGTERM"); 52 exit(-1); 53 } 54 sleep(5); 55 printf("le pere envoie SIGKILL %d au fils\n",sigkill); 56 if ((retour= kill(pid, SIGKILL)) == -1) 57 { 58 perror("kill SIGKILL"); 59 exit(-1); 60 } 61 sleep(3); 62 wait(null); 63 break; 64 } 65 } Exercice 2 : Synchronisation par SIGSTOP et SIGCONT On désire simuler un bar électronique. Écrire un programme qui crée un fils. Le père jouera le rôle du barman et le fils celui du client. Le barman doit effectuer deux tâches servir_verre(1) et servir_verre(2). Le client doit effectuer deux tâches demander_verre(1) et demander_verre(2). On veut synchroniser la réalisation de ces tâches dans cette ordre : demander_verre(1), servir_verre(1), demander_verre(2), servir_verre(2) en utilisant les signaux SIGSTOP et SIGCONT. Comment feriez vous pour faire la même chose sans utiliser ces signaux? 1 #include <signal.h> 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 void servir_verre(int inum) 7 { 8 printf ("Je suis %d et je sers le verre %d\n", getpid(), inum); 9 } 10 void demander_verre(int inum) 11 { 12 printf ("Je suis %d et je demande le verre %d\n", getpid(), inum);

13 } 14 15 int main(int argc, char *argv[]) 16 { 17 int pid, statut; 18 char *p; 19 20 pid = fork(); 21 switch(pid) 22 { 23 case -1: 24 { 25 perror("fork"); 26 exit(-1); 27 } 28 case 0 : 29 demander_verre(1); 30 sleep(4); 31 kill(getppid(),sigcont); 32 kill(getpid(),sigstop); 33 demander_verre(2); 34 sleep(4); 35 kill(getppid(),sigcont); 36 break; 37 default : 38 kill(getpid(),sigstop); 39 servir_verre(1); 40 sleep(4); 41 kill(pid,sigcont); 42 kill(getpid(),sigstop); 43 servir_verre(2); 44 wait(&statut); 45 } 46 } 47 Exercice 3 : Le cas particulier de SIGALRM Écrire un programme qui attend que l utilisateur réagisse à un message de type message d alerte. Il a 5 secondes pour le faire. Si au bout de trois tentatives l utilisateur ne l a toujours pas fait le programme lance le programme terminaison_automatique() sinon il lance le programme terminaison_manuelle(). On simule l acquittement du message d erreur par une pression sur le clavier. 1 #include <signal.h> 2 #include <stdio.h> 3 #include <errno.h> 4 5 int isaisie, icpt; 6 7 void f(int sig) 8 {

9 printf("top\n"); 10 isaisie = 1; 11 icpt++; 12 } 13 14 void TerminaisonManuelle() 15 { 16 printf("arret MANUEL\n"); 17 } 18 void TerminaisonAutomatique() 19 { 20 printf("tant PIS - ARRET AUTOMATIQUE\n"); 21 } 22 23 24 int main() 25 { 26 struct sigaction action; 27 action.sa_handler = f; 28 if(sigaction(sigalrm,&action,null)==-1) 29 { 30 perror("erreur Sigaction"); 31 exit(-1); 32 } 33 isaisie = 1; 34 icpt = 1; 35 while((isaisie) && (icpt <= 3)) 36 { 37 isaisie = 0; 38 alarm(5); 39 printf("alerte - Validez l arrêt par une pression sur la touche ENTREE\n 40 scanf("%*c"); 41 if(isaisie == 0) 42 alarm(0); 43 } 44 if(isaisie == 0) 45 TerminaisonManuelle(); 46 else 47 TerminaisonAutomatique(); 48 } 49 Exercice 4 : Le traitement des zombies avec le signal SIGCHLD Écrire un programme qui crée un fils. Le père déroute le signal SIGCHLD pour supprimer le fils zombie, puis il fork. Le fils s endort. Le programme ne se terminera pas il faudra le tuer à partir de la ligne de commande. 1 #include <signal.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <errno.h>

5 void f(int); 6 void derouter(int); 7 void erreur(const char *); 8 void main() 9 { 10 pid_t pid; 11 derouter(sigchld); 12 pid = fork(); 13 switch(pid) 14 { 15 case -1: 16 erreur("erreur Fork:"); 17 18 case 0 : 19 printf("fils : %d\n",getpid()); 20 break; 21 22 default: 23 while(1) 24 { 25 printf("je travaille\n"); 26 sleep(3); 27 } 28 } 29 } 30 void derouter(int sig) 31 { 32 struct sigaction action; 33 action.sa_handler = f; 34 printf("signal %d recu et deroute par le pere\n",sig); 35 if(sigaction(sig,&action,null)==-1) 36 erreur("erreur Sigaction:"); 37 } 38 void f(int sig) 39 { 40 int statut; 41 printf("le fils zombie est supprime %d\n", wait(&statut)); 42 } 43 void erreur(const char * message) 44 { 45 perror(message); 46 exit(-1); 47 } 48