PHP is written in C, so it operates much like THE underlying API of the system. Like most languages, PHP processes communicate in the following ways: message queues, pipes, shared memory, sockets, and signals. This article is to sort out these communication methods:
PIPE communication PIPE
Pipes are used to carry communication data between abbreviations. For ease of understanding, A pipe can be likened to A file, where process A writes data to pipe P, and process B reads data from pipe P. PHP provides the same API for pipe manipulation as for file manipulation, except that the posix_mkFIFO function is used to create pipes. The read and write operations are the same as the file manipulation functions. Of course, you could just use a file to emulate a pipe, but you wouldn’t be able to use the features of a pipe.
The idea behind pipe communication is to first create a pipe, then the child process writes to the pipe, and the parent process reads from the pipe, so that the parent and child processes can communicate directly.
<? $pipePath = "pipe"; if( ! file_exists( $pipePath ) ){ if( ! posix_mkfifo( $pipePath, 0666) ){ exit('make pipe false! ' . PHP_EOL); }} // create process, child process writes pipe, parent process reads pipe // create child process through pcntl_fork function. The pcntl_fork function is special in that it returns multiple values at once. // In the parent process: it returns the child process ID which is greater than 0. // In the child process, it returns 0. If -1 is returned, the process failed to be created. $pid = pcntl_fork(); If ($pid == 0){$file = fopen($pPATH, 'w'); fwrite( $file, 'hello world'); sleep(1); exit; $file = fopen($pipePath, 'r'); // When reading is not blocking, the parent process does not wait to read, and returns immediately when there is no message in the pipe. // stream_set_blocking( $file, False); echo fread( $file, 20) . PHP_EOL; pcntl_wait($status); // Recycle child process}Copy the code
The message queue
A message queue is a queue data structure that is stored in memory.
<? $parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $childList = array(); $id = ftok(__FILE__, 'm'); $msgQueue = msg_get_queue($id); const MSG_TYEP = 1; Function producer() {global $msgQueue; $pid = posix_getpid(); $repeatNum = 5; for ($i = 0; $i <= $repeatNum; $i++) { $str = "({$pid}) progress create! {$i}"; msg_send($msgQueue, MSG_TYEP, $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_TYEP, $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 cluster error\n"); } elseIf ($pid == 0) {$pid = posix_getpid(); $callback(); exit("({$pid})child progress end! \n"); } else {return $pid; } } for ($i = 0; $i < 3; $i++) { $pid = createProgress('producer'); $childList[$pid] = 1; echo "create producer progresses: {$pid}\n"; } for ($i = 0; $i < 2; $i++) { $pid = createProgress('consumer'); $childList[$pid] = 1; echo "create consumer progresses: {$pid}\n"; } while (! empty($childList)) { $childPid = pcntl_wait($status); if ($childPid > 0) { unset($childList[$childPid]); } } echo "({$parentPid})main progress end! \n";Copy the code
Running results:
create producer progresses: 21432
create producer progresses: 21433
create producer progresses: 21434
create consumer progresses: 21435
(21426) progress create! 2 | consumer(21435) destroy
(21424) progress create! 1 | consumer(21436) destroy
create consumer progresses: 21436
(21426) progress create! 3 | consumer(21436) destroy
(21426) progress create! 4 | consumer(21435) destroy
(21425) progress create! 3 | consumer(21436) destroy
(21424) progress create! 2 | consumer(21435) destroy
(21426) progress create! 5 | consumer(21435) destroy
(21424) progress create! 3 | consumer(21436) destroy
(21433)child progress end!
(21425) progress create! 4 | consumer(21435) destroy
(21424) progress create! 4 | consumer(21436) destroy
(21434)child progress end!
(21424) progress create! 5 | consumer(21435) destroy
(21425) progress create! 5 | consumer(21436) destroy
(21432)child progress end!
(21435)child progress end!
(21436)child progress end!
(21431)main progress end!
Copy the code
Semaphores and shared memory
<? php $parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $shm_id = ftok(__FILE__, 'm'); $shm_id = ftok(__FILE__, 'm') $shm_id = ftok(__FILE__, 's'); $shareMemory = shm_ATTACH ($shm_id); $signal = sem_get($shm_id); const SHARE_KEY = 1; // function producer() {global $shareMemory; global $signal; $pid = posix_getpid(); $repeatNum = 5; for ($i = 1; $i <= $repeatNum; $i++) {// acquire semaphore - block the process until the semaphore is acquired by [key] sem_acquire($signal); If ($shareMemory, SHARE_KEY) {$count = shm_get_var($shareMemory, SHARE_KEY); 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); } } function createProgress($callback) { $pid = pcntl_fork(); If ($pid == -1) {exit("fork progress error! \n"); } elseIf ($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 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
Results: Use semaphore to realize the locking mechanism of shared memory
parent progress pid:31720
create producer child progress: 31721
create producer child progress: 31722
(31721) count: 0
(31721) count: 1
(31721) count: 2
(31721) count: 3
(31721) count: 4
(31721) child progress end!
create producer child progress: 31723
(31722) count: 5
(31722) count: 6
(31722) count: 7
(31722) count: 8
(31722) count: 9
(31722) child progress end!
(31723) count: 10
(31723) count: 11
(31723) count: 12
(31723) count: 13
(31723) count: 14
(31723) child progress end!
(31720) main progress end!
Copy the code
Without the lock
Warning: sem_release(): 4357894312 (key 0 x73048925 SysV semaphore) is not currently acquired in/Users/easyboom/WWW/example/semaphore and Shared memory. PHP on line 38Copy the code