2016-11-03 110 views
3

我已經實現了一個訪問控制,用於插入用於預訂服務的數據庫表中。它可以正常工作一段時間,然後sem_get()函數失敗,儘管我在每個sem_get()之後調用sem_release()PHP sem_get函數失敗

case 'room': 
    $key = "room"; 
    $semaphore = sem_get($key, 1, 0666, 1); 
    if ($semaphore) { 
     sem_acquire($semaphore); 
     //do some stuff 
     if ($already_reserved_rooms < $max_rooms) { 
      $return="ok"; 
      sem_release($semaphore); 
      return $return; 
     } 
      sem_release($semaphore); 
    } 
    else { 
     //send me mail that semaphore failed 
    } 

    return 'no rooms'; 
    break; 

我該打電話給sem_remove()嗎?

我按照this網站上的步驟操作。

+2

當'sem_get'失敗時,它會記錄一個警告。告訴我們警告。 –

+0

我會從'sem_remove'的描述中說,在全部**進程完全完成信號量之前,絕對不是您想要做的事情。 – apokryfos

+0

感謝主席的回覆,這一切我可以找到PHP警告:sem_release():SysV信號量5(密鑰0x214)目前沒有獲得 – JokerDev

回答

0

拆卸信號燈

是的,你應該叫sem_remove()當你與信號燈設置完成。否則,信號集將持續存在於系統中,直到您將其移除。然而,信號量集仍然存在的事實引起沒有問題而信號燈的數量小於SEMMNS限制:

SEMMNS對信號燈的系統級限制:政策依賴(在Linux上,這限制可以通過/proc/sys/kernel/sem的第二個字段進行讀取和修改)。

sem_remove()立即刪除信號集喚醒所有使用此信號阻塞的進程。

順便說一句,您可以使用ipcrm命令從命令行中刪除信號量,並使用ipcs命令顯示有關IPC設施(包括信號燈)的信息。

釋放信號燈

您不需要調用sem_release()而自動解除標誌(sem_get的第四個參數)上。但只要你不需要獲得的「鎖定」,釋放信號就是一個好主意。

sem_release()只增加內部信號量的值。將其視爲解鎖操作,與sem_acquire()相反。

sem_get()故障

sem_get()函數返回在下列情況下FALSE

  • PHP參數解析失敗(E_ERROR);
  • 信號量存在,但調用進程沒有權限訪問該設置(E_WARNING);
  • 內存分配錯誤(E_WARNING);
  • 的信號量集的最大數目,或信號量的系統寬最大數目超過(E_WARNING

在每個箱子sem_get記錄一個錯誤,或警告。所以你必須檢查日誌爲了找出問題的根源。

由於您的代碼工作了一段時間,它不是參數分析問題,而不是權限。內存分配問題很少見。所以很可能您的信號量限制已經用完了。查看semget的手冊頁以供參考。該手冊頁介紹如何通過/proc/sys/kernel/sem來讀取和修改限制。

有關sysvsem擴展內部機制的更多信息,請參閱this答案。

+0

感謝您的評論,但是它和sem_release有什麼區別?然後我將如何控制其他用戶的信號量,因爲我希望他們都分享相同的信號量。 – JokerDev

+0

當你說「當你完成」你的意思是在我的代碼上述案件的末尾,如果我在案件結束時調用sem_remove()它會影響其他進程,等待當前正在獲取信號量釋放? – JokerDev

+0

@drupaler1,'sem_release'解鎖信號量,'sem_remove'移除信號集。您可以將信號集保留爲持久性的,但在請求關閉階段附近某處將其刪除的可能性較小。通過帶有信號集_的_我指的是當您不再需要對信號集執行任何操作時。 'sem_acquire'阻塞直到可以獲取信號量。只要信號集存在,就可以自由獲取/釋放。您不需要刪除sem.set。查看更新後的答案。 –

0

sem_get()的$ key參數是整數,而您將它作爲字符串傳遞。請考慮通過ftok()調用獲取整數鍵。

所以請考慮更換

$key = "room"; 

下面的代碼:

$project = "r"; // Project identifier. This must be a one character string. 
$key = ftok(__FILE__, $project);