本文实例讲述了PHP共享内存用法。分享给大家供大家参考,具体如下:
共享内存主要用于进程间通信
php中的共享内存有两套扩展可以实现
1、shmop 编译时需要开启 --enable-shmop 参数
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
$shm_key = ftok ( __FILE__ , 't' ); /** 开辟一块共享内存 int $key , string $flags , int $mode , int $size $flags: a:访问只读内存段 c:创建一个新内存段,或者如果该内存段已存在,尝试打开它进行读写 w:可读写的内存段 n:创建一个新内存段,如果该内存段已存在,则会失败 $mode: 八进制格式 0655 $size: 开辟的数据大小 字节 */ $shm_id = shmop_open( $shm_key , "c" , 0644, 1024); /** * 写入数据 数据必须是字符串格式 , 最后一个指偏移量 * 注意:偏移量必须在指定的范围之内,否则写入不了 * */ $size = shmop_write( $shm_id , 'songjiankang' , 0); echo "write into {$size}" ; #读取的范围也必须在申请的内存范围之内,否则失败 $data = shmop_read( $shm_id , 0, 100); var_dump( $data ); #删除 只是做一个删除标志位,同时不在允许新的进程进程读取,当在没有任何进程读取时系统会自动删除 shmop_delete( $shm_id ); #关闭该内存段 shmop_close( $shm_id ); |
2、用 Semaphore 扩展中的 sem 类函数 (用起来更方便,类似 key-value 格式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// Get the file token key $key = ftok (__DIR__, 'a' ); // 创建一个共享内存 $shm_id = shm_attach( $key , 1024, 777); // resource type if ( $shm_id === false) { die ( 'Unable to create the shared memory segment' ); } #设置一个值 shm_put_var( $shm_id , 111, 'value' ); #删除一个key //shm_remove_var($shm_id, 111); #获取一个值 $value = shm_get_var( $shm_id , 111); var_dump( $value ); #检测一个key是否存在 // var_dump(shm_has_var($shm_id, 111)); #从系统中移除 shm_remove( $shm_id ); #关闭和共享内存的连接 shm_detach( $shm_id ); |
注意:这两种方式不通用的
一个用共享内存和信号量实现的消息队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
/** * 使用共享内存和信号量实现 * * 支持多进程, 支持各种数据类型的存储 * 注: 完成入队或出队操作,尽快使用unset(), 以释放临界区 * */ class ShmQueue { private $maxQSize = 0; // 队列最大长度 private $front = 0; // 队头指针 private $rear = 0; // 队尾指针 private $blockSize = 256; // 块的大小(byte) private $memSize = 25600; // 最大共享内存(byte) private $shmId = 0; private $filePtr = './shmq.ptr' ; private $semId = 0; public function __construct () { $shmkey = ftok ( __FILE__ , 't' ); $this ->shmId = shmop_open( $shmkey , "c" , 0644, $this ->memSize); $this ->maxQSize = $this ->memSize / $this ->blockSize; // 申請一个信号量 $this ->semId = sem_get( $shmkey , 1); sem_acquire( $this ->semId); // 申请进入临界区 $this ->init(); } private function init () { if ( file_exists ( $this ->filePtr)) { $contents = file_get_contents ( $this ->filePtr); $data = explode ( '|' , $contents ); if (isset( $data [0]) && isset( $data [1])) { $this ->front = (int) $data [0]; $this ->rear = (int) $data [1]; } } } public function getLength () { return (( $this ->rear - $this ->front + $this ->memSize) % ( $this ->memSize)) / $this ->blockSize; } public function enQueue ( $value ) { if ( $this ->ptrInc( $this ->rear) == $this ->front) { // 队满 return false; } $data = $this ->encode( $value ); shmop_write( $this ->shmId, $data , $this ->rear); $this ->rear = $this ->ptrInc( $this ->rear); return true; } public function deQueue () { if ( $this ->front == $this ->rear) { // 队空 return false; } $value = shmop_read( $this ->shmId, $this ->front, $this ->blockSize - 1); $this ->front = $this ->ptrInc( $this ->front); return $this ->decode( $value ); } private function ptrInc ( $ptr ) { return ( $ptr + $this ->blockSize) % ( $this ->memSize); } private function encode ( $value ) { $data = serialize( $value ) . "__eof" ; echo '' ; echo strlen ( $data ); echo '' ; echo $this ->blockSize - 1; echo '' ; if ( strlen ( $data ) > $this ->blockSize - 1) { throw new Exception( strlen ( $data ) . " is overload block size!" ); } return $data ; } private function decode ( $value ) { $data = explode ( "__eof" , $value ); return unserialize( $data [0]); } public function __destruct () { $data = $this ->front . '|' . $this ->rear; file_put_contents ( $this ->filePtr, $data ); sem_release( $this ->semId); // 出临界区, 释放信号量 } } /* * // 进队操作 $shmq = new ShmQueue(); $data = 'test data'; $shmq->enQueue($data); * unset($shmq); // 出队操作 $shmq = new ShmQueue(); $data = $shmq->deQueue(); * unset($shmq); */ |
linux下 用 ipc命令查看 ,用 ipcrm 命令可以删除
希望本文所述对大家PHP程序设计有所帮助。