In this paper, we explain the Linux environment using PHP for concurrent task processing and how to use pipe to synchronize data between processes. It's easy to write, as a memo.
PHP Multi-process
Use the multi-process functionality with the PCNTL_XXX series functions. Note: Pcntl_xxx can only run in the PHP CLI (command line) environment, in the Web server environment, there will be unexpected results, please use it with caution!
Piping pipe
Pipelines are used to host communication data between abbreviations. To facilitate understanding, the pipeline can be likened to a file, process a writes the data to the pipe p, and then process B reads the data from the pipe p. PHP provides the same pipeline operations API as the API for manipulating files, except that the POSIX_MKFIFO function is used to create pipelines, and reads and writes are the same as file manipulation functions. Of course, you can use the file to simulate the pipeline directly, but you can't use the features of the pipeline.
Zombie Process
At the end of the child process, the parent process does not wait for it (by calling wait or Waitpid), and the child process does not release all resources after the end (wasted!). ), this process is called the zombie process, he stored the child process at the end of the relevant data, if the zombie process too much, will occupy a lot of system resources (such as memory), affecting the performance of the machine.
Code
/** * This was a demo for PHP fork and pipe usage. Fork use * to-create child process and pipe are used to sychoroize * the child process and its main process. * @author Bourneli * @date: 2012-7-6 */define ("PC", 10); Number of processes define ("to", 4); Timeout define ("TS", 4); Event span for simulating task delay if (!function_exists (' pcntl_fork ')) {die ("Pcntl_fork not existing"); }//Create Pipeline $sPipePath = "My_pipe." Posix_getpid (); if (!posix_mkfifo ($sPipePath, 0666)) {die ("Create pipe {$sPipePath} error"); }//Simulation task concurrent for ($i = 0; $i < PC; + + $i) {$nPID = Pcntl_fork ();//create sub-process if ($nPID = = 0) {// Child process Sleep (rand (1,TS)); Analog Delay $oW = fopen ($sPipePath, ' w '); Fwrite ($oW, $i. " \ n "); The current task finishes processing, writing data fclose ($oW) in the pipeline; Exit (0); Exit after execution}//parent process $oR = fopen ($sPipePath, ' R '); Stream_set_blocking ($oR, FALSE); Set the pipe to non-clogging to accommodate the timeout mechanism $sData = '; Data in the storage pipeline $nLine = 0; $nStart = time (); while ($nLine &Lt PC && (Time ()-$nStart) < to) {$sLine = Fread ($oR, 1024); if (empty ($sLine)) {continue; } echo "Current line: {$sLine}\n"; Used to analyze how many tasks have been processed by ' \ n ' to identify foreach (Str_split ($sLine) as $c) {if ("\ n" = = $c) {+ + $nLine; }} $sData. = $sLine; } echo "Final line count: $nLine \ n"; Fclose ($oR); Unlink ($sPipePath); Delete pipeline, has no effect//wait for the child process to complete, to avoid the zombie process $n = 0; while ($n < PC) {$nStatus =-1; $nPID = pcntl_wait ($nStatus, Wnohang); if ($nPID > 0) {echo "{$nPID} exit\n"; + + $n; }}//Verify the results, primarily to see if each task is completed $arr 2 = array (); foreach (Explode ("\ n", $sData) as $i) {//Trim all if (is_numeric (Trim ($i))) {Array_push ($arr 2, $i); }} $arr 2 = Array_unique ($arr 2); if (count ($arr 2) = = PC) {echo ' OK '; } else {echo "error count". Count ($arr 2). "\ n"; Var_dump ($arr 2); }