PHP共享内存用法实例分析
本文实例讲述了PHP共享内存用法。分享给大家供大家参考,具体如下:
共享内存主要用于进程间通信
php中的共享内存有两套扩展可以实现
1、shmop 编译时需要开启--enable-shmop参数
实例:
$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"writeinto{$size}";
#读取的范围也必须在申请的内存范围之内,否则失败
$data=shmop_read($shm_id,0,100);
var_dump($data);
#删除只是做一个删除标志位,同时不在允许新的进程进程读取,当在没有任何进程读取时系统会自动删除
shmop_delete($shm_id);
#关闭该内存段
shmop_close($shm_id);
2、用Semaphore扩展中的sem类函数(用起来更方便,类似key-value格式)
//Getthefiletokenkey
$key=ftok(__DIR__,'a');
//创建一个共享内存
$shm_id=shm_attach($key,1024,777);//resourcetype
if($shm_id===false){
die('Unabletocreatethesharedmemorysegment');
}
#设置一个值
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);
注意:这两种方式不通用的
一个用共享内存和信号量实现的消息队列
/**
*使用共享内存和信号量实现
*
*支持多进程,支持各种数据类型的存储
*注:完成入队或出队操作,尽快使用unset(),以释放临界区
*
*/
classShmQueue
{
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;
publicfunction__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();
}
privatefunctioninit()
{
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];
}
}
}
publicfunctiongetLength()
{
return(($this->rear-$this->front+$this->memSize)%($this->memSize))/
$this->blockSize;
}
publicfunctionenQueue($value)
{
if($this->ptrInc($this->rear)==$this->front){//队满
returnfalse;
}
$data=$this->encode($value);
shmop_write($this->shmId,$data,$this->rear);
$this->rear=$this->ptrInc($this->rear);
returntrue;
}
publicfunctiondeQueue()
{
if($this->front==$this->rear){//队空
returnfalse;
}
$value=shmop_read($this->shmId,$this->front,$this->blockSize-1);
$this->front=$this->ptrInc($this->front);
return$this->decode($value);
}
privatefunctionptrInc($ptr)
{
return($ptr+$this->blockSize)%($this->memSize);
}
privatefunctionencode($value)
{
$data=serialize($value)."__eof";
echo'';
echostrlen($data);
echo'';
echo$this->blockSize-1;
echo'';
if(strlen($data)>$this->blockSize-1){
thrownewException(strlen($data)."isoverloadblocksize!");
}
return$data;
}
privatefunctiondecode($value)
{
$data=explode("__eof",$value);
returnunserialize($data[0]);
}
publicfunction__destruct()
{
$data=$this->front.'|'.$this->rear;
file_put_contents($this->filePtr,$data);
sem_release($this->semId);//出临界区,释放信号量
}
}
/*
*//进队操作$shmq=newShmQueue();$data='testdata';$shmq->enQueue($data);
*unset($shmq);//出队操作$shmq=newShmQueue();$data=$shmq->deQueue();
*unset($shmq);
*/
linux下用ipc命令查看,用ipcrm命令可以删除
更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP基本语法入门教程》、《PHP错误与异常处理方法总结》、《php程序设计算法总结》及《php面向对象程序设计入门教程》
希望本文所述对大家PHP程序设计有所帮助。