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.
Simple example
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.
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 progress end! \n"); } else {$childList[$pid] = 1; } // wait for child process to finish pcntl_wait($status); echo "({$parentPid})main progress end!" ;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 queue A message queue is a queue stored in memory. The following code creates three producer children and two consumer children. These five processes will communicate via message queues.
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); Function consumer(){global $msgQueue; $pid = posix_getpid(); $repeatNum = 6; for ( $i = 1; $i <= $repeatNum; $i++) { $rel = msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message); echo "{$message} | consumer({$pid}) destroy \n"; $rand = rand (1, 3); sleep($rand); } } function createProgress($callback){ $pid = pcntl_fork(); If ($pid == -1) {exit("fork progress error! \n"); } else if ($pid == 0) {$pid = posix_getpid(); $callback(); exit("({$pid})child progress end! \n"); }else{return $pid; $I = 0; $I = 0; $i < 3; $i ++ ) { $pid = createProgress('producer'); $childList[$pid] = 1; echo "create producer child progress: {$pid} \n"; } // for ($I = 0; $i < 2; $i ++ ) { $pid = createProgress('consumer'); $childList[$pid] = 1; echo "create consumer child progress: {$pid} \n"; } // Wait for all child processes to finish while(! empty($childList)){ $childPid = pcntl_wait($status); if ($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.
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; $i++) {// acquire sem_acquire($signal); If ($shareMemory,SHARE_KEY) {$count = $get_var($shareMemory,SHARE_KEY); $count ++; shm_put_var($shareMemory,SHARE_KEY,$count); echo "({$pid}) count: {$count}\n"; $shareMemory,SHARE_KEY,0; $shareMemory,SHARE_KEY,0 echo "({$pid}) count: 0\n"; } // release sem_release($signal); $rand = rand (1, 3); sleep($rand); } } function createProgress($callback){ $pid = pcntl_fork(); If ($pid == -1) {exit("fork progress error! \n"); } else if ($pid == 0) {$pid = posix_getpid(); $callback(); exit("({$pid})child progress end! \n"); }else{return $pid; $I = 0; $I = 0; $i < 3; $i ++ ) { $pid = createProgress('producer'); $childList[$pid] = 1; echo "create producer child progress: {$pid} \n"; } // Wait for all child processes to finish while(! empty($childList)){ $childPid = pcntl_wait($status); if ($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.
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
The above content hopes to help you, more free PHP factory PDF, PHP advanced architecture video materials, PHP wonderful good article can be wechat search concerns: PHP open source community
2021 Jinsanyin four big factory interview real questions collection, must see!
Four years of PHP technical articles collation collection – PHP framework
A collection of four years’ worth of PHP technical articles – Microservices Architecture
Distributed Architecture is a four-year collection of PHP technical articles
Four years of PHP technical essays – High Concurrency scenarios
Four years of elite PHP technical article collation collection – database