この記事では、負荷を軽減するために PHP で共有メモリを作成する方法を紹介します。ここでは関数 shmop を理解する必要があります。記事に従って学習しましょう~
PHP にはメモリ用の 2 セットのインターフェイスがあります共有すること。 1 つは shm で、実際には変数共有であり、オブジェクト変数を格納する前にシリアル化します。使用すると非常に便利ですが、効率を優先するメモリアクセス操作ではシリアル化されたストレージは意味がありません。もう 1 つは shmop で、Linux と Windows に共通ですが、shm よりも機能が弱く、Linux では shm* 系の関数を呼び出すことで直接実装されますが、Windows ではシステムをカプセル化することで実装されます。関数が同じ呼び出しを行いました。
共有メモリセグメントを作成するには、関数 shmop を使用する必要があるため、拡張を有効にすることが前提条件です。 [推奨学習: PHP ビデオ チュートリアル ]
shmop メイン関数
shmop_open (共有メモリ ブロックを作成または開く)、shmop_write (への書き込み)共有メモリ ブロック)、shmop_read (共有メモリ ブロックからデータを読み取る)、shmop_size (共有メモリ ブロックのサイズを取得する)、shmop_close (共有メモリ ブロックを閉じる)、shmop_delete (共有メモリ ブロックを削除する)
<?php //创建一块共享内存 $shm_key = 0x4337b101; $shm_id = @shmop_open($shm_key, 'c', 0644, 1024); //读取并写入数据 $data = shmop_read($shm_id, 0, 1024); shmop_write($shm_id, json_encode($data), 0); $size = shmop_size($shm_id); //获取内存中实际数据占用大小 //关闭内存块,并不会删除共享内存,只是清除 PHP 的资源 shmop_close($shm_id);
shmop_open (メモリセグメントの作成)
この関数で最初に表示されるのは、システム ID パラメーターです。これは、システム内の共有メモリセグメントを識別する番号です。 2 番目のパラメータはアクセス モードで、fopen 関数のアクセス モードとよく似ています。メモリ セグメントには 4 つの異なるモードでアクセスできます。
モード "a" では、読み取り専用メモリ セグメントにアクセスできます。読み取り専用アクセス モード "c" では、新しいメモリ セグメントが作成されます。または、メモリ セグメントが既に存在する場合は、読み取りと書き込みのためにオープンしてみます。
モード "n" では、新しいメモリ セグメントが作成されます。同じキーが既に存在する場合、作成は失敗します。これは、次の目的のためです。共有メモリの安全な使用。
3 番目のパラメータは、メモリ セグメントの権限です。ここには 8 進数値を指定する必要があります。
4 番目のパラメータは、メモリ セグメント サイズをバイト単位で指定します。使用される共有メモリセグメントは固定長であるため、保存時および読み取り時にデータの長さを計算する必要があり、そうでないと書き込みに失敗したり、NULL 値が読み取られる可能性があります。 。
この関数は、他の関数がこの共有メモリ セグメントを操作するために使用できる ID 番号を返すことに注意してください。この ID は、パラメータとして渡されるシステム ID とは異なり、共有メモリのアクセス ID です。この 2 つを混同しないように注意してください。失敗すると、shmop_open は FALSE を返します。メモリ ブロックを作成するときは、キー パラメータに変数ではなく定数を使用することをお勧めします。そうしないと、メモリ リークが発生する可能性があります。
shmop_write (メモリ セグメントへのデータの書き込み)
この関数は fwrite 関数に似ており、次の 2 つのパラメータがあります: オープン ストリーム リソース (fopen によって返される)そして書き込みたいデータ。 shmop_write 関数もこのタスクを実行します。
最初のパラメータは shmop_open によって返される ID で、操作している共有メモリ ブロックを識別します。 2 番目のパラメータは保存したいデータで、最後の 3 番目のパラメータは書き込みを開始する位置です。デフォルトでは、書き込みを開始する場所を示すために常に 0 を使用します。この関数は失敗すると FALSE を返し、成功すると書き込まれたバイト数を返すことに注意してください。
shmop_read(メモリ セグメントからのデータの読み取り)
共有メモリ セグメントからのデータの読み取りは非常に簡単です。必要なのは、開いているメモリ セグメントと shmop_read 関数だけです。この関数はいくつかのパラメータを受け取り、fread のように動作します。
ここのパラメータに注意してください。 shmop_read 関数は shmop_open によって返される ID を受け入れますが、これはすでにわかっていますが、他の 2 つのパラメーターも受け入れます。 2 番目の引数は、読み取りたいメモリ セグメント内の位置で、3 番目の引数は読み取りたいバイト数です。 2 番目のパラメータは常にデータの始まりを示す 0 にすることができますが、3 番目のパラメータは読み込むバイト数がわからないため、問題が発生する可能性があります。
これは fread 関数で行うことと非常に似ており、オープン ストリーム リソース (fopen によって返される) とストリームから読み込むバイト数という 2 つのパラメーターを受け取ります。ファイルを完全に読み取るには、filesize 関数 (ファイル内のバイト数を返す) を使用します。
shmop_size (メモリ セグメント データの実際のサイズを返します)
たとえば、長さ 100 バイトのメモリ空間をオープンしましたが、実際の長さは保存されたデータが 90 のみの場合、shmop_size を使用して返される値は 90 です。
shmop_delete (メモリ セグメントの削除)
この関数は 1 つのパラメータのみを受け入れます。削除したい共有メモリ ID。これは実際にメモリ セグメントを削除するわけではありません。共有メモリ セグメントは、別のプロセスが使用している間は削除できないため、メモリ セグメントに削除のマークが付けられます。 shmop_delete 関数は、メモリ セグメントを削除対象としてマークし、他のプロセスがそのセグメントを開くのを防ぎます。それを削除するには、そのメモリセグメントを閉じる必要があります。メモリ ブロックを作成するときは、キー パラメータに変数ではなく定数を使用することをお勧めします。そうしないと、メモリ リークが発生する可能性があります。
shmop_close(メモリセグメントを閉じる)
我们在对内存段进行读取和写入,但完成操作后,我们必须从它解除,这非常类似于处理文件时的 fclose 函数。打开包含一个文件的流并在其中读取或写入数据后,我们必须关闭它,否则将发生锁定。
简单测试结果查看
我是在LNMP环境下操作的,如果你也和我一样,在执行完简单的操作之后,可以使用linux命令查看一下地址和占用大小
# ipcs -m [root@bogon ~]# ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 0 gdm 600 393216 2 dest 0x00000000 32769 gdm 600 393216 2 dest 0x4337b101 884750 nobody 644 1024 0
命令说明
key :共享内存的唯一的key值,共享内存通过该key来判断你读取的是哪一块内存。 owner:创建该共享内存块的用户 bytes:该内存块的大小 status:当前状态,如:dest,即将删除等。
项目实际应用小案例
/** * 将领技能 */ class Generalskill_model extends CI_Model {<!-- --> private $_memory_key = 0x4337b001; //共享内存地址key private $_memory_size = 1048576; //开辟共享内存大小 //最好根据实际数据长度大小定义。 public function __construct() {<!-- --> parent::__construct(); } public function get_skill_list() {<!-- --> $data = []; $shmid = @shmop_open($this->_memory_key, 'a', 0644, $this->_memory_size); if ($shmid === FALSE) {<!-- --> $shmid = @shmop_open($this->_memory_key, 'c', 0644, $this->_memory_size); $data = $this->return_skill_list(); shmop_write($shmid, json_encode($data), 0); @shmop_close($shmid); return $data; } $data = json_decode(preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', trim(shmop_read($shmid, 0, $this->_memory_size))), true); @shmop_close($shmid); return $data; } public function return_skill_list() {<!-- --> //这里是一个超大的数组,其实就是把这个数组json化,然后存入共享内存段。 其实可以用redis等其他缓存...这里我就是为了不用redis等其他nosql才用的shmop return array ( => array ('id' => '1','animation' => '13','skill_type' => '1','power_type' => '1','site' => '1','type' => '1','paramete' => '0','paramete2' => '0','paramete3' => '0','chance' => '0','ratio' => '1', ), => array ('id' => '2','animation' => '3','skill_type' => '2','power_type' => '1','site' => '1','type' => '1','paramete' => '0','paramete2' => '0','paramete3' => '0','chance' => '0','ratio' => '2', ),..........................................
当然你要考虑的是,如果数据更新的话,那么内存段也要删除,并且更新数据…通过shmop_delete可以删除 。这就需要你们自己根据项目应用来考虑了
还有就是这篇文章只是为了简单的读,并没有出现复杂的读写,否则可能会出现进程互斥等意想不到的冲突如果复杂,那么就可以考虑信号量了。
以上がPHP が負荷を軽減するために共有メモリを作成する方法の詳細な例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。