PHP共用記憶體

來源:互聯網
上載者:User

標籤:接收   sub   UI   iss   for   miss   lan   儲存   ram   

如何使用 PHP shmop 建立和操作共用記憶體段,使用它們儲存可供其他應用程式使用的資料。

1. 建立記憶體段

共用記憶體函數類似於檔案操作函數,但無需處理一個流,您將處理一個共用記憶體訪問 ID。第一個樣本就是 shmopopen 函數,它允許您開啟一個現有的記憶體段或建立一個新記憶體段。此函數非常類似於經典的 fopen 函數,後者開啟用於檔案操作的流,返回一個資源供其他希望讀取或寫入該開啟的流的函數使用。讓我們看看 shmopopen的用法:

<?php  $key = ftok(__FILE__, ‘h‘);$mode = ‘c‘;$permissions = 0644;$size = 1024;$shmid = shmop_open($key, $mode, $permissions, $size);?>
第一個參數($key):

系統建立IPC通訊 (訊息佇列、訊號量和共用記憶體) 時必須指定一個key值。通常情況下,該key值通過ftok函數得到, * *key是一個我們邏輯上表示共用記憶體段的標識。不同進程只要選擇同一個Key值就可以共用同一段儲存段。

第二個參數($mode):

訪問模式,它類似於fopen的訪問模式,有以下幾種

  • 模式 “a”,它允許您訪問唯讀記憶體段
  • 模式 “w”,它允許您訪問可讀寫的記憶體段
  • 模式 “c”,它建立一個新記憶體段,或者如果該記憶體段已存在,嘗試開啟它進行讀寫 *模式 “n”,它建立一個新記憶體段,如果該記憶體段已存在,則會失敗,返回 false,並伴隨有warning: unable to attach or create shared memory segment
第三個參數($permissions):

記憶體段的許可權。您必須在這裡提供一個八進位值,它類似於UNIX作業系統檔案和目錄的操作許可權。

第四個參數($size):

記憶體段大小,以位元組為單位。在寫入一個記憶體段之前,您必須在它之上分配適當的位元組數。

返回結果:

此函數返回一個 ID 編號,其他函數可使用該 ID 編號操作該共用記憶體段。這個 ID 是共用記憶體訪問 ID,與系統 ID 不同,它以參數的形式傳遞。請注意不要混淆這兩者。如果失敗,shmop_open 將返回 FALSE。

shmop_open成功後,使用ipcs -m, 可以查看到剛剛建立的記憶體段,注意 申請的記憶體段有嚴格的許可權,比如用root使用者申請的,普通使用者就無權訪問

2. 向記憶體段寫入資料

使用 shmop_write 函數向共用記憶體塊寫入資料。此函數的使用很簡單,它僅接受 3 個參數,如下所示。

<?php  //這裡shmid可以延用上一段代碼返回的shmid$shmid = shmop_open(ftok(__FILE__,‘h‘), ‘c‘, 0644, 1024); shmop_write($shmid, "Hello World!", 0);?>

這個函數類似於 fwrite 函數, 在這裡有三個參數。 * 第一個參數(shmid):是shmopopen返回的ID,它識別您操作的共享內存塊。?第二個參數(shmid):是shmopopen返回的ID,它識別您操作的共用記憶體塊。?第二個參數(data):是您希望儲存的資料。 * 第三個參數($offset):是您希望開始寫入的位置。預設情況下,我們始終使用 0 來表示開始寫入的位置。

返回結果:此函數在失敗時會返回 FALSE,在成功時會返回寫入的位元組數。

3. 從記憶體段讀取資料

從共用記憶體段讀取資料很簡單。您只需要一個開啟的記憶體段和 shmop_read 函數,它接受三個參數,如下所示:

<?php  $shmid = shmop_open(ftok(\__FILE_\_,‘h‘), ‘c‘, 0644, 1024);shmop_write($shmid, "Hello World\!", 0);  var_dump(shmop_read($shmid, 0, 11));  ?>
  • 第一個參數($shmid):是 shmop_open 返回的 ID,它識別您操作的共用記憶體塊。
  • 第二個參數($start):是您希望從記憶體段讀取的位置,這個參數可以始終為0, 表示資料的開頭
  • 第三個參數(count):是您希望讀取的字節數。一般情況下我們用shmopsize(count):是您希望讀取的位元組數。一般情況下我們用shmopsize(shmid),以便完整的讀取它。
4. 刪除記憶體段

shmop_delete 該函數只接收一個參數,如下所示:

<?php  $shmid = shmop_open(ftok(\__FILE_\_,‘h‘), ‘c‘, 0644, 1024);shmop_delete($shmid);  ?>

其實這個函數不會實際刪除該記憶體段。它將該記憶體區段標記為刪除狀態,因為共用記憶體段在有其他進程正在使用它時無法被刪除。shmop_delete 函數將該記憶體區段標記為刪除,阻止任何其他進程開啟它。要刪除它,我們需要關閉該記憶體段。

5. 關閉記憶體段

開啟一個共用記憶體段會 “附加” 到它。附加該記憶體段之後,我們可在其中進行讀取和寫入,但完成操作後,我們必須從它解除。

<?php  $shmid = shmop_open(ftok(\__FILE_\_,‘h‘), ‘c‘, 0644, 1024);shmop_write($shmid, "Hello World\!", 0);  shmop_delete($shmid); shmop_close($shmid);  ?>
共用記憶體的原子操作 - 訊號控制

針對共用記憶體的寫操作本身不是原子性的,那麼當我們大量並發進行讀寫的時候,怎麼保證原子性呢,這裡要引入訊號量進行控制。

PHP 也提供了內建擴充 sysvsem ,其實我們在看sysvsem 提供的一系列sem*的方法的時候,就會想到,這和上面提到的shmop*有什麼區別呢,我們來看官房文檔中的這一個解釋:PHP already had a shared memory extension (sysvshm) written by Christian Cartus [email protected], 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 擴充提供的方法在儲存之前對使用者的資料進行serialize處理,這裡就導致這個儲存的資料是無法與其它語言共用的,這一系列方法是php only的方法。

引入訊號控制之後的樣本:

<?php  $key = ftok(_FILE_, ‘h‘) $mode = "c";$permissions = 0755;$size = 1024; // 記憶體段的大小,單位是位元組$semid = sem_get($key); # 請求訊號控制權if (sem_acquire($semid)) {      $shmid = shmop_open($key, ‘c‘, 0644, 1024); # 讀取並寫入資料    shmop_write($shmid, ‘13800138000‘, 0); # 關閉記憶體塊    shmop_close($shmid); # 釋放訊號 sem_release($semid);}

共用記憶體的操作是非常快的,在本地想要類比實現寫入衝突是非常困難的,但是本地想類比實現寫入衝突實際上是非常難的(考慮到電腦的執行速度)。在本地測試中,使用 for 迴圈操作時如果不使用shmop_close 關閉資源會出現無法開啟共用記憶體的錯誤警告。這應該是因為正在共用記憶體被上一次操作佔用中還沒有釋放導致。

PHP共用記憶體

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.