Поиск…


Многопроцессорная обработка с использованием встроенных функций вилки

Вы можете использовать встроенные функции для запуска процессов 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 (), который завершает дочерний процесс и возвращает код состояния выхода.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow