PHP
multiprocessing
Ricerca…
Multiprocessing utilizzando le funzioni di fork integrate
È possibile utilizzare le funzioni integrate per eseguire i processi PHP come fork. Questo è il modo più semplice per ottenere un lavoro parallelo se non hai bisogno che i tuoi thread parlino tra loro.
Ciò consente di inserire attività a tempo elevato (come il caricamento di un file su un altro server o l'invio di un messaggio di posta elettronica) su un altro thread in modo che lo script venga caricato più rapidamente e possa utilizzare più core, ma si tenga presente che non si tratta di vero multithreading e il thread principale non sarà sapere cosa stanno facendo i bambini.
Nota che sotto Windows questo farà apparire un altro prompt dei comandi per ogni fork che avvii.
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);
Creazione di processi figlio tramite fork
PHP ha costruito in funzione pcntl_fork
per la creazione del processo figlio. pcntl_fork
è uguale a fork
in unix. Non contiene alcun parametro e restituisce numeri interi che possono essere utilizzati per differenziare tra processo padre e figlio. Si consideri il seguente codice per la spiegazione
<?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
}
?>
Come puoi vedere -1
è un errore nel fork e il bambino non è stato creato. Alla creazione di child, abbiamo due processi in esecuzione con PID
separati.
Un'altra considerazione qui è un zombie process
o un zombie process
defunct process
quando il processo genitore termina prima del processo figlio. Per evitare che i bambini zombi pcntl_wait($status)
semplicemente aggiungi pcntl_wait($status)
alla fine del processo genitore.
pnctl_wait sospende l'esecuzione del processo genitore fino all'uscita dal processo figlio.
Vale anche la pena notare che il zombie process
non può essere ucciso usando il segnale SIGKILL
.
Comunicazione tra processi
La comunicazione tra processi consente ai programmatori di comunicare tra diversi processi. Ad esempio, consideriamo la necessità di scrivere un'applicazione PHP in grado di eseguire comandi bash e stampare l'output. Useremo proc_open
, che eseguirà il comando e restituirà una risorsa con cui possiamo comunicare. Il codice seguente mostra un'implementazione di base che esegue pwd
in bash
da 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
esegue il comando bash
con $descriptor
come specifiche del descrittore. Successivamente utilizziamo is_resource
per convalidare il processo. Una volta terminato, possiamo iniziare a interagire con il processo figlio usando $ pipe che viene generato secondo le specifiche del descrittore.
Successivamente, possiamo semplicemente usare fwrite
per scrivere su stdin del processo figlio. In questo caso pwd
seguito dal ritorno a capo. Infine stream_get_contents
è usato per leggere lo stdout del processo figlio.
Ricordarsi sempre di chiudere il processo figlio utilizzando proc_close () che interromperà il figlio e restituirà il codice di stato di uscita.