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 应用程序中的力量。

可采用许多不同的方式来巧妙地实现这种存储,惟一的限制是开发人员的创造力和技能。

本文参考地址:https://www.php.cn/php-weizijiaocheng-431533.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值