PHP共享內(nèi)存使用與信號(hào)控制實(shí)例分析
本文實(shí)例講述了PHP共享內(nèi)存使用與信號(hào)控制。分享給大家供大家參考,具體如下:
共享內(nèi)存
共享內(nèi)存的使用主要是為了能夠在同一臺(tái)機(jī)器不同的進(jìn)程中共享一些數(shù)據(jù),比如在多個(gè) php-fpm 進(jìn)程中共享當(dāng)前進(jìn)程的使用情況。這種通信也稱為進(jìn)程間通信(Inter-Process Communication),簡稱 IPC。
PHP 內(nèi)置的 shmop 擴(kuò)展 (Shared Memory Operations) 提供了一系列共享內(nèi)存操作的函數(shù)(可能是用的人不多吧,這一塊兒的文檔還沒有中文翻譯)。在 Linux 上,這些函數(shù)直接是通過調(diào)用 shm* 系列的函數(shù)實(shí)現(xiàn),而 Winodows 上也通過對系統(tǒng)函數(shù)的封裝實(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)的還有一個(gè)很重要的函數(shù):ftok,通過文件的 inode 信息(*nix 上通過 stat 或 ls -i 命令查看)創(chuàng)建 IPC 的唯一 key(文件/文件夾的 inode 是唯一的)。這個(gè)函數(shù)在 Linux 上也是直接調(diào)用同名的系統(tǒng)函數(shù)實(shí)現(xiàn),Windows 上還是使用一些封裝。
一個(gè)簡單的計(jì)數(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)存塊,并不會(huì)刪除共享內(nèi)存,只是清除 PHP 的資源 shmop_close($shm_id);
以上這段代碼沒執(zhí)行一次計(jì)數(shù)加 1,而且數(shù)據(jù)是在不同進(jìn)程之間共享的。也就是說除非手動(dòng)刪除這塊內(nèi)存使用,否則這個(gè)數(shù)據(jù)是不會(huì)重置的。
有個(gè)需要稍微注意的點(diǎn):shmop_open 的第二個(gè)參數(shù)是個(gè) flag,類似 fopen 的第二個(gè)參數(shù),其取值有以前幾個(gè):
"a" 只讀訪問;
"c" 如果內(nèi)存片段不存在,則創(chuàng)建,如果存在,則可讀寫;
"w" 讀寫;
"n" 創(chuàng)建新的內(nèi)存片段,如果同樣 key 的已存在,則會(huì)創(chuàng)建失敗,這是為了安全使用共享內(nèi)存考慮。
此外,由于使用的共享內(nèi)存片段是固定長度的,在存儲(chǔ)和讀取的時(shí)候要計(jì)算好數(shù)據(jù)的長度,不然可能會(huì)寫入失敗或者讀取空值。
信號(hào)控制
既然上面使用到了共享內(nèi)存存儲(chǔ)數(shù)據(jù),就需要考慮是否有多個(gè)進(jìn)程同時(shí)寫入數(shù)據(jù)到共享內(nèi)存的情況,是否需要避免沖突。如果是這樣,就需要引入信號(hào)量進(jìn)行控制。
PHP 也提供了類似的內(nèi)置擴(kuò)展 sysvsem(這個(gè)擴(kuò)展在 Windows 環(huán)境下沒有,文檔中將 ftok 函數(shù)也歸到這個(gè)擴(kuò)展中,但實(shí)際上ftok 是在標(biāo)準(zhǔn)函數(shù)庫中提供的,所以在 Windows 下也是可用的)。
在說信號(hào)量控制之前,先說另外一件有意思的事情:看官方文檔你會(huì)發(fā)現(xiàn)這里同樣也有共享內(nèi)存操作的函數(shù)(shm_*),因?yàn)檫@其實(shí)是同一類別(或者說來自于同一作者)的三個(gè)擴(kuò)展,還有一個(gè)是 sysvmsg(隊(duì)列消息) 。函數(shù)的實(shí)現(xiàn)上稍有差別,但實(shí)際做的事情基本相同。這和上文的 shmop 擴(kuò)展有什么區(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 擴(kuò)展提供的方法并不是原封不動(dòng)的存儲(chǔ)用戶的數(shù)據(jù),而是先使用 PHP 的變量序列化函數(shù)對參數(shù)進(jìn)行序列化然后再進(jìn)行存儲(chǔ)。這就導(dǎo)致通過這些方法存儲(chǔ)的數(shù)據(jù)無法和非 PHP 進(jìn)程共享。不過這樣也能存儲(chǔ)更豐富的 PHP 數(shù)據(jù)類型,上文的擴(kuò)展中 shmop_write 只能寫入字符串。那么為什么 sysvshm 同樣不支持 Windows 呢?因?yàn)槠洳]有引入封裝了 shm* 系列函數(shù)的tsrm_win32.h 的頭文件。
引入信號(hào)控制之后的示例:
<?php $id_key = ftok(__FILE__, 't'); $sem_id = sem_get($id_key); # 請求信號(hào)控制權(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); # 釋放信號(hào) sem_release($sem_id); }
但是本地想模擬實(shí)現(xiàn)寫入沖突實(shí)際上是非常難的(考慮到計(jì)算機(jī)的執(zhí)行速度)。在本地測試中,使用 for 循環(huán)操作時(shí)如果不使用shmop_close 關(guān)閉資源會(huì)出現(xiàn)無法打開共享內(nèi)存的錯(cuò)誤警告。這應(yīng)該是因?yàn)檎诠蚕韮?nèi)存被上一次操作占用中還沒有釋放導(dǎo)致。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP基本語法入門教程》、《PHP錯(cuò)誤與異常處理方法總結(jié)》、《php程序設(shè)計(jì)算法總結(jié)》及《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》
希望本文所述對大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
php讀取txt文件并將數(shù)據(jù)插入到數(shù)據(jù)庫
這篇文章主要介紹了php讀取txt文件并將數(shù)據(jù)插入到數(shù)據(jù)庫的方法和示例代碼,小文件大家可以參考第一種,大文件導(dǎo)入的話請參考第二種。2016-02-02解決PhpMyAdmin中導(dǎo)入2M以上大文件限制的方法分享
當(dāng)用phpMyAdmin導(dǎo)入的資料庫大小大于2M的時(shí)候,會(huì)出現(xiàn)如下提示: No data was received to import. Either no file name was submitted、or the file size exceeded the maximum size permitted by your PHP configuration. See FAQ 1.16.2014-06-06php mssql 分頁SQL語句優(yōu)化 持續(xù)影響
經(jīng)過SQL優(yōu)化后的分面查詢速度能夠得到大幅提高。2009-04-04php數(shù)組函數(shù)序列之sort() 對數(shù)組的元素值進(jìn)行升序排序
sort() 函數(shù)按升序?qū)o定數(shù)組的值排序。注釋:本函數(shù)為數(shù)組中的單元賦予新的鍵名。原有的鍵名將被刪除2011-11-11PHP利用redis位圖實(shí)現(xiàn)簡單的簽到功能
在日常開發(fā)中, 我們會(huì)遇到需要存儲(chǔ)大量 bool類型數(shù)據(jù)的需求, 比如用戶簽到和用戶登陸的記錄等, 本文將為大家介紹如何利用redis位圖輕松實(shí)現(xiàn)簽到功能,感興趣的可以了解一下2023-06-06php面向?qū)ο笾衧tatic靜態(tài)屬性和靜態(tài)方法的調(diào)用
這篇文章主要介紹了php面向?qū)ο笾衧tatic靜態(tài)屬性和靜態(tài)方法的調(diào)用,實(shí)例分析了static靜態(tài)屬性和靜態(tài)方法的原理與調(diào)用技巧,需要的朋友可以參考下2015-02-02