A 2015, AG 2021A 2015, AG 2021
Communication processus-utilisateur
A 2015, AG 2021A 2015, AG 2021
Communication avec un processus Les fichiers standard
Redirections Signaux
UNIX – GNU/Linux
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
Ces fichiers permettent la communication entre un processus et l'utilisateur
Les descripteurs sont définis à bas niveau dans le fichier unistd.h :
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /*
Standard output. */
#define STDERR_FILENO 2 /*
Standard error output. */
Il est conseillé d'utiliser les noms symboliques STD*
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
A haut niveau dans le fichier stdio.h : extern struct _IO_FILE *stdin; /*
Standard input stream. */
extern struct _IO_FILE *stdout; /*
Standard output stream. */
extern struct _IO_FILE *stderr; /*
Standard error output stream. */
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
Ces descripteurs font partie de l'héritage du processus lors de sa création
Lorsque le processus a été créé par un
interpréteur de commande ces trois fichiers sont obtenus par l'ouverture d'un fichier
/dev/tty* dont le nom est affiché par la commande tty
/dev/tty1, /dev/tty2, … pour un terminal en mode caractère
/dev/pts/0, /dev/pts/1, … pour un pseudo- terminal ( fenêtre, réseau)
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
La commande stty permet d'afficher/modifier les caractéristiques de fonctionnement du
terminal :
taille des caractères,
signaux envoyés par des
combinaisons de touches ^c, ^z, taille des caractères,
Suspension/Reprise de l'affichage :
^s/^q
Caractères de fin de ligne/fichier : \n,
^d ...
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
Le terminal fonctionne en deux modes principaux :
Mode canonique ou « cooked » dans lequel : Les corrections durant la frappe sont
possibles
Les caractères frappés sont stockés dans un tampon d'entrée et ne sont transmis au processus qu'après la frappe d'un caractère Entrée (\r) au clavier transformé en \n marquant la fin de la ligne
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
Mode direct ou raw permettant une gestion
directe par l'application des caractères frappés au clavier :
Saisie de caractères à la volée Réception directe des caractères
Ce mode est utilisé par les éditeurs de texte par exemple pour permettre la gestion du
curseur avec les touches de déplacement, de changement de page …
La commande stty sane permet de revenir au mode canonique après l'arrêt brutal d'un éditeur de texte par exemple
Pas de caractères d'édition BS, DEL, ...
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
Le terminal est appelé terminal de contrôle du processus
Tous les processus appartenant au même groupe de processus ont le même terminal de contrôle et certains signaux sont transmis à l'ensemble de ces processus
Signal d'arrêt lors d'une déconnexion par exemple.
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
0/stdin : ouverture en lecture du terminal = clavier
1/stdout : ouverture en sortie du terminal = écran, les caractères émis ne sont affichés qu'après écriture d'un caractère \n, tampon d'une ligne
2/stderr : ouverture en sortie du terminal = écran, les caractères émis sont affichés immédiatement, à utiliser pour afficher les messages lors de la mise au point d'un
programme
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les fichiers standard d'entrée/sortie
bas niveau int
haut niveau struct FILE * stdin
stdout stderr
0 1 2
Périphérique
A 2015, AG 2021A 2015, AG 2021
Communication avec un processus Les fichiers standard
Redirections Signaux
UNIX – GNU/Linux
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Redirection
La redirection d'un fichier standard
d'entrée/sortie peut être effectuée de 2 manières :
Par ouverture d'un fichier et son
association à un descripteur de haut niveau à l'aide de la fonction de
bibliothèque freopen
Par modification du périphérique
désigné par le descripteur de bas
niveau en utilisant une des primitives dup ou dup2
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
freopen
FILE *freopen(const char *path, const char
*mode, FILE *stream);
La fonction freopen ouvre le fichier de nom path et l'associe au descripteur stream
Le flux original est fermé s'il était valide Mode est identique à celui de fopen :
r, r+ en lecture w, w+ en écriture
a, a+ en mode ajout
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
freopen
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE * redir;
fprintf(stdout,"La sortie standard\n");
fprintf(stderr,"La sortie d'erreur standard\n");
redir = freopen("/tmp/stdout.txt","w",stdout);
if ( redir == NULL ) {
perror("Echec de l'ouverture de /tmp/stdout.txt");
return EXIT_FAILURE;
}
fprintf(stdout,"La sortie standard après redirection\n");
fprintf(stderr,
"La sortie d'erreur standard après redirection\n");
return EXIT_SUCCESS;
}
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
freopen
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup/dup2
C'est la méthode universelle permettant d'effectuer une redirection par duplication d'un descripteur de bas niveau valide dans un descripteur non valide
Elle est utilisable même si le descripteur de bas niveau que l'on veut dupliquer existe déjà et ne peut être ouvert :
tube
tube nommé socket
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup/dup2
Elle comporte 4 étapes dont deux (1 et 4) sont facultatives :
1- Création d'un descripteur en utilisant open
2- Fermeture du descripteur à rediriger avec close
3- duplication du descripteur valide à l'aide de dup
4- fermeture du descripteur ayant été utilisé pour la redirection
L 'étape 1 est inutile si le descripteur existe déjà ( tube, socket )
L'étape 4 est facultative dans tous les cas
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup/dup2
Les primitives de duplication :
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
dup : duplique les descripteur passé en paramètre dans le plus petit descripteur disponible
dup2 : ferme newfd si besoin puis duplique oldfd dans newfd, oldfd doit être valide. Si newfd = oldfd rien n'est fait
Valeur retournée : -1 en cas d'erreur, newfd sinon
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Création du descripteur
bas niveau int haut niveau
struct FILE * stdin
stdout stderr
0 1 2 fd
fd = open( ….)
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Fermeture descripteur sortie standard
bas niveau int
haut niveau struct FILE * stdin
stdout stderr
0 1 2 fd
close(1)
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Après duplication du descripteur fd
bas niveau int
haut niveau struct FILE * stdin
stdout stderr
0 1 2 fd
dup(fd)
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Fermeture du descripteur fd
bas niveau int
haut niveau struct FILE * stdin
stdout stderr
0 1 2 fd
close(fd)
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
int erreur;
fprintf(stdout,"La sortie standard\n");
if ( (erreur = open("/tmp/stdout.txt",\
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR)) < 0 ) { perror("Echec de l'ouverture de /tmp/stdout.txt");
return EXIT_FAILURE; } close(1);
if ( dup(erreur) < 0 ){
perror("dup");
return EXIT_FAILURE; } close(erreur);
fprintf(stderr,"La sortie standard d'erreur après redirection\n");
fprintf(stdout,"La sortie standard après redirection\n");
fflush(stdout);
return EXIT_SUCCESS;
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup2
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
int erreur;
fprintf(stdout,"La sortie standard\n");
if ( (erreur = open("/tmp/stdout.txt",\
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR)) < 0 ) { perror("Echec de l'ouverture de /tmp/stdout.txt");
return EXIT_FAILURE; }
if ( dup2(erreur, STDOUT_FILENO) < 0 ){
perror("dup2");
return EXIT_FAILURE;
}
close(erreur);
fprintf(stderr,"La sortie standard d'erreur après redirection\n");
fprintf(stdout,"La sortie standard après redirection\n");
fflush(stdout);
return EXIT_SUCCESS;
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Utilisation de la primitive dup2
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
recouvrement
Les descripteurs des fichiers ouverts font partie de l'héritage durant le fork
Durant un exec tous ces descripteurs, sauf ceux ouverts avec le drapeau O_CLOEXEC restent valides il est donc possible de
rediriger les fichiers standard juste avant l'appel à exec
La même procédure peut évidemment être utilisée après fork pour exécuter un
processus fils après avoir redirigé un ou plusieurs fichiers standard
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
recouvrement
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main (int narg, char * arg []) {
char * arguments [] = {"cat", (char*) NULL};
int entree, sortie;
entree=open("/etc/motd",O_RDONLY);
if ( entree < 0 ) {
perror("Ouverture de /etc/motd");
return EXIT_FAILURE;
}
sortie=open("/tmp/motd",O_WRONLY|O_CREAT|
O_TRUNC,S_IRWXU);
if ( sortie < 0 ) {
perror("Ouverture de /tmp/motd");
return EXIT_FAILURE;
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
recouvrement
close(0);
if ( dup(entree) < 0){
perror("Echec de la redirection de l'entee standard");
return EXIT_FAILURE;
}
close(1);
if ( dup(sortie) < 0){
perror("Echec de la redirection de la sortie standard");
return EXIT_FAILURE;
}
(void) execv("/bin/cat", arguments);
perror("Echec de la primitive execlp cat");
return EXIT_FAILURE;
}
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
recouvrement
A 2015, AG 2021A 2015, AG 2021
Communication avec un processus Les fichiers standard
Redirections Signaux
UNIX – GNU/Linux
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Qu'est ce qu'un signal ?
Un signal est une information élémentaire reçue par un processus lui signalant
l'occurrence d'un événement : Fin d'un fils
Erreur arithmétique Demande d'arrêt
Demande de suspension temporaire Reprise de l'exécution
...
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Envoi d'un signal
Ce signal peut-être envoyé
par le SE au processus qui à commis une faute
par un autre processus exécutant la primitive :
int kill(pid_t pid, int sig)
par l'utilisateur avec la commande kill : kill [options] PID [...]
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Les signaux (man 7 signal) Posix 1-1990
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
1-2001
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
Signaux divers
A 2015, AG 2021A 2015, AG 2021
Signaux temps réel
32 signaux temps réel
Définis sans Posix.1b et Poosix.1.2001
Numéro : SIGRTMIN=33 à SIGRTMAX=64 Pas de signification particulière
Deux ou trois signaux sont utilisés par la bibliothèque pthreads
Toujours utiliser SIGRTMIN+n et pas un numéro
Exemple : SIGRTMIN+2 = 35
Communication Comm. Inter.
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
réception d'un signal
A la réception d'un signal le processus peut se comporter des trois manières suivantes :
Ignorer le signal : rien ne se passe (SIG_IGN)
Laisser le système d'exploitation
appliquer l'action par défaut indiquée dans les tableaux précédents
(SIG_DFL)
Traiter le signal en ayant auparavant associé au signal une fonction de traitement à l'aide de la primitive signal
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Envoi d'un signal avec la commande kill
Syntaxe :
kill [options] p1 [ p2 … pn ] Options :
-no_signal
-s, --signal no_signal
-l, --list : liste les signaux
-L, --table : liste les signaux mis en forme
Par défaut le signal SIGTERM (15) est envoyé
Attention : certains shell possédent une
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Traitement des signaux par le processus
Pour effectuer une action spécifique lors de la réception du signal il faut associer une fonction de traitement aux signaux que l'on désire traiter par utilisation de la primitive signal
La fonction exécutée lors de l'arrivée du signal reçoit en paramètre le numéro du signal et ne doit retourner aucun résultat
Après traitement du signal la fonction peut : Terminer le processus en appelant exit Retourner au programme interrompu
en exécutant une instruction return
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
la primitive signal
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
void (*signal (int signum, void (* handler)(int))) (int)
sighandler_t est un pointeur sur une fonction ne retournant aucun résultat, recevant en
paramètre un entier
Les paramètres de la primitive signal sont : Un entier le numéro du signal à traiter
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
la primitive signal
La fonction associée au signal peut être une des 2 fonctions prédéfinies par signal.h :
SIG_DFL : traitement par défaut du signal (voir tableau des signaux) SIG_IGN : ignorer le signal
Un pointeur sur une fonction
spécifique qui doit être définie par le programmeur
La primitive retourne la valeur précédente du gestionnaire de signal ou -1 en cas d'erreur
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
la primitive signal
Après exécution de cette primitive, la
réception du signal dont le numéro a été passé en paramètre :
Interrompra le processus quelque soit l'endroit où il en est dans son
exécution
Lancera l'exécution de la fonction pointée par le second paramètre Si la fonction exécute return le programme sera repris à l'endroit ou il a été interrompu Si la fonction appelle exit le processus sera terminé
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
int main ( ){
signal(s,traite) ;
…
…
…
…
… ...
…
return EXIT_SUCCESS }
void traite(int s) { ….
….
return ; }
Signal s
au programme
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
int main ( ){
signal(s,traite) ;
…
…
…
…
… ...
…
return EXIT_SUCCESS }
void traite(int s) { ….
….
exit ; }
Signal s
termine le processus
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture des signaux non BSD
Dans le traitement classique et ancien des signaux la réception d'un signal provoque :
L'exécution de la fonction associée au signal
Le retour à la fonction standard
SIG_DFL associée au signal qui est en général arrêt du processus
Si l'on veut traiter plusieurs occurrences du même signal il est nécessaire de ré-associer la fonction au signal lors de son traitement
L'arrivée de plusieurs signaux peut inter-
rompre la fonction de traitement du signal ce qui pose des problèmes de réentrance
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture des signaux non BSD
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
# define NSIG _NSIG
/* pour compatibilité avec le prototype */
typedef void (*sighandler_t)(int);
void traite_signal ( int no_sig ){
fprintf(stderr,"Le signal %d a été reçu\n", no_sig);
return;
}
Numéro de signal max + 1
A 2015, AG 2021A 2015, AG 2021
La fonction pause met le processus en sommeil jusqu'à l'arrivée d'un signal et
retourne -1
après son traitement Communication
Comm. Inter.
Capture des signaux non BSD
int main( int narg, char ** arg, char ** env){
int i;
sighandler_t tsig;
/* tentative de capture de tous les signaux */
fprintf(stderr,"Valeur de NSIG : %d\n", NSIG);
for ( i=1; i<= NSIG; i++){
tsig=signal(i, traite_signal);
if ( tsig == SIG_ERR){
fprintf(stderr,"Signal no %d non traité\n",i);
perror("Traitement signal");
} else
fprintf(stderr,"Signal no %d traité\n",i);
} for (;;){
i=pause();
if ( i == -1 )
fprintf(stderr,"Un signal à été reçu et traité\n");
}
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Ces signaux ne peuvent être
traités : 9,19
Capture des signaux non BSD
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Ces signaux ne peuvent être
traités : 32,33
33 est le premier signal
temps réel 64 le dernier
Capture des signaux non BSD
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
64 est le dernier signal temps-réel
Le fenêtre a été redimensionnée 2 fois sigwinch est Ignoré la 2ème fois
^ C la première fois le signal est traité et retourne à son traitement standard
arrêt
^ C la deuxième fois arrête le programme
Capture des signaux non BSD
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture des signaux BSD
La réception d'un signal ne restaure pas l'action associé au signal au traitement par défaut
Plusieurs signaux identiques peuvent donc donc être traités par le processus sans ré- associer au signal la fonction de traitement Lors du traitement du signal les signaux sont bloqués évitant d'avoir à écrire une fonction de traitement ré-entrante
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture des signaux BSD
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void traite_signal ( int no_sig ){
fprintf(stderr,"Le signal %d a été reçu\n", no_sig);
return;
}
int main( int narg, char ** arg, char ** env){
int i;
sighandler_t tsig;
/* tentative de capture de tous les signaux */
fprintf(stderr,"Mon PID : %d\n", getpid());
fprintf(stderr,"Valeur de NSIG : %d\n", NSIG);
for ( i=1; i<= NSIG; i++){
tsig=signal(i, traite_signal);
Définition de sighandler_t Traitement signaux « à la BSD »
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Fenêtre d’exécution
Plusieurs ^c au clavier n'arrête pas le processus
SIGHUP
SIGTERM SIGINT
SIGSTOP = ^Z au clavier Reprise avec fg
le shell envoie SIGCONT SIGSTOP
SIGCONT
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
signaux au processus
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
processus fils
La mise en attente d'un père sur la fin de ces processus fils est souvent pénalisante pour l'exécution du processus père
Une programmation véritablement parallèle le père et le(s) fils exécutant chacun une
tâche suppose que le père puisse s'exécuter sans se soucier de la fin de son processus fils et être informé par le système que ce fils s'est terminé
Le signal SIGCHLD, ignoré par défaut, est envoyé au processus père lorsqu'un de ces processus fils se termine
A 2015, AG 2021A 2015, AG 2021
Communication
Comm. Inter.
signal SIGCHLD
Ce programme créé n processus, n passé en paramètre sur la ligne de commande
Chaque processus fils s'endort pendant p secondes, p étant son numéro d'ordre puis se termine
Le processus père exécute une boucle vide interrompu régulièrement par la terminaison des ses fils.
Cette boucle se termine lorsque tous ses fils se sont terminés
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture de SIGCHLD
#define _GNU_SOURCE
#define _BSD_SOURCE
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int fils_max=0;
void fin_fils ( int no_sig ){
int status, fils;
fils_max++;
fils=wait(&status);
if ( WIFEXITED(status) )
fprintf(stderr,"Le processus %d s'est terminé normalement\n", fils);
else
fprintf(stderr,"Le processus %d s'est terminé anormalement\n", fils);
return;
}
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture de SIGCHLD
int main( int narg, char ** arg, char ** env){
int i, fils, max;
sighandler_t tsig;
tsig=signal(SIGCHLD, fin_fils);
if ( tsig == SIG_ERR){
perror("Traitement signal"); return EXIT_FAILURE;
}
max = atoi(*(arg+1));
fils=-1;
for (i=1; i <= max && fils !=0 ; i++){
fils = fork();
switch (fils) {
case -1 : perror("Echec de fork");
break;
case 0 :
fprintf(stderr,"Le processus %d\n", getpid());
sleep(i);
return EXIT_SUCCESS;
} }
while ( fils_max != max ) ; /* boucle vide */
fprintf(stderr,"Mes fils se sont terminés\n");
return EXIT_SUCCESS;
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture de SIGCHLD
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture de SIGCHLD : remarques
Lors du traitement d'un signal l'arrivée d'un autre signal est bloqué par le système tant que le gestionnaire n'est pas terminé
Le signal bloqué est mis en attente jusqu'à la fin de l'exécution du gestionnaire
Un seul signal est mémorisé
L'arrivée de 2 signaux identiques pendant le traitement du signal ne déclenchera pas 2 exécutions du gestionnaire
L'exemple présenté fonctionne correctement car chaque processus s'endort un temps
différent
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture de SIGCHLD : remarques
La partie père suivante est plus réaliste Chaque fils exécute son propre code Le processus père exécute le sien, interrompu par le signal SIGCHILD
Quand sa partie de code est finie il attend ses éventuels fils dans la boucle while
terminale
A 2015, AG 2021A 2015, AG 2021
Communication Comm. Inter.
Capture de SIGCHLD
for (i=1; i <= max && fils !=0 ; i++){
fils = fork();
switch (fils) {
case -1 : perror("Echec de fork"); break;
case 0 :
fprintf(stderr,"Le processus %d\n", getpid());
return EXIT_SUCCESS;
}
} /* attente des fils dont le signal sigchild a ete perdu */
tsig=signal(SIGCHLD, SIG_IGN);
if ( tsig == SIG_ERR){
perror("Traitement signal");
return EXIT_FAILURE;
}
fils=wait((int*) NULL);
while ( fils != -1 ){
fils=wait((int*) NULL);
}
fprintf(stderr,"Mes fils se sont terminés\n");
return EXIT_SUCCESS;
}