Précédent Remonter Suivant

6  Attente de terminaison d'un processus fils

La primitive
    #include <sys/types.h>
    #include <sys/wait.h>

    pid_t wait (int *status) ;
suspend l'exécution du processus appelant jusqu'à ce qu'un de ses processus fils se termine. Si un processus fils s'est déjà terminé, wait() retourne le résultat immédiatement.

wait() retourne le pid du processus fils si le retour est dû à la terminaison d'un processus fils ; -1 en cas d'erreur.

Si status n'est pas un pointeur nul, le status du processus fils (valeur retournée par exit()) est mémorisé à l'emplacement pointé par status.

De manière plus précise : Ces informations peuvent être accédées facilement à l'aide des macros suivantes définies dans sys/wait.h. (Attention, ces macros utilisent le status, et non un pointeur sur ce status.) :
WIFEXITED (status)
renvoie vrai si le statut provient d'un processus fils qui s'est terminé normalement ;
WEXITSTATUS (status)
(si WIFEXITED (status) renvoie vrai) renvoie le code de retour du processus fils passé à _exit() ou exit() ou la valeur retournée par la fonction main() ;
WIFSIGNALED (status)
renvoie vrai si le statut provient d'un processus fils qui s'est terminé à cause de la réception d'un signal ;
WTERMSIG (status)
(si WIFSIGNALED (status) renvoie vrai) renvoie la valeur du signal qui a provoqué la terminaison du processus fils.
D'autres macros sont disponibles ; leur documentation est accessible par la commande man 2 wait.

Exemple
% cat status_fils.c 
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

main (void)
{
  pid_t pid ; 
  int status ;

  pid = fork () ;
  
  switch (pid) {
    case -1 :
      perror ("fork") ; 
      exit (1) ;
    case 0 : /* le fils */
      printf ("processus fils\n") ;
      exit (2) ;
    default : /* le pere */
      printf ("pere: a cree processus %d\n", pid) ;
      wait (&status) ;
      if (WIFEXITED (status))
        printf ("fils termine normalement: status = %d\n",
                WEXITSTATUS (status)) ;
      else
        printf ("fils termine anormalement\n") ;
  }
}

% ./status_fils
pere: a cree processus 907
processus fils
fils termine normalement: status = 2

Exercice 3   Donner un programme qui affiche, dans l'ordre, les entiers de 0 à 3 par 4 processus à partir de la structure suivante ;

for (i=0 ; i < 4 ; i++) {
  switch (fork ()) {
    case -1 : 
        ...
    case 0 : 
        ...
    default : 
        ...
  }  

Exercice 4  [Trifourche]   Écrire la fonction

  trifourche (void(*)(void), void(*)(void), void(*)(void)) ; 
Le processus exécutant trifourche (f1, f2, f3) engendre des processus exécutant respectivement les fonctions f1, f2, et f3, et attend la fin des processus engendrés pour terminer la fonction.

Cette fonction est par exemple utilisée dans le contexte suivant :

void fa (void)
{
  sleep (4) ; 
  printf ("Fonction fa executee par le processus %d\n", getpid ()) ;
}

void fb (void)
{
  sleep (2) ; 
  printf ("Fonction fb executee par le processus %d\n", getpid ()) ;
}

void fc (void)
{
  sleep (3) ; 
  printf ("Fonction fc executee par le processus %d\n", getpid ()) ;
}

int main (void) 
{
  trifourche (fa, fb, fc) ;
  printf ("Terminaison de main ()\n") ; 
}

Exercice 5  [Multifourche]   La fonction multifourche() généralise la fonction trifourche() précédente.

typedef int (*intint ) (int) ;

void multifourche (int n, intint f[]) ; 
Le type intint est défini comme « pointeur sur une fonction retournant d'entier à entier ». Les arguments de multifourche() sont un tableau de telles fonctions et la taille n de ce tableau. Chacune des fonctions est exécutée par un processus différent qui affiche aussi le valeur retournée par la fonction.

Exercice 6   Soit la commande sigma à deux arguments. sigma inf sup affiche la somme des entiers de inf à sup.

En remarquant que l'on peut calculer indépendamment å
i=a,b-a/2 i et åb-a/2+1, b i pour calculer sigma a b, développer une version de la commande sigma utilisant des processus.

Exercice 7   Soit le programme suivant compilé en un exécutable nommé partage :

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main (void)
{
  char buf [6] ;
  int fd ;
  
  fd = open ("foo", O_RDWR, 420) ;

  switch (fork ()) {
    case -1 :
      perror ("fork") ;
      exit (1) ;
    case 0 :
      printf ("%d caracteres ecrits\n", write (fd, "12345", 5)) ;
      break ;
    default :
      printf ("%d caracteres lus\n", read (fd, buf, 5)) ;
      buf [5] = '\0' ;
      printf ("Ligne lue : %s\n", buf) ;
      close (fd) ;
  }
}
Donner le résultat de la séquence de commandes Unix suivante :

  % echo ABCDEFGH > foo
  % ./partage
  % cat foo


Précédent Remonter Suivant