本文实例讲述了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程序设计有所帮助。