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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow