国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

PHP共享內(nèi)存使用與信號控制實例分析

2024-05-05 00:03:36
字體:
供稿:網(wǎng)友

本文實例講述了PHP共享內(nèi)存使用與信號控制。分享給大家供大家參考,具體如下:

共享內(nèi)存

共享內(nèi)存的使用主要是為了能夠在同一臺機器不同的進程中共享一些數(shù)據(jù),比如在多個 php-fpm 進程中共享當前進程的使用情況。這種通信也稱為進程間通信(Inter-Process Communication),簡稱 IPC。

PHP 內(nèi)置的 shmop 擴展 (Shared Memory Operations) 提供了一系列共享內(nèi)存操作的函數(shù)(可能是用的人不多吧,這一塊兒的文檔還沒有中文翻譯)。在 Linux 上,這些函數(shù)直接是通過調(diào)用 shm* 系列的函數(shù)實現(xiàn),而 Winodows 上也通過對系統(tǒng)函數(shù)的封裝實現(xiàn)了同樣的調(diào)用。

主要函數(shù):

shmop_close — 關(guān)閉共享內(nèi)存塊

shmop_delete — 刪除共享內(nèi)存塊

shmop_open — 創(chuàng)建或打開共享內(nèi)存塊

shmop_read — 從共享內(nèi)存塊中讀取數(shù)據(jù)

shmop_size — 獲取共享內(nèi)存塊的大小

shmop_write — 向共享內(nèi)存塊中寫入數(shù)據(jù)

與此相關(guān)的還有一個很重要的函數(shù):ftok,通過文件的 inode 信息(*nix 上通過 stat 或 ls -i 命令查看)創(chuàng)建 IPC 的唯一 key(文件/文件夾的 inode 是唯一的)。這個函數(shù)在 Linux 上也是直接調(diào)用同名的系統(tǒng)函數(shù)實現(xiàn),Windows 上還是使用一些封裝。

一個簡單的計數(shù)例子:

<?php# 創(chuàng)建一塊共享內(nèi)存$shm_key = ftok(__FILE__, 't');$shm_id = shmop_open($shm_key, 'c', 0644, 8);# 讀取并寫入數(shù)據(jù)$count = (int) shmop_read($shm_id, 0, 8) + 1;shmop_write($shm_id, str_pad($count, 8, '0', STR_PAD_LEFT), 0);// echo shmop_read($shm_id, 0, 8);# 關(guān)閉內(nèi)存塊,并不會刪除共享內(nèi)存,只是清除 PHP 的資源shmop_close($shm_id);

以上這段代碼沒執(zhí)行一次計數(shù)加 1,而且數(shù)據(jù)是在不同進程之間共享的。也就是說除非手動刪除這塊內(nèi)存使用,否則這個數(shù)據(jù)是不會重置的。

有個需要稍微注意的點:shmop_open 的第二個參數(shù)是個 flag,類似 fopen 的第二個參數(shù),其取值有以前幾個:

"a" 只讀訪問;

"c" 如果內(nèi)存片段不存在,則創(chuàng)建,如果存在,則可讀寫;

"w" 讀寫;

"n" 創(chuàng)建新的內(nèi)存片段,如果同樣 key 的已存在,則會創(chuàng)建失敗,這是為了安全使用共享內(nèi)存考慮。

此外,由于使用的共享內(nèi)存片段是固定長度的,在存儲和讀取的時候要計算好數(shù)據(jù)的長度,不然可能會寫入失敗或者讀取空值。

信號控制

既然上面使用到了共享內(nèi)存存儲數(shù)據(jù),就需要考慮是否有多個進程同時寫入數(shù)據(jù)到共享內(nèi)存的情況,是否需要避免沖突。如果是這樣,就需要引入信號量進行控制。

PHP 也提供了類似的內(nèi)置擴展 sysvsem(這個擴展在 Windows 環(huán)境下沒有,文檔中將 ftok 函數(shù)也歸到這個擴展中,但實際上ftok 是在標準函數(shù)庫中提供的,所以在 Windows 下也是可用的)。

在說信號量控制之前,先說另外一件有意思的事情:看官方文檔你會發(fā)現(xiàn)這里同樣也有共享內(nèi)存操作的函數(shù)(shm_*),因為這其實是同一類別(或者說來自于同一作者)的三個擴展,還有一個是 sysvmsg(隊列消息) 。函數(shù)的實現(xiàn)上稍有差別,但實際做的事情基本相同。這和上文的 shmop 擴展有什么區(qū)別呢?shmop 源碼下的 README 文件有簡單的說明:

PHP already had a shared memory extension (sysvshm) written by Christian Cartus <cartus@atrior.de>, unfortunately this extension was designed with PHP only in mind and offers high level features which are extremely bothersome for basic SHM we had in mind.

簡單說來:sysvshm 擴展提供的方法并不是原封不動的存儲用戶的數(shù)據(jù),而是先使用 PHP 的變量序列化函數(shù)對參數(shù)進行序列化然后再進行存儲。這就導致通過這些方法存儲的數(shù)據(jù)無法和非 PHP 進程共享。不過這樣也能存儲更豐富的 PHP 數(shù)據(jù)類型,上文的擴展中 shmop_write 只能寫入字符串。那么為什么 sysvshm 同樣不支持 Windows 呢?因為其并沒有引入封裝了 shm* 系列函數(shù)的tsrm_win32.h 的頭文件。

引入信號控制之后的示例:

<?php$id_key = ftok(__FILE__, 't');$sem_id = sem_get($id_key);# 請求信號控制權(quán)if (sem_acquire($sem_id)) {  $shm_id = shmop_open($id_key, 'c', 0644, 8);  # 讀取并寫入數(shù)據(jù)  $count = (int) shmop_read($shm_id, 0, 8) + 1;  shmop_write($shm_id, str_pad($count, 8, '0', STR_PAD_LEFT), 0);  // echo shmop_read($shm_id, 0, 8);  # 關(guān)閉內(nèi)存塊  shmop_close($shm_id);  # 釋放信號  sem_release($sem_id);}

但是本地想模擬實現(xiàn)寫入沖突實際上是非常難的(考慮到計算機的執(zhí)行速度)。在本地測試中,使用 for 循環(huán)操作時如果不使用shmop_close 關(guān)閉資源會出現(xiàn)無法打開共享內(nèi)存的錯誤警告。這應(yīng)該是因為正在共享內(nèi)存被上一次操作占用中還沒有釋放導致。

希望本文所述對大家PHP程序設(shè)計有所幫助。


注:相關(guān)教程知識閱讀請移步到PHP教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 云阳县| 陕西省| 思茅市| 胶南市| 乐陵市| 鲜城| 柞水县| 格尔木市| 如东县| 镇江市| 临西县| 普洱| 济阳县| 辽中县| 文安县| 昆明市| 正蓝旗| 留坝县| 侯马市| 错那县| 江华| 霍林郭勒市| 神池县| 江达县| 读书| 德格县| 五家渠市| 萨嘎县| 新津县| 莱州市| 温州市| 和田县| 嘉鱼县| 两当县| 扬中市| 台前县| 济源市| 济源市| 鄱阳县| 吕梁市| 赤水市|