Analogue's Blog

home

Comment forker proprement en PHP ?

25 Aug 2009

Comment forker proprement en PHP ?

Pour un script particulier, j'ai eu besoin d'effectuer des traitements en parallèle en PHP: j'ai donc fait appel au fork. Le fait de forker permet à un programme de se dupliquer, en vue de réaliser un autre traitement, en même temps que le premier.

Le language PHP, destiné à priori au monde du web, ne s'est vu attribuer des méthodes de forking que tardivement, dans la version 4.1.0.

Le concept n'étant pas aisé à comprendre pour un développeur débutant en PHP, je vous livre un exemple très simple d'utilisation du fork: Un processus père lance 10 processus fils qui ont une durée de vie de 1 à 10 secondes. Puis le processus père se termine après la fin de vie du dernier de ses fils:


('NB_CHILDREN', 10); // Nombre d'enfants à forker

$a_pids = array(); // Tableau contenant les PIDs des fils

echo "Avant le premier fork\n";

for (
$i = 1; $i <= NB_CHILDREN; $i++)
{
 echo
"Je fork l'enfant n°$i\n";
 
$pid = pcntl_fork();
 if (
$pid === -1)
 {
  die(
"Impossible de forker\n");
 }
 elseif (
$pid)
 {
  echo
'Je suis le père, pid reçu: '. $pid ."\n";
  
$a_pids[] = $pid;
 }
 else
 {
  
sleep($i);
  echo
'Je suis un fils, pid reçu: '. $pid ."\n";
  exit;
 }
}

echo
"Le père attend la fin de ses fils...\n";

foreach (
$a_pids as $pid)
{
 if (
pcntl_waitpid($pid, $status) === -1)
 {
  die(
"Impossible d'attendre la fin d'un de mes fils\n");
 }
}

echo
"Tous les enfants ont terminé, je peux en finir =)\n";


Si vous tentez de lancer ce programme en ligne de commande, vous obtiendrez la sortie suivante:
analogue@plop:~$ php -f test-fork.php
Avant le premier fork
Je fork l'enfant n°1
Je suis le père, PID reçu: 8071
Je fork l'enfant n°2
Je suis le père, PID reçu: 8072
Je fork l'enfant n°3
Je suis le père, PID reçu: 8073
Je fork l'enfant n°4
Je suis le père, PID reçu: 8074
Je fork l'enfant n°5
Je suis le père, PID reçu: 8075
Je fork l'enfant n°6
Je suis le père, PID reçu: 8076
Je fork l'enfant n°7
Je suis le père, PID reçu: 8077
Je fork l'enfant n°8
Je suis le père, PID reçu: 8078
Je fork l'enfant n°9
Je suis le père, PID reçu: 8079
Je fork l'enfant n°10
Je suis le père, PID reçu: 8080
Le père attend la fin de ses fils...
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Je suis un fils, PID reçu: 0
Tous les enfants ont terminé, je peux en finir =)
analogue@plop:~$
A la place de la ligne sleep($i); exécutée par chaque fils, vous pouvez insérer le traitement de votre choix, qui sera exécuté en parallèle, par exemple un crawler ;)

Sachez enfin que les méthodes de contrôle de processus de PHP ne sont disponibles qu'en ligne de commande (PHP CLI). Si vous êtes sous Debian GNU/Linux ou Ubuntu, un simple apt-get install php-cli vous installera le binaire nécessaire.

Comments