php操做共享內存shmop類及簡單使用測試(代碼)

SimpleSHM 是一個較小的抽象層,用於使用 PHP 操做共享內存,支持以一種面向對象的方式輕鬆操做內存段。在編寫使用共享內存進行存儲的小型應用程序時,這個庫可幫助建立很是簡潔的代碼。可使用 3 個方法進行處理:讀、寫和刪除。從該類中簡單地實例化一個對象,能夠控制打開的共享內存段。php

類對象和測試代碼數據庫

<?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);
    }
}

額外說明json

<?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 服務請求、數據庫查詢或者甚至模板引擎緩存的結果。在內存中讀取和寫入將帶來比在磁盤中讀取和寫入更高的性能。dom

使用此存儲技術不只對緩存有用,也對應用程序之間的數據交換也有用,只要數據以兩端均可讀的格式存儲。不要低估共享內存在 Web 應用程序中的力量。可採用許多不一樣的方式來巧妙地實現這種存儲,唯一的限制是開發人員的創造力和技能。ide

相關文章
相關標籤/搜索