Maison  >  Article  >  développement back-end  >  Une étude préliminaire sur plusieurs processus en PHP7

Une étude préliminaire sur plusieurs processus en PHP7

藏色散人
藏色散人avant
2019-04-04 13:52:463496parcourir

Préparation

Nous savons tous que PHP s'exécute en un seul processus. La gestion de la multi-concurrence par PHP repose principalement sur le multi-processus du serveur ou PHP-FPM et du serveur. réutilisation de leurs processus, mais PHP L'implémentation de plusieurs processus est également d'une grande importance, en particulier lors du traitement de grandes quantités de données ou de l'exécution de processus démons DEMON en arrière-plan en mode Cli en arrière-plan.

Le multi-threading de PHP a également été mentionné, mais le problème du partage et de l'allocation des ressources multi-thread au sein du processus est difficile à résoudre. PHP possède également une extension multi-thread pthreads , mais elle est dite instable et nécessite que l'environnement soit thread-safe, elle n'est donc pas beaucoup utilisée.

Dans le passé, un grand maître du groupe PHP a dit un jour que si PHP en arrière-plan veut progresser, il doit éviter le multi-processus. Il se trouve que le processus démon de l'entreprise utilise également le multi-processus de PHP. processus, combiné avec les différents de Gu Ge Après avoir lu les informations et les manuels, j'ai enfin compris le multi-traitement et écrit une petite démo (implémentée sur un système Linux, je la résumerai dans cet article). S'il y a des erreurs ou des omissions, merci. vous de les avoir mentionnés.

Pour implémenter le multi-traitement en PHP, nous avons besoin de deux extensions pcntl et posix La méthode d'installation ne sera pas décrite ici.

En php, nous utilisons pcntl_fork() pour créer plusieurs processus (dans la programmation en langage C des systèmes *NIX, les processus existants génèrent de nouveaux processus en appelant la fonction fork). Le nouveau processus après le fork devient le processus enfant, le processus d'origine devient le processus parent et le processus enfant possède une copie du processus parent. Notez ici :

• Le processus enfant partage le segment de texte du programme avec le processus parent

• Le processus enfant a une copie de l'espace de données, du tas et de la pile du processus parent. Notez que c'est le cas. une copie, pas un partage

• Le processus parent et le processus enfant continueront à exécuter le code du programme après le fork

• Après le fork, que le processus parent ou le processus enfant s'exécute d'abord ne peut pas être confirmé, et cela dépend de la planification du système (dépend de la croyance)

Il est dit ici que le processus enfant a une copie de l'espace de données, du tas et de la pile du processus parent. dans la plupart des implémentations, il ne s'agit pas d'une véritable copie complète. Plus important encore, la technologie COW (Copy On Write) est utilisée pour économiser de l'espace de stockage. Pour faire simple, si ni le processus parent ni le processus enfant ne modifient ces données, ce tas et cette pile, alors le processus parent et le processus enfant partagent temporairement les mêmes données, tas et pile. Ce n'est que lorsque le processus parent ou le processus enfant tente de modifier les données, le tas et la pile qu'une opération de copie se produit. C'est ce qu'on appelle la copie sur écriture.

Après avoir appelé pcntl_fork(), la fonction renverra deux valeurs. Renvoie l'ID de processus du processus enfant dans le processus parent et renvoie le numéro 0 à l'intérieur du processus enfant lui-même. Étant donné que plusieurs processus ne peuvent pas s'exécuter correctement dans l'environnement Apache ou FPM, vous devez exécuter le code dans l'environnement php cli.

Créer un sous-processus

La création d'un sous-processus PHP est le début de plusieurs processus, nous avons besoin de la fonction pcntl_fork()

explication détaillée de la fonction fork

— Générer une branche (processus enfant) à la position actuelle du processus actuel. Une fois que cette fonction a créé un nouveau processus enfant, le processus enfant héritera du contexte actuel du processus parent et continuera à s'exécuter vers le bas depuis la fonction pcntl_fork()  comme le processus parent, sauf que la valeur de retour de pcntl_fork() obtenue est différente, nous pouvons donc distinguer le processus parent et le processus enfant en jugeant la valeur de retour, et le processus parent et le processus enfant peuvent être affectés à des traitements logiques différents. pcntl_fork()

Lorsque la fonction pcntl_fork() est exécutée avec succès, elle renvoie l'identifiant de processus (pid) du processus enfant dans le processus parent, car le pid du processus d'initialisation du processus initial du système est 1, le pid de. les processus suivants seront supérieurs à ce processus, nous pouvons donc confirmer que le processus actuel est le processus parent en jugeant que la valeur de retour de pcntl_fork() est supérieure à 1 dans le processus enfant, la valeur de retour de cette fonction sera ; une valeur fixe de 0. Nous pouvons également juger que la valeur de retour de pcntl_fork() est 0. Pour déterminer le processus enfant ; lorsque la fonction pcntl_fork() ne s'exécute pas, elle retournera -1 dans le processus parent, et bien sûr aucun processus enfant ne sera généré.

instance de processus fork

processus enfant fork

$ppid = posix_getpid();
$pid = pcntl_fork();
if ($pid == -1) {
    throw new Exception('fork child process fail');
} elseif ($pid > 0) {
    cli_set_process_title("我是父 process,pid is : {$ppid}.");
    sleep(30);
} else {
    $cpid = posix_getpid();
    cli_set_process_title("我是 {$ppid} 子的 process,我的 process pid is : {$cpid}.");
    sleep(30);
}

Description :

posix_getpid() : renvoie l'identifiant du processus actuel

cli_set_process_title('process name') : donne un nom fort au processus actuel.

En exécutant cet exemple, nous pouvons voir les deux processus PHP actuels.

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ ps aux|grep -v grep |grep 我
www      18026  0.5  1.2 204068 25772 pts/0    S+   14:08   0:00 我是父 process,pid is : 18026.
www      18027  0.0  0.3 204068  6640 pts/0    S+   14:08   0:00 我 18026 子的 process,我的 process pid is : 18027. 
Le premier morceau de code, après le démarrage du programme à partir de pcntl_fork(), le processus parent et le processus enfant continueront à exécuter le code :

$pid = pcntl_fork();
if( $pid > 0 ){
  echo "我是父亲".PHP_EOL;
} else if( 0 == $pid ) {
  echo "我是儿子".PHP_EOL;
} else {
  echo "fork失败".PHP_EOL;
} 
Résultat :

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 123.php
我是父亲
我是儿子
Le deuxième morceau de code est utilisé pour illustrer que le processus enfant possède une copie des données du processus parent, plutôt que de les partager :

// 初始化一个 number变量 数值为1
$number = 1;
$pid = pcntl_fork();
if ($pid > 0) {
    $number += 1;
    echo "我是父亲,number+1 : { $number }" . PHP_EOL;
} else if (0 == $pid) {
    $number += 2;
    echo "我是儿子,number+2 : { $number }" . PHP_EOL;
} else {
    echo "fork失败" . PHP_EOL;
}
Résultat

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer