PHP
многопроцессорная обработка
Поиск…
Многопроцессорная обработка с использованием встроенных функций вилки
Вы можете использовать встроенные функции для запуска процессов PHP в качестве вилок. Это самый простой способ добиться параллельной работы, если вам не нужны ваши потоки, чтобы разговаривать друг с другом.
Это позволяет вам ставить задачи с интенсивным временем (например, загрузку файла на другой сервер или отправку электронной почты) в другой поток, чтобы ваш сценарий загружался быстрее и мог использовать несколько ядер, но имейте в виду, что это не настоящая многопоточность, а ваш основной поток не будет знать, что делают дети.
Обратите внимание, что в Windows это приведет к появлению другой командной строки для каждой вилки, которую вы запускаете.
master.php
$cmd = "php worker.php 10";
if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') // for windows use popen and pclose
{
pclose(popen($cmd,"r"));
}
else //for unix systems use shell exec with "&" in the end
{
exec('bash -c "exec nohup setsid '.$cmd.' > /dev/null 2>&1 &"');
}
worker.php
//send emails, upload files, analyze logs, etc
$sleeptime = $argv[1];
sleep($sleeptime);
Создание дочернего процесса с использованием fork
PHP создал встроенную функцию pcntl_fork
для создания дочернего процесса. pcntl_fork
такой же, как fork
в unix. Он не принимает никаких параметров и возвращает целое число, которое может использоваться для дифференциации родительского и дочернего процессов. Рассмотрим следующий код для объяснения
<?php
// $pid is the PID of child
$pid = pcntl_fork();
if ($pid == -1) {
die('Error while creating child process');
} else if ($pid) {
// Parent process
} else {
// Child process
}
?>
Как вы можете видеть, -1
- это ошибка в fork, и ребенок не был создан. При создании дочернего процесса у нас есть два процесса, работающих с отдельным PID
.
Еще одно соображение здесь - zombie process
или defunct process
когда родительский процесс заканчивается перед дочерним процессом. Чтобы предотвратить процесс обработки детьми-зомби, просто добавьте pcntl_wait($status)
в конец родительского процесса.
pnctl_wait приостанавливает выполнение родительского процесса до выхода дочернего процесса.
Также стоит отметить, что zombie process
не может быть убит с использованием сигнала SIGKILL
.
Межпроцессного взаимодействия
Межпроцессная связь позволяет программистам общаться между различными процессами. Например, давайте рассмотрим, что нам нужно написать приложение PHP, которое может запускать команды bash и печатать выходные данные. Мы будем использовать proc_open
, который выполнит команду и вернет ресурс, с которым мы можем общаться. Следующий код показывает базовую реализацию, которая запускает pwd
в bash
из php
<?php
$descriptor = array(
0 => array("pipe", "r"), // pipe for stdin of child
1 => array("pipe", "w"), // pipe for stdout of child
);
$process = proc_open("bash", $descriptor, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], "pwd" . "\n");
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
}
?>
proc_open
запускает команду bash
с $descriptor
качестве спецификаций дескриптора. После этого мы используем is_resource
для проверки процесса. После этого мы можем начать взаимодействовать с дочерним процессом, используя $ pipe, который создается в соответствии со спецификациями дескриптора.
После этого мы можем просто использовать fwrite
для записи в stdin дочернего процесса. В этом случае pwd
следует за возвратом каретки. Наконец stream_get_contents
используется для чтения stdout дочернего процесса.
Всегда помните о закрытии дочернего процесса с помощью proc_close (), который завершает дочерний процесс и возвращает код состояния выхода.