One, the introduction

A process is a running activity of a program with independent functions about a set of data. In other words, the basic unit of a program when the system schedules multiple cpus. Processes are not a foreign concept to most languages, and PHP, “the best language in the world,” is certainly an exception.

Second, the environment

Processes in PHP are done as extensions. With these extensions, we can easily complete a sequence of actions for the process.

  • PCNTL extension: The main process extension, the completion process is created in the wait operation.
  • Posix extension: Complete the COMMON POSIX compatible API, such as obtaining process ID, killing process, etc.
  • Sysvmsg extension: a message queue for interprocess communication in System V mode.
  • Sysvsem extension: To achieve system V semaphore.
  • Sysvshm extension: Implements system V shared memory.
  • Sockets extension: Implement socket communication.

These extensions are only available on Linux/MAC, not Windows. Finally, a PHP version of 5.5+ is recommended.

Related code: process-related code

3. Simple examples

A simple PHP multi-process example, in this example, a child process, a parent process. The child process outputs 5 times and exits the program.

$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $childList = array(); $pid = pcntl_fork(); If ($pid == -1) {exit("fork progress error! \n"); } else if ($pid == 0) {$pid = posix_getpid(); $repeatNum = 5; for ( $i = 1; $i <= $repeatnum; ="" $i++)="" {="" echo="" "({$pid})child="" progress="" is="" running! ="" {$i}="" \n"; = "" $rand = rand (1, 3);" " sleep($rand); ="" }="" exit("({$pid})child="" end! \n"); $childList [$pid]="1;" Pcntl_wait ($status); ="" "({$parentpid})main="" end!" ; <="" code="">Copy the code

Perfect, finally creating a child process, a parent process. Finished? No, the processes are independent of each other, without any intersection, and the scope of use is severely affected by the present. What to do? Interprogress communication.

4. Inter-process Communication (IPC)

In Linux, processes communicate in the following ways: message queues, semaphores, shared memory, signals, pipes, sockets.

1. Message queues

A message queue is a queue that is stored in memory. The following code creates three producer children and two consumer children. These five processes will communicate via message queues.

$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $childList = array(); / / create a message queue, and define the message types (similar to a database of library) $id = ftok (__FILE__, 'm'); $msgQueue = msg_get_queue($id); const MSG_TYPE = 1; Function producer(){global $msgQueue; $pid = posix_getpid(); $repeatNum = 5; for ( $i = 1; $i <= $repeatnum; ="" $i++)="" {="" $str="({$pid})progress create! {$i}" ; ="" msg_send($msgqueue,msg_type,$str); = "" $rand = rand (1, 3);" " sleep($rand); = = = ""}" "consumers" function "=" "consumer () {=" global "=" "$msgqueue; ="" $pid="posix_getpid();" $repeatnum="6;" for="" (="" $i="1;" <="$repeatNum;" $rel="msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message);" echo="" "{$message}="" |="" consumer({$pid})="" destroy="" \n"; = "" createprogress ($callback) {=" "if =" 1 ") = "" create failure =" "exit (" fork =" "progress =" "error! \n"); = = "" else" "($pid =" = "0) =" "child process executable program =" "$callback (); ="" exit("({$pid})child="" end! \n"); $pid =" $pid "; $pid =" $pid "; If ($I ="0 ") {$I ="0 "; 3; ="" ++="" )="" $childlist[$pid]="1;" "The create =" "producer =" child "=" "progress: =" "} {$pid = "" 2 =" writing process "2; ="" consumer="" wait for all child processes to finish ="" while(! empty($childlist)){="" $childpid="pcntl_wait($status);" ($childpid=""> 0){ unset($childList[$childPid]); } } echo "({$parentPid})main progress end! \n";Copy the code

Since the message queue to data is accessible by only one process, no additional locks or semaphores are required.

2. Semaphore and shared memory

Semaphore: an atomic operation provided by the system, a semaphore that only one process can operate at the same time. A semaphore acquired by a process must be released by the process.

Shared memory: a common memory area created by the system, which can be accessed by any process. Multiple processes can access this area at the same time. To ensure data consistency, you need to lock or semaphore this memory area.

Below, create multiple processes to modify the same value in memory.

$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $childList = array(); / / create the Shared memory, create a semaphore, define the Shared key $shm_id = ftok (__FILE__, 'm'); $sem_id = ftok(__FILE__,'s'); $shareMemory = shm_attach($shm_id); $signal = sem_get($sem_id); const SHARE_KEY = 1; // function producer(){global $shareMemory; global $signal; $pid = posix_getpid(); $repeatNum = 5; for ( $i = 1; $i <= $repeatnum; If ($i++)=" $i++ "; If = = "" "" (shm_has_var ($sharememory share_key)) {= "" has a value, add a =" "$count =" shm_get_var ($sharememory, share_key);" + +; ="" shm_put_var($sharememory,share_key,$count); ="" echo="" "({$pid})="" count:="" {$count}\n"; = ""} else {=" "has no value, initialization =" "shm_put_var ($sharememory, share_key, 0); ="" 0\n"; $signal ($signal); $signal ($signal); = "" $rand = rand (1, 3);" " sleep($rand); ="" function="" createprogress($callback){="" $pid="pcntl_fork();" (= "1") = "" create failure =" "exit (" fork =" "progress =" "error! \n"); = = "" else" "($pid =" = "0) =" "child process executable program =" "$callback (); ="" exit("({$pid})child="" end! \n"); $pid =" $pid "; If ($I ="0 ") {$I ="0 "; $i="" <="" 3; ="" ++="" )="" $childlist[$pid]="1;" "create="" producer="" child="" progress:="" {$pid}="" \n"; ="" wait for all child processes to finish ="" while(! empty($childlist)){="" $childpid="pcntl_wait($status);" ($childpid=""> 0){ unset($childList[$childPid]); $shareMemory; $shareMemory; $shareMemory; sem_remove($signal); echo "({$parentPid})main progress end! \n";Copy the code

3. The signal

A signal is a system call. The kill command is usually used to send a signal to a process. You can run kill -l in Liunx/MAC to check the signals. In the following example, the parent process waits 5 seconds to send sigINT to the child process. The child process captures the signal, and the signal handler function processes it.

$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; Function sighandler($signo) {$pid = posix_getpid(); echo "{$pid} progress,oh no ,I'm killed! \n"; exit(1); } $pid = pcntl_fork(); If ($pid == -1) {exit("fork progress error! \n"); $declare(ticks=10); $declare(ticks=10); $declare(ticks=10); pcntl_signal(SIGINT, "sighandler"); $pid = posix_getpid(); while(true){ echo "{$pid} child progress is running! \n"; sleep(1); } exit("({$pid})child progress end! \n"); }else{$childList[$pid] = 1; // After 5 seconds, the parent sends sigint to the child. posix_kill($pid,SIGINT); sleep(5); } echo "({$parentPid})main progress end! \n";Copy the code

4. Pipes (named pipes)

Pipe is a common means of multi-process communication, which can be divided into nameless pipe and named pipe. Nameless pipe can only be used for communication between processes with related relationship, while named pipe can be used for any process on the same host. Only named pipes are described here. In the following example, the child process writes data and the parent process reads data.

$pipe_path = '/data/test.pipe'; if(! file_exists($pipe_path)){ if(! posix_mkfifo($pipe_path,0664)){ exit("create pipe error!" ); } } $pid = pcntl_fork(); If ($pid = = 0) {/ / the child to the pipeline data written $file = fopen ($pipe_path, 'w'); while (true){ fwrite($file,'hello world'); $rand = rand (1, 3); sleep($rand); } exit('child end! '); $file = fopen($pipe_path,'r'); while (true){ $rel = fread($file,20); echo "{$rel}\n"; $rand = rand (1, 2); sleep($rand); }}Copy the code

5.socket

Socket is often referred to as socket programming. This needs to be added.