Delve into PHP's multi-process programming method _php Skills

Source: Internet
Author: User
Tags php script

Creation of child processes
the general process of the subroutine is:

<?php
$pid = Pcntl_fork ();
if ($pid = = 1) {
     //Create Failure
     die (' could not fork ');
}
else{
    if ($pid) {
        //the code to write from here is the exit of the parent process
        ("parent!");
    }
    else{
        //subprocess code, in order to prevent the continuous activation of the child process caused by the exhaustion of the system resources, the general process code after the completion of the run, add exit to ensure that the child process normal exit.
        exit ("Child");
    }
? >

Code above if the child process is created successfully, the system has 2 processes, one for the parent process and one for the subprocess, and the child process ID number is $pid. When the system runs to $pid = Pcntl_fork (), branches in this place, and the parent-child process starts to run its own program code. The result of the code running is parent and child, it's strange, why is it that an if and else mutex code output the result? In fact, as mentioned above, when the code is pcntl_fork, a parent runs, and a subprocess runs the child. The code results show the parent and child. As to who is the first after the problem, it depends on the allocation of system resources.

If you need more than one process to process the data, you can screwdriver the process according to the number of data, such as a 1000-piece process. It's OK to use a For loop.

 #如果获得的总数小于或等于0, wait 60 seconds, and exit
  if ($count <= 0) 
  {sleep
    );
    Exit;
  }
  #如果大于1000, calculate the number of processes needed
  if ($count > 1000)
  {
    $cycleSize = ceil ($count/1000);
  }
  else
  {
    $cycleSize = 1;
  }
  
  for ($i =0; $i < $cycleSize; $i + +)
  {
    $pid  = Pcntl_fork ();
    if ($pid = = 1)
    {break
      ;
    }
    else
    {
      if ($pid)
      {
        #父进程获得子进程的pid, stored in array
        $pidArr [] = $pid;
      }
      else
      {
        //start sending, after the child process finishes its own task, exit.
          exit;
  }
  
  }} while (count ($PIDARR) > 0)
  {
    $myId  = Pcntl_waitpid ( -1, $status, Wnohang);
    foreach ($pidArr as $key => $pid)
    {
      if ($myId = = $pid) unset ($PIDARR [$key]);
    }
  

Then use crontab to make this PHP program automatically run at intervals.

Of course, the sample code is relatively simple, but also need to consider how to prevent multiple child processes from executing to the same data or the current process processing data is not complete, crontab began to execute the PHP file to enable the new process, and so on.


PHP Multi-Process Implementation method
The following is a systematic way to organize the implementation of the PHP multi-process:

1. Direct mode

Pcntl_fork () creates a process in which the parent process returns a value that is the PID of the child process, and the return value of the subprocess is 0,-1 to indicate that the creation process failed. It's very similar to C.

Test Script test.php

<?php
  //Example of multiple processes
  date_default_timezone_set (' asia/chongqing ');
  echo "Parent start, pid", Getmypid (), "\ n";
  Beep ();
  For ($i =0 $i <3; + + $i) {
     $pid = Pcntl_fork ();
      if ($pid = = 1) {
         die ("Cannot fork");
     } else if ($pid > 0) {
         echo "parent continue \ n";
         For ($k =0 $k <2; + + $k) {
           beep ();
        }
     } else if ($pid = = 0) {
         echo "child start, pid", Getmypid (), "\ n" ;
         For ($j =0 $j <5; + + $j) {
           beep ();
        }
         Exit;
     }
  }
  function beep () {
      echo getmypid (), "T", date (' y-m-d h:i:s ', Time ()), "\ n";
     Sleep (1);
  }
? >

Run with command line

#php-F test.php

Output results

Parent start, PID 1793
1793  2013-01-14 15:04:17
parent continue
1793 2013-01-14 Child start, PID 1794
1794  2013-01-14 15:04:18
1794  2013-01-14 15:04:19 1793 2013-01-14 15:04:19
1794  2013-01-14 15:04:20
parent Continue
1793  2013-01-14 15:04:20 Child
Start, PID 1795
1795  2013-01-14 15:04:20
17931794        2013-01-14 15:04:212013-01-14 15:04:21

1795  2013-01-14 15:04:21
1794  2013-01-14 15:04:22
1795  2013-01-14 15:04:22
parent Continue
1793  2013-01-14 15:04:22 child
start, PID 1796
1796  2013-01-14 15:04:22
1793  2013-01-14 15:04:23
1796  2013-01-14 15:04:23
1795  2013-01-14 15:04:23
1795  2013-01-14 15:04:24
1796  2013-01-14
15:04:24 1796 2013-01-14 15:04:25 1796  2013-01-14 15:04:26

From there, 3 child processes are created and run in parallel with the parent process. One line of formatting is different from the other,
17931794 2013-01-14 15:04:212013-01-14 15:04:21
The conflict was caused by two processes writing at the same time.


2. Blocking mode

In a direct way, the parent process creates a subprocess and does not wait for the child process to end, but continues to run. There seems to be no problem here. If the PHP script does not end automatically after running, but resides in memory, it can cause the child process to be unable to reclaim the problem. Which is the zombie process. You can wait for the process to end through the Pcntl_wai () method, and then recycle the process that has ended.
Change the test script to:

$pid = Pcntl_fork ();
if ($pid = = 1) {
  ...
} else if ($pid > 0) {
   echo "parent continue \ n";
   Pcntl_wait ($status);
   For ($k =0 $k <2; + + $k) {
     beep ();
  }
} else if ($pid = = 0) {
   ...
}

Run with command line

#php-F test.php

Output results

Parent start, PID 1807
1807  2013-01-14 15:20:05
parent Continue child
start, PID 1808
1808  2013-01-14 15:20:06
1808  2013-01-14 15:20:07
1808 2013-01-14 15:20:08
1808  2013-01-14 15:20:09
1808  2013-01-14 15:20:10
1807  2013-01-14 15:20:11
1807  2013-01-14 15:20:12
parent Continue child
start, PID 1809
1809  2013-01-14 15:20:13
1809  2013-01-14 15:20:14
1809  2013-01-14 15:20:15
1809  2013-01-14 15:20:16
1809  2013-01-14 15:20:17
1807  2013-01-14 15:20:18
1807  2013-01-14 15:20:19 child
start, PID 1810
1810  2013-01-14 15:20:20
Parent Continue
1810  2013-01-14 15:20:21
1810  2013-01-14 15:20:22
1810  2013-01-14 15:20:23
1810  2013-01-14
15:20:24 1807 2013-01-14 15:20:25 1807  2013-01-14 15:20:26

The parent process blocks itself at pcntl_wait () and waits for the subprocess to run until it is finished.


3. Non-blocking mode

Blocking mode loses the parallelism of multiple processes. There is also a way to reclaim both the finished subprocess and the parallel. This is the non-blocking way.
To modify a script:

<?php//Example of multiple processes Date_default_timezone_set (' asia/chongqing ');
  DECLARE (ticks = 1);
  Pcntl_signal (SIGCHLD, "garbage");
  echo "Parent start, pid", Getmypid (), "\ n";
  Beep ();
      For ($i =0 $i <3; + + $i) {$pid = Pcntl_fork ();
     if ($pid = = 1) {die ("Cannot fork");
         else if ($pid > 0) {echo "parent continue \ n";
        for ($k =0; $k <2; + + $k) {beep ();
         else if ($pid = = 0) {echo "Child start, pid", Getmypid (), "\ n";
        for ($j =0; $j <5; + + $j) {beep ();
     } exit (0);
  }//Parent while (1) {//does something else sleep (5);
      
      }//* * * function garbage ($signal) {echo "SiGNeL $signal received\n";
     while ($pid = Pcntl_waitpid ( -1, $status, Wnohang)) > 0) {echo "\ t child end PID $pid, status $status \ n"; The function beep () {echo getmypid (), "\ T", Date (' y-m-d h:i:s ', Time ()),"\ n";
  Sleep (1);
 }?>

Run with command line

#php-F test.php &

Output results

 parent start, PID 2066 2066 2013-01-14 16:45:34 parent continue 2066 2013-01-14 16:45 : Child start, PID 2067 2067 2013-01-14 16:45:35 20662067 2013-01-14 16:45:362013-01-14 16:45:36 2067 2013-01- 16:45:37 parent Continue 2066 2013-01-14 16:45:37 child start, PID 2068 2068 2013-01-14 16:45:37 2067 2013-01-14 16:
45:38 2068 2013-01-14 16:45:38 2066 2013-01-14 16:45:38 parent Continue 2066 2013-01-14 16:45:40 child start, PID 2069 2069 2067 2013-01-14 16:45:40 2013-01-14 16:45:40 2068 2013-01-14 16:45:40 2066 2013-01-14 16:45:41 2069 2013-01-14 1 6:45:41 2068 2013-01-14 16:45:41 SiGNeL received child end PID 2067, status 0 2069 2013-01-14 16:45:42 2068 201
3-01-14 16:45:42 2069 2013-01-14 16:45:43 SiGNeL-Received child end PID 2068, status 0 2069 2013-01-14 16:45:44 SiGNeL received child end PID 2069, status 0 

Multiple processes run in parallel and run for about 10 seconds with Ps-ef | grep PHP View the running process with only one process
Lqling 2066 1388 0 16:45 pts/1 00:00:00 php-f t5.php
Is the parent process, and the child process is reclaimed.


Child process exit status

Pcntl_waitpid ( -1, $status, Wnohang) $status

Returns the end state of a child process


multi-threaded under Windows

Windows system does not support the PCNTL function, fortunately there is curl_multi_exec () This tool, using internal multithreading, access to multiple links, each link can serve as a task.

Writing Scripts test1.php

<?php date_default_timezone_set (' asia/chongqing ');
     $tasks = Array (' Http://localhost/feedbowl/t2.php?job=task1 ', ' Http://localhost/feedbowl/t2.php?job=task2 ',
  ' Http://localhost/feedbowl/t2.php?job=task3 ');
  $MH = Curl_multi_init ();
     foreach ($tasks as $i => $task) {$ch [$i] = Curl_init ();
     curl_setopt ($ch [$i], Curlopt_url, $task);
     curl_setopt ($ch [$i], Curlopt_returntransfer, 1);
  Curl_multi_add_handle ($MH, $ch [$i]);
  {$MRC = Curl_multi_exec ($MH, $active);} while ($MRC = = Curlm_call_multi_perform); while ($active && $MRC = = CURLM_OK) {if Curl_multi_select ($MH)!=-1) {do {$MRC = Curl_multi_exec ($m h, $active);
     while ($MRC = = Curlm_call_multi_perform); }//Completed, checkout result foreach ($tasks as $j => $task) {if (Curl_error ($ch [$j])) {echo Ta
     SK ${j} [$task] Error ", Curl_error ($ch [$j])," \ r \ n "; else {echo "task ${j} [$task] get: \ r \ n", Curl_multi_getcoNtent ($ch [$j]), "\ r \ n";
 }}?>

Writing Scripts test2.php

<?php
  date_default_timezone_set (' asia/chongqing ');
  echo "Child start, pid", Getmypid (), "\ r \ n";
  For ($i =0 $i <5; + + $i) {
     beep ();
  }
  Exit (0);
  function beep () {
    echo getmypid (), "T", date (' y-m-d h:i:s ', Time ()), "\ r \ n";
    Sleep (1);
  }
? >

Run with command line

#php-F test1.php &

Output results

Task 0 [Http://localhost/feedbowl/t2.php?job=task1] Get: Child
start, PID 5804
5804  2013-01-15 20:22:35
5804  2013-01-15 20:22:36
5804  2013-01-15 20:22:37
5804 2013-01-15 20:22:38 5804  2013-01-15 20:22:39

Task 1 [http://localhost/feedbowl/t2.php?job=task2] Get: Child
start, PID 5804
5804  2013-01-15 20:22:35
5804  2013-01-15
20:22:36 5804 2013-01-15 20:22:37 5804  2013-01-15 20:22:38
5804  2013-01-15 20:22:39

Task 2 [http://localhost/feedbowl/t2.php?job =TASK3] Get: Child
start, PID 5804
5804  2013-01-15 20:22:35
5804 2013-01-15 20:22:36 5804  2013-01-15 20:22:37
5804  2013-01-15 20:22:38
5804  2013-01-15 20:22:39

From the time you print, you can see that multiple tasks are running almost simultaneously.

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.