php操作共享内存shmop类及简单使用测试(代码)详解编程语言

SimpleSHM 是一个较小的抽象层,用于使用 PHP 操作共享内存,支持以一种面向对象的方式轻松操作内存段。在编写使用共享内存进行存储的小型应用程序时,这个库可帮助创建非常简洁的代码。可以使用 3 个方法进行处理:读、写和删除。从该类中简单地实例化一个对象,可以控制打开的共享内存段。

类对象和测试代码

<?php 
//类对象 
namespace Simple/SHM; 
class Block 
{ 
/** 
* Holds the system id for the shared memory block 
* 
* @var int 
* @access protected 
*/ 
protected $id; 
/** 
* Holds the shared memory block id returned by shmop_open 
* 
* @var int 
* @access protected 
*/ 
protected $shmid; 
/** 
* Holds the default permission (octal) that will be used in created memory blocks 
* 
* @var int 
* @access protected 
*/ 
protected $perms = 0644; 
/** 
* Shared memory block instantiation 
* 
* In the constructor we'll check if the block we're going to manipulate 
* already exists or needs to be created. If it exists, let's open it. 
* 
* @access public 
* @param string $id (optional) ID of the shared memory block you want to manipulate 
*/ 
public function __construct($id = null) 
{ 
if($id === null) { 
$this->id = $this->generateID(); 
} else { 
$this->id = $id; 
} 
if($this->exists($this->id)) { 
$this->shmid = shmop_open($this->id, "w", 0, 0); 
} 
} 
/** 
* Generates a random ID for a shared memory block 
* 
* @access protected 
* @return int System V IPC key generated from pathname and a project identifier 
*/ 
protected function generateID() 
{ 
$id = ftok(__FILE__, "b"); 
return $id; 
} 
/** 
* Checks if a shared memory block with the provided id exists or not 
* 
* In order to check for shared memory existance, we have to open it with 
* reading access. If it doesn't exist, warnings will be cast, therefore we 
* suppress those with the @ operator. 
* 
* @access public 
* @param string $id ID of the shared memory block you want to check 
* @return boolean True if the block exists, false if it doesn't 
*/ 
public function exists($id) 
{ 
$status = @shmop_open($id, "a", 0, 0); 
return $status; 
} 
/** 
* Writes on a shared memory block 
* 
* First we check for the block existance, and if it doesn't, we'll create it. Now, if the 
* block already exists, we need to delete it and create it again with a new byte allocation that 
* matches the size of the data that we want to write there. We mark for deletion,  close the semaphore 
* and create it again. 
* 
* @access public 
* @param string $data The data that you wan't to write into the shared memory block 
*/ 
public function write($data) 
{ 
$size = mb_strlen($data, 'UTF-8'); 
if($this->exists($this->id)) { 
shmop_delete($this->shmid); 
shmop_close($this->shmid); 
$this->shmid = shmop_open($this->id, "c", $this->perms, $size); 
shmop_write($this->shmid, $data, 0); 
} else { 
$this->shmid = shmop_open($this->id, "c", $this->perms, $size); 
shmop_write($this->shmid, $data, 0); 
} 
} 
/** 
* Reads from a shared memory block 
* 
* @access public 
* @return string The data read from the shared memory block 
*/ 
public function read() 
{ 
$size = shmop_size($this->shmid); 
$data = shmop_read($this->shmid, 0, $size); 
return $data; 
} 
/** 
* Mark a shared memory block for deletion 
* 
* @access public 
*/ 
public function delete() 
{ 
shmop_delete($this->shmid); 
} 
/** 
* Gets the current shared memory block id 
* 
* @access public 
*/ 
public function getId() 
{ 
return $this->id; 
} 
/** 
* Gets the current shared memory block permissions 
* 
* @access public 
*/ 
public function getPermissions() 
{ 
return $this->perms; 
} 
/** 
* Sets the default permission (octal) that will be used in created memory blocks 
* 
* @access public 
* @param string $perms Permissions, in octal form 
*/ 
public function setPermissions($perms) 
{ 
$this->perms = $perms; 
} 
/** 
* Closes the shared memory block and stops manipulation 
* 
* @access public 
*/ 
public function __destruct() 
{ 
shmop_close($this->shmid); 
} 
}
<?php 
//测试使用代码 
namespace Simple/SHM/Test; 
use Simple/SHM/Block; 
class BlockTest extends /PHPUnit_Framework_TestCase 
{ 
public function testIsCreatingNewBlock() 
{ 
$memory = new Block; 
$this->assertInstanceOf('Simple//SHM//Block', $memory); 
$memory->write('Sample'); 
$data = $memory->read(); 
$this->assertEquals('Sample', $data); 
} 
public function testIsCreatingNewBlockWithId() 
{ 
$memory = new Block(897); 
$this->assertInstanceOf('Simple//SHM//Block', $memory); 
$this->assertEquals(897, $memory->getId()); 
$memory->write('Sample 2'); 
$data = $memory->read(); 
$this->assertEquals('Sample 2', $data); 
} 
public function testIsMarkingBlockForDeletion() 
{ 
$memory = new Block(897); 
$memory->delete(); 
$data = $memory->read(); 
$this->assertEquals('Sample 2', $data); 
} 
public function testIsPersistingNewBlockWithoutId() 
{ 
$memory = new Block; 
$this->assertInstanceOf('Simple//SHM//Block', $memory); 
$memory->write('Sample 3'); 
unset($memory); 
$memory = new Block; 
$data = $memory->read(); 
$this->assertEquals('Sample 3', $data); 
} 
}

额外说明

<?php 
$memory = new SimpleSHM; 
$memory->write('Sample'); 
echo $memory->read(); 
?>

请注意,上面代码里没有为该类传递一个 ID。如果没有传递 ID,它将随机选择一个编号并打开该编号的新内存段。我们可以以参数的形式传递一个编号,供构造函数打开现有的内存段,或者创建一个具有特定 ID 的内存段,如下

<?php 
$new = new SimpleSHM(897); 
$new->write('Sample'); 
echo $new->read(); 
?>

神奇的方法 __destructor 负责在该内存段上调用 shmop_close 来取消设置对象,以与该内存段分离。我们将这称为 “SimpleSHM 101”。现在让我们将此方法用于更高级的用途:使用共享内存作为存储。存储数据集需要序列化,因为数组或对象无法存储在内存中。尽管这里使用了 JSON 来序列化,但任何其他方法(比如 XML 或内置的 PHP 序列化功能)也已足够。如下

<?php 
require('SimpleSHM.class.php'); 
$results = array( 
'user' => 'John', 
'password' => '123456', 
'posts' => array('My name is John', 'My name is not John') 
); 
$data = json_encode($results); 
$memory = new SimpleSHM; 
$memory->write($data); 
$storedarray = json_decode($memory->read()); 
print_r($storedarray); 
?>

我们成功地将一个数组序列化为一个 JSON 字符串,将它存储在共享内存块中,从中读取数据,去序列化 JSON 字符串,并显示存储的数组。这看起来很简单,但请想象一下这个代码片段带来的可能性。您可以使用它存储 Web 服务请求、数据库查询或者甚至模板引擎缓存的结果。在内存中读取和写入将带来比在磁盘中读取和写入更高的性能。

使用此存储技术不仅对缓存有用,也对应用程序之间的数据交换也有用,只要数据以两端都可读的格式存储。不要低估共享内存在 Web 应用程序中的力量。可采用许多不同的方式来巧妙地实现这种存储,惟一的限制是开发人员的创造力和技能。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/17183.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论