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

PHP进程通信基础之信号

Comunicazione tramite segnali. È possibile visualizzare i tipi di segnali attualmente disponibili nel sistema con kill -l
Per dettagli su ciascun segnale, consultare questo mio articolo: https://it.oldtoolbag.com/article/106040.htm
Quando si utilizza un segnale, è possibile controllare la versione corrente di PHP tramite php --version. È stato deciso quale metodo utilizzare per la comunicazione tra processi.

[root@roverliang ipc]# php --version
PHP 5.6.24 (cli) (costruito: 15 ago 2016 19:14:02)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

E' necessario utilizzare la funzione pcntl_signal_dispatch per PHP versione (PHP 5 >= 5.3.0, PHP 7)

Se la versione di PHP è inferiore a 5.3, alcune grandi aziende potrebbero essere inferiori a questa versione. In questo caso, viene utilizzato declare(ticks=1), il che significa che ogni volta che viene eseguito un istruzione di basso livello,
verrà controllato se è apparso il segnale. Per ulteriori informazioni, vedere https://it.oldtoolbag.com/article/48340.htm

L'esplicazione ufficiale è la seguente: Tick (periodo di clock) è un evento che si verifica ogni volta che l'interprete esegue N istruzioni di basso livello contabili all'interno di un segmento declare. Il valore di N è specificato nella sezione directive di declare con ticks=N.

Allora cosa sono le istruzioni di basso livello? Come mostrato nel codice seguente:

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

Quindi questo ciclo for contiene tre istruzioni di basso livello. Ogni volta che viene outputto $i, viene controllato se è accaduto un evento registrato. Si può immaginare che l'efficienza sia relativamente bassa. Quindi se si rileva che la versione di PHP è maggiore o uguale a 5.3, si utilizza pcntl_signal_dispatch per effettuare la distribuzione dei segnali.

Il processo principale registra alcune funzioni di gestione dei segnali durante l'avvio.

/**
 * @param $signal segnale
 */
function signalHandal($signal)
{
  switch ($signal) {
    case SIGINT:
      //do something
      break;
    case SIGHUP:
      //do something
      break;
    default :
      //do something
      break;
  }
}

然后将信号处理器与信号处理函数绑定:

//根据不同的信号,安装不同的信号处理器
pcntl_signal(SIGINT, 'signalHandal');
pcntl_signal(SIGHUP, 'signalHandal');
pcntl_signal(SIGUSR1, 'signalHandla');

在子进程中监听信号,如果出现该信号,就调用预安装的信号处理函数

//分配信号。
pcntl_signal_dispatch($signal);

让我们整理一下思路:
1、定义信号发生时需要处理的函数
2、将信号与信号处理函数绑定,称为信号安装。
3、监听或分发信号,出现信号调用已安装的信号处理程序。

Comprendere bene i concetti di segnali sopra, vediamo un demo:

<?php
$parentpid = posix_getpid();
echo "Progresso del genitore pid:{$parentpid}\n";
//Definire una funzione gestore di segnali
function sighandler($signal) {
  if ($signal == SIGINT) {
    $pid = getmypid();
    exit("{$pid} processo, Ucciso!".PHP_EOL);
  }
}
//php version < 5.3 .Ogni volta che esegue un comando di basso livello, verifica se è stato emesso questo segnale. La perdita di efficienza è molto grande.
//declare(ticks=1);
$child_list = [];
//Registrare un gestore di segnali. Quando viene emesso questo segnale, viene chiamata la funzione definita
pcntl_signal(SIGINT, 'sighandler');
for($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  if ($pid == 0) {
    //Sottoprocédure
    while (true) {
      //Chiamare il gestore di segnali installato per verificare se ci sono nuovi segnali in attesa di dispatching
      pcntl_signal_dispatch();
      echo "Sono il figlio: ".getmypid(). " e sto eseguendo !".PHP_EOL;
      sleep(rand(1,3));
    }
  }
    $child_list[] = $pid;
  } else {
    die('fork fall!'.PHP_EOL);
  }
}
sleep(5);
foreach ($child_list as $key => $pid) {
  posix_kill($pid, SIGINT);
}
sleep(2);
echo "{$parentpid} genitore è finito".PHP_EOL;