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

Basics of PHP Process Communication: Signals

For signal communication, you can use kill -l to view the current signal types of the system.
For the detailed meaning of each signal, please refer to my article: https://www.oldtoolbag.com/article/106040.htm
When using signals, you can use php --To view the current version of PHP, decide on the method to be used for inter-process signal communication.

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

The use of the pcntl_signal_dispatch function requires PHP version (PHP 5 >= 5.3.0, PHP 7)

If the PHP version is less than5.3.Some large companies may be lower than this version. At this time, declare(ticks=1), meaning that every execution of a low-level instruction,
it will check whether the signal occurs. For a detailed introduction, please refer to https://www.oldtoolbag.com/article/48340.htm

The official explanation is as follows: Tick (clock cycle) is an event that occurs every N executable low-level statements in the declare code block. The value of N is specified in the directive section of declare as ticks=N.

Then what is a low-level statement? As shown in the following code:

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

Then this for loop contains three low-level instructions. Each time $i is output, it will check whether an event has occurred that has been registered. It can be imagined that this efficiency is relatively low. So if it is detected that the PHP version is greater than or equal to5.3 So, use pcntl_signal_dispatch to perform signal dispatch.

The master process registers some signal handling functions when it starts up.

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

Then bind the signal handler to the signal handling function:

//Install different signal handlers according to different signals
pcntl_signal(SIGINT, 'signalHandal');
pcntl_signal(SIGHUP, 'signalHandal');
pcntl_signal(SIGUSR1, 'signalHandla');

Listen to the signal in the child process, and if the signal occurs, call the pre-installed signal handling function

//Signal allocation.
pcntl_signal_dispatch($signal);

Let's organize our thoughts:
1Defining the function required to handle the events that cause the signal to occur
2Binding the signal and the signal handling function, known as signal installation.
3Signal listening or distribution, invoke the installed signal upon the occurrence of a signal.

Understanding the above signal concepts, let's take a look at a demo:

<?php
$parentpid = posix_getpid();
echo "parent progress pid:{$parentpid}\n";
//Define a signal handling function
function sighandler($signal) {
  if ($signal == SIGINT) {
    $pid = getmypid();
    exit("{$pid} process, Killed!".PHP_EOL);
  }
}
//php version < 5.3 . Check for the signal after each low-level instruction is executed. This is very inefficient.
//declare(ticks=1);
$child_list = [];
//Register a signal handler. When the signal is issued, call the defined function
pcntl_signal(SIGINT, 'sighandler');
for($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  if ($pid == 0) {
    //Child process
    while (true) {
      //Invoke the installed signal signal handler to check if there are any new signals waiting to be dispatched
      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;