PHP
multi~~POS=TRUNC
Sök…
Multiprocessering med inbyggda gaffelfunktioner
Du kan använda inbyggda funktioner för att köra PHP-processer som gafflar. Detta är det enklaste sättet att uppnå parallellt arbete om du inte behöver dina trådar för att prata med varandra.
Detta gör att du kan lägga tidskrävande uppgifter (som att ladda upp en fil till en annan server eller skicka ett e-postmeddelande) till en annan tråd så att ditt skript laddas snabbare och kan använda flera kärnor men vara medveten om att detta inte är riktigt multiträdning och din huvudtråd inte kommer vet vad barnen gör upp till.
Observera att under Windows kommer detta att göra en ny kommandotolk till varje gaffel du startar.
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);
Skapa barnprocess med gaffel
PHP har inbyggd funktion pcntl_fork
för att skapa barnprocess. pcntl_fork
är samma som fork
i unix. Det tar inte in några parametrar och returnerar heltal som kan användas för att skilja mellan förälder- och barnprocess. Tänk på följande kod för att förklara
<?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
}
?>
Som du kan se -1
är ett fel i gaffeln och barnet skapades inte. När vi skapar barn har vi två processer som körs med separat PID
.
En annan övervägning här är en zombie process
eller defunct process
när förälderprocessen avslutas innan barnprocessen. För att förhindra en zombiebarnsprocess lägg bara till pcntl_wait($status)
i slutet av överordnadsprocessen.
pnctl_wait avbryter körning av överordnad process tills barnprocessen har avslutats.
Det är också värt att notera att zombie process
inte kan dödas med SIGKILL
signal.
Kommunikation mellan processer
Interprocesskommunikation gör det möjligt för programmerare att kommunicera mellan olika processer. Låt oss till exempel tänka på att vi måste skriva en PHP-applikation som kan köra bash-kommandon och skriva ut utdata. Vi kommer att använda proc_open
, som kommer att utföra kommandot och returnera en resurs som vi kan kommunicera med. Följande kod visar en grundläggande implementering som kör pwd
i bash
från 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
kör bash
kommando med $descriptor
som deskriptorsspecifikationer. Efter det använder vi is_resource
att validera processen. När det är gjort kan vi börja interagera med barnprocessen med $ -rör som genereras enligt beskrivarens specifikationer.
Efter det kan vi helt enkelt använda fwrite
att skriva till stdin of child process. I detta fall pwd
följt av vagn tillbaka. Slutligen används stream_get_contents
för att läsa stdout of child process.
Kom alltid ihåg att stänga barnprocessen genom att använda proc_close () som avslutar barnet och returnerar utgångsstatuskoden.