English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Fundamentos de la comunicación de procesos en PHP: señales

Usar comunicación de señales. Se puede usar kill -l para ver los tipos de señales del sistema actual.
El significado detallado de cada señal, consulte este artículo de mí: https://es.oldtoolbag.com/article/106040.htm
Al usar señales, se puede ver a través de php --Para ver la versión actual de PHP, se ha decidido utilizar este método para la comunicación de señales entre procesos.

[root@roverliang ipc]# php --versión
PHP 5.6.24 (cli) (construido: Ago 15 2016 19:14:02)
Derechos de autor (c) 1997-2016 El Grupo PHP
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

Para usar la función pcntl_signal_dispatch, se requiere PHP versión (PHP 5 >= 5.3.0, PHP 7)

Si la versión de PHP es menor que5.3.Algunas grandes empresas pueden estar por debajo de esta versión. En este momento, se utilizará declare(ticks=1), lo que significa que cada vez que se ejecuta una instrucción de bajo nivel,
se verificará si se ha producido la señal. Para una descripción detallada, consulte https://es.oldtoolbag.com/article/48340.htm

La explicación en el sitio web es la siguiente: Tick (ciclo de reloj) es un evento que ocurre cada vez que el intérprete ejecuta N instrucciones de bajo nivel en el código declare. El valor de N se especifica en la sección directive de declare con ticks=N.

Entonces, ¿qué son las instrucciones de bajo nivel? Véase el siguiente código:

  for ($i = 0; $i < 3; $i++) {
    echo $i.PHP_EOL;
  }

Entonces, este bucle for contiene tres instrucciones de bajo nivel. Cada vez que se salida una $i, se verifica si se produjo algún evento registrado, lo que es可想而知, la eficiencia es bastante baja. Por lo tanto, si se detecta que su PHP es mayor o igual que5.3 。Entonces, se utiliza pcntl_singal_dispath para realizar la distribución de señales.

El proceso principal registra algunas funciones de manejo de señales en el momento del inicio.

/**
 * @param $signal Señal
 */
function signalHandal($signal)
{
  switch ($signal) {
    case SIGINT:
      //Hacer algo
      break;
    case SIGHUP:
      //Hacer algo
      break;
    default :
      //Hacer algo
      break;
  }
}

Luego, enlazar el procesador de señales con la función de procesamiento de señales:

//Instalar diferentes procesadores de señales según diferentes señales
pcntl_signal(SIGINT, 'signalHandal');
pcntl_signal(SIGHUP, 'signalHandal');
pcntl_signal(SIGUSR1, 'signalHandla');

Escuchar la señal en el subproceso, si ocurre esa señal, se llama a la función de manejo de señal preinstalada

//Asignar la señal.
pcntl_signal_dispatch($signal);

Organicemos un poco nuestras ideas:
1、Definir la función necesaria para manejar el evento que ocasiona la señal
2、Enlazar la señal con la función de procesamiento de señal, lo que se llama instalar la señal.
3、Escuchar o distribuir señales, se llama a la señal instalada cuando ocurre una señal.

Entendiendo bien el concepto de señal mencionado anteriormente, veamos un demo:

<?php
$parentpid = posix_getpid();
echo "progresso del padre pid:{$parentpid}\n";
//Definir una función de manejo de señales
function sighandler($signal) {
  if ($signal == SIGINT) {
    $pid = getmypid();
    exit("{$pid} proceso, Matado!".PHP_EOL);
  }
}
//php version < 5.3 . Cada vez que se ejecuta una instrucción de bajo nivel, se verifica si se ha producido la señal. La pérdida de eficiencia es muy grande.
//declare(ticks=1);
$child_list = [];
//Registrar un gestor de señales. Al emitirse la señal, se llama a la función definida
pcntl_signal(SIGINT, 'sighandler');
for($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  if ($pid == 0) {
    //Subproceso
    while (true) {
      //Llamar al gestor de señales instalado para detectar si hay nuevas señales esperando dispatching
      pcntl_signal_dispatch();
      echo "I am child: ".getmypid(). " and i am running !".PHP_EOL;
      sleep(rand(1,3));
    }
  }
    $child_list[] = $pid;
  } else {
    die('fork fail!'.PHP_EOL);
  }
}
sleep(5);
foreach ($child_list as $key => $pid) {
  posix_kill($pid, SIGINT);
}
sleep(2);
echo "{$parentpid} parent is end".PHP_EOL;
Te gustará