Signaux – Tubes La gestion des signaux La communication par tube

Slides:



Advertisements
Présentations similaires
Premier programme en C :
Advertisements

La boucle for : init7.c et init71.c
Synchronisation des processus père - fils
GEF 243B Programmation informatique appliquée
(Classes prédéfinies – API Java)
Cours n°2M2. IST-IE (S. Sidhom) UE 303 Promo. M2 IST-IE 2005/06 Conception dun système d'information multimédia Architecture trois-tiers : PHP/MySQL &
C.
Mémoire & Processus Cours SE - SRC
Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',
Suite à de nombreuses remarques concernant le projet de structures de données 'Gestion d'un Aéroport' , voici un polycopié de cours concernant la gestion.
Tableaux Certains problèmes nécessitent beaucoup de variables du même type. Exemple : relevé de températures matin et soir dans 10 villes pour 10 jours.
Chap. 1 Structures séquentielles : listes linéaires
FLSI602 Génie Informatique et Réseaux
Système d’exploitation : Assembleur
Système d’Exploitation
Systèmes d'exploitations Les redirections d'entrées/sorties GRARI Mounir ESTO Année 2011.
Common Gateway Interface
Regrouper des éléments de même type et pouvoir y accéder à laide dun identificateur et dun indice. Objectif des tableaux.
Introduction à la programmation (420-PK2-SL) cours 12 Gestion des applications Technologie de linformation (LEA.BW)
Récursivité.
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
Système d’exploitation
Programmation fonctionnelle Le langage LISP
Course Critique Race Condition
Les pointeurs Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert?
FICHIERS : Définition : Algorithme général:
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Test et débogage Tests unitaires. Gestion d’erreurs. Notion d’état, de pré-condition et de post-condition. Assertion. Traces de programme. Débogueur et.
Sixième cours Les chaînes de caractères et le passage de paramètres par référence Passage de paramètres par référence String.h.
Programmation concurrente
IFT 6800 Atelier en Technologies d’information
SYSTÈME D’EXPLOITATION I
ÉLÉMENTS DE BASE UNIX.
Christine Bonnet SOURCES : « Samples » dOracle, « Oracle 8 » R. Chapuis PRO*C – C ++
Programme de baccalauréat en informatique Programmation Orientée Objets IFT Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement.
Utilisation avancée de linux
Structures des données
02/11/06Programmation multitâche sous UnixIsaip-Esaip1 Groupe Isaip-Esaip P. Trégouët – A. Schaal remerciements à M. Benzaïd pour sa contribution à la.
Le langage C Rappel Pointeurs & Allocation de mémoire.
Ch. PAUL - Piles et Files à l'aide de listes chainées
Programmation Système et Réseau (sous Linux)
LES PILES ET FILES.
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
PHP 5° PARTIE : LES COOKIES
SIF-1053 Architecture des ordinateurs
GESTION ET TRAITEMENT DES ERREURS
Communication avec l’environnement
Un survol du language C.
Interactions entre Processus
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
Tutorat en bio-informatique
Programmation Système et Réseau
Exec et signaux. Comment surveiller les processus? Avant d’aller plus loin, vous aurez sans doute besoin de cette commande : ps –A u: permet d’afficher.
8PRO100 Éléments de programmation Les pointeurs de caractères.
1 Système d’exploitation Les scripts csh 1 ère Année Année Tienté HSU.
Classe 1 CSI2572 Autres modificateurs de déclaration de variables: & volatile & register & static & auto & extern & const volatile Indique au compilateur.
Les variables fichiers. Le type fichier On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; –Nom physique.
Signaux Il s'agit de messages asynchrones envoyés à un processus
Architecture Client/Serveur
8PRO107 Éléments de programmation Les adresses et les pointeurs.
1 PHP 5 Notions fondamentales (niveau 1 cours #3) Formation continue – Cégep de Sainte-Foy François G Couillard.
Chapitre 9 Les caractères.
Client/Server Socket. Client/Serveur.
1 UNIX AVANCE Yves PAGNOTTE – Janvier – LES PROCESSUS SOUS UNIX.
Informatique 2A Langage C 5ème séance. Déroulement de la séance 5 1 ère partie Étude des chaînes de caractères 2 ème partie Les structures 3.
Informatique 2A Langage C 4ème séance
1 UNIX AVANCE Yves PAGNOTTE – Janvier – COMMUNICATION INTER PROCESSUS : TUBES.
Communication entre Processus
Transcription de la présentation:

Signaux – Tubes La gestion des signaux La communication par tube Tube ordinaire ("pipe") Tube nommé ("FIFO") Les primitives de recouvrement Fonctions de la famille exec La duplication des descripteurs

Les signaux Un signal correspond à un évènement particulier, dont l'occurrence produit l'émission à destination du (ou des) processus concerné(s) De façon plus informatique, on peut définir les signaux comme étant des interruptions logicielles 4 questions importantes Quelle information un signal véhicule t'il ? Comment les signaux sont ils émis ? Quand les signaux sont ils pris en compte ? Que fait un processus à la prise en compte d'un signal ? Vocabulaire Un signal pendant est un signal envoyé mais pas encore pris en compte Un signal est délivré lorsqu'il est pris en compte par le processus qui le reçoit On peut dans certaines version d'Unix différer volontairement la délivrance de certains signaux : bloqués ou masqués

Liste des signaux Définis dans <signal.h> SIGABRT : terminaison anormale du processus. SIGALRM : alarme horloge SIGFPE : erreur arithmétique SIGHUP : rupture de connexion SIGILL : instruction illégale SIGINT : interruption terminal SIGKILL : terminaison impérative. Ne peut être ignoré ou intercepter SIGPIPE : écriture dans un conduit sans lecteur disponible SIGQUIT : signal quitter du terminal SIGSEGV : accès mémoire invalide SIGTERM : signal « terminer » du terminal SIGUSR1 : signal utilisateur 1 SIGUSR2 : signal utilisateur 2 SIGCHLD : processus fils stoppé ou terminé SIGCONT : continuer une exécution interrompue SIGSTOP : interrompre l’exécution. Ne peut être ignoré ou intercepter SIGTSTP : signal d ’arrêt d ’exécution généré par le terminal SIGTTIN : processus en arrière plan essayant de lire le terminal SIGTTOU : processus en arrière plan essayant d ’écrire sur le terminal SIGBUS : erreur accès bus SIGPOLL : événement interrogeable SIGPROF : expiration de l’échéancier de profilage SIGSYS : appel système invalide SIGTRAP : point d’arrêt exécution pas à pas SIGURG : donnée disponible à un socket avec bande passante élevée SIGVTALRM : échéancier virtuel expiré SIGXCPU : quota de temps CPU dépassé SIGXFSZ : taille maximale de fichier dépassée Définis dans <signal.h> La seule information contenue est le type du signal Le récepteur ne sait pas si l'évènement s'est produit Le récepteur ne connaît pas l'identité de l'émetteur L'évènement provient De l'extérieur (clavier, …) De l'intérieur (erreur arithmétique, …) Les plus importants pour nous SIGUSR1, SIGUSR2, SIGKILL, SIGALRM, SIGINT

Émission d'un signal La primitive kill permet d'émettre un signal sig vers un ou plusieurs processus int kill(pid_t pid, int sig); pid représente Si pid > 0, le pid du processus Si pid = 0, tous les processus dans le même groupe que le processus émetteur Si pid = -1, non définie dans POSIX Si pid < -1, tous les processus du groupe |pid| ATTENTION : cet appel système est particulièrement mal nommé, car il ne tue que très rarement un processus …

Prise en compte d'un signal A chaque type de signal est associé, dans le système un handler. Le handler définit le comportement d'un processus quand un signal est délivré. Par défaut, un comportement est associé à tous les signaux Terminaison du processus, terminaison avec image (core), ignoré, suspension du processus, continuation Sauf pour les signaux SIGKILL, SIGCONT, SIGSTOP, il est possible de définir un handler installé par le processus Une fonction de handler est définie comme suit : void my_handler(int sig); Cette fonction de handler est exécutée par le processus à la délivrance d'un signal. Cette fonction ne retourne pas de valeur (variable globale …). Elle reçoit le numéro du signal. A la fin de l'exécution de cette fonction, l'exécution du processus reprend au point où elle a été suspendue. Quelques remarques Un processus endormi est réveillé par l'arrivée d'un signal Les signaux sont sans effet sur un processus zombi

Prise en compte d'un signal Blocage des signaux : La norme POSIX définit un ensemble de fonctions pour la manipulation des signaux Voir documentation (sigprocmask, sigpending, …) Installation de la fonction de handler POSIX : structure sigaction à remplir, puis fonction sigaction() Structure sigaction dépend des versions de Linux … (ne jamais l'initialiser de façon statique …) Non POSIX (mais tellement plus simple) void (*signal(int sig, void (*my_handler)(int))) (int); La fonction signal renvoie un pointeur sur la fonction de handler précédente associée au signal Example signal(SIGUSR1, my_handler); Préférer la version POSIX si vous devez gérer des signaux dans une application portable (mais plus difficile à mettre en œuvre).

Signaux : quelques précisions supplémentaires Il faut généralement réinstaller le handler à la délivrance d'un signal pour prendre en compte le suivant (suivant les versions du SE) … Une fonction de handler doit rester courte Installer le handler avant l'arrivée du signal Un processus peut se mettre en attente de réception d'un signal Non POSIX : pause() La fonction pause ne permet ni d'attendre l'arrivée d'un signal de type précis, ni de savoir quel signal arrive (récupérer la valeur du paramètre dans la fonction de handler) POSIX : sigsuspend() Fonction particulière unsigned int alarm(unsigned int secondes) Génère le signal SIGALRM après un nombre de secondes passé en paramètre à la fonction alarm

Signal : exemple (non POSIX) #include <stdio.h> #include <signal.h> void my_handler(int); int variable_gbl = 0; int main() { if (signal(SIGINT, my_handler) == SIG_ERR) /* Erreur */ pause(); if (variable_gbl == 1) . . . return 0; } void my_handler(int a) variable_gbl = 1;

Communication par tubes Mécanisme de communication appartenant au système de gestion de fichiers Un tube correspond à un nœud sur un disque logique Un tube est désigné par un descripteur Un tube est manipulé avec les fonctions read et write Un tube peut être associé aux E/S grâce aux mécanisme de redirection (primitive de recouvrement …) Caractéristiques Mécanisme de communication unidirectionnel 2 extrémités : soit lecture, soit écriture L'opération de lecture dans un tube est destructrice Flot continu de caractères (envois successifs vus comme un seul) Un tube a une capacité finie (nombre d'adresses directes contenu dans un nœud …)

Les tubes ordinaires (ou non nommés) Ce fichier est détruit lorsque plus aucun processus ne l'utilise Aucun répertoire ne contient de référence à ce fichier Un tube ordinaire est un fichier sans nom Impossible pour un processus d'ouvrir un tube ordinaire à l'aide de la fonction open() Il faut donc connaître le descripteur associé à ce fichier A la création Héritage entre processus Conséquences : limité entre processus issus de la même descendance du créateur du tube ordinaire Quand un processus a perdu un accès dans un des 2 modes, il ne peu plus le retrouver

Tubes ordinaires : création La fonction pipe() permet de créer un tube ordinaire int pipe(int p[2]); #include <unistd.h> Alloue un nœud sur le disque et crée 2 descripteurs dans la table du processus appelant. Le tableau de 2 entiers est passé en paramètre et contient au retour ces descripteurs (p[0] pour la sortie, p[1] pour l'entrée) write read p[1] p[0]

Tubes ordinaires : lecture Algorithme Si le tube n'est pas vide, on extrait au plus TAILLE_BUF caractères qui sont placés à l'adresse buf Si le tube est vide Si le nombre d'écrivains est nul, la fin du fichier est atteinte (nb_lu = 0) Si le nombre d'écrivains n'est pas nul, Si la lecture est bloquante (par défaut), le processus est mis en sommeil jusqu'à ce que le tube ne soit plus vide Si la lecture est non bloquante (cf fonction fcntl), retour immédiat avec -1 Risque d'auto-blocage ou d'inter-blocage #include <stdio.h> #include <unistd.h> #define TAILLE_BUF 50 int main() { int p[2]; int nb_lu; char buf[TAILLE_BUF]; if (pipe(p) == -1) /* Erreur */ close(p[1]); … nb_lu = read(p[0], buf, TAILLE_BUF); return 0; } Ne conserver que les descripteurs utiles Fermer systématiquement tous les autres

Tubes ordinaires : écriture int main() { int tube[2]; int n; char buf[50]; if (pipe(tube) == -1) printf("Erreur de pipe !!!\n"); exit(0); } ... /* Creation du fils */ /* code du pere */ close(tube[0]); … n = strlen(buf) + 1; write(tube[1], buff, n); Algorithme Si le nombre de lecteurs dans le tube est nul, le signal SIGPIPE est délivré au processus écrivain (par défaut, il termine le processus …). Si le nombre de lecteurs est non nul Si l'écriture est bloquante (cf fonction fcntl), le retour n'a lieu que si n caractères ont été écrits (écriture atomique si n < PIPE_BUF définie dans <limits.h>). Le processus est donc susceptible de s'endormir. Si l'écriture est non bloquante Si n > PIPE_BUF, le retour est inférieur à n Si n ≤ PIPE_BUF, l'écriture atomique est réalisée (si tube non plein)

Les tubes nommés (FIFO) Ils font partie de la norme POSIX sous le nom de fifo Ils ont toutes les propriétés des tubes ordinaires, avec en plus : Ils ont une référence dans le système de fichiers Un processus connaissant cette référence peut récupérer un descripteur via la fonction open Autorise la communication entre différents processus Fonction de création d'un tube nommé int mkfifo(const char*ref, mode_t mode) ref indique le chemin d'accès au fichier, mode est construit comme open Dans <sys/types.h> et <sys/stat.h> int main() { char s[30] = "bonjour !!!"; int num, fd; if ( mkfifo("fifo", 0666) == -1) perror("mkfifo"); fd=open("fifo", O_WRONLY); . . . write(fd, s, strlen(s)); . . . int main() { char s[30]; int num, fd; if ( mkfifo("fifo", 0666) == -1) perror("mkfifo"); fd=open("fifo", O_RDONLY); . . . read(fd, s, 30); . . .

Primitives de recouvrement Ensemble de fonctions permettant à un processus de charger en mémoire un nouveau programme binaire en vue de son exécution Remplacement de l'espace d'adressage du processus par un nouveau programme (segment texte, données, pile, tas) Pas de retour de recouvrement, sauf si il n'a pas pu avoir lieu Pas de création de processus Lance le nouveau programme Déroulement d'un tel appel système Recherche du fichier à exécuter (utilisation de la variable PATH) Vérification des droits d'accès en exécution de l'utilisateur Vérification que le fichier est exécutable (nombre magique) Sauvegarde des paramètres de l'appel à la fonction de recouvrement Création du nouvel espace d'adressage (texte, données, pile, tas) Restitue les paramètres précédemment sauvegardés Initialisation du contexte matériel

Primitives de recouvrement execv : Paramètres de la commande transmis sous forme d’un tableau de pointeurs sur des chaînes de caractères. La première case du tableau doit contenir le nom absolu de l’exécutable et le dernier doit être NULL. execl : Nombre variable de paramètres. Le premier paramètre étant le nom absolu de l’exécutable, le dernier est NULL. execvp et execlp : Utilise la variable PATH pour localiser l'exécutable. Peut lancer des scripts execle et execve : aussi un pointeur sur un tableau de variables d'environnement execlp("ls", "ls", "-l", "-a", NULL); execl("/bin/ls", "ls", "-l", "-a", NULL); char *mes_arg[4]={"/bin/ls", "-l", "-a", ""}; execv("/bin/ls", mes_arg);

Duplication des descripteurs La duplication des descripteurs permet à un processus d'acquérir un nouveau descripteur (dans sa table de descripteurs) synonyme d'un descripteur déjà existant Ce mécanisme est principalement utilisé pour rediriger les E/S standard Ce mécanisme repose sur le fait que le descripteur dupliqué prendra toujours la place du plus petit descripteur libre dans la table. Rappel : A la création d'un processus, la table des descripteurs contient 3 descripteurs TableDesc[0] stdin TableDesc [1] stdout TableDesc [2] stderr

Duplication des descripteurs On supprime une référence dans la table des descripteurs avec la fonction int close(numero_du_descripteur) Par exemple, pour supprimer la référence à stdin close(0); La fonction dup (dans <unistd.h>) associe le descripteur au plus petit numéro disponible dans la table int dup(int descripteur); Par exemple, si p[0] est la sortie d'un tube ordinaire dup(p[0]); ce qui remplace l'entrée standard (le clavier) par la sortie du tube p La fonction dup2 force le descripteur1 à la place du descripteur2 (réalise un close(descripteur2 si besoin)) int dup2(int descripteur1, int descripteur2);

Exemple de programme close(tube[1]); close(tube[0]); int main() { . . . if (pid_fils == 0) /* Code du fils */ close(0); dup(tube[0]); close(tube[1]); close(tube[0]); if (execlp("./affichage", "./affichage", 0) == -1) printf("Erreur execlp !!!\n"); exit(0); } else /* code du pere */ strcpy(buf, "bonjour !!!\n"); write(tube[1], &buf, strlen(buf) + 1); sleep(1); kill(pid_fils, SIGKILL); wait(0); return 0; /* affichage. c */ int main() { char c; do scanf("%c", &c); printf("%c", c); } while(1); return 0; }