PHP Conference Japan 2024

sem_get

(PHP 4, PHP 5, PHP 7, PHP 8)

sem_get取得號誌 ID

說明

sem_get(
    int $key,
    int $max_acquire = 1,
    int $permissions = 0666,
    bool $auto_release = true
): SysvSemaphore|false

sem_get() 會傳回一個 ID,可用於存取具有指定 key 的 System V 號誌。

第二次呼叫 sem_get() 取得相同鍵值,會傳回不同的號誌識別碼,但兩個識別碼都存取同一個底層號誌。

如果 key0,則每次呼叫 sem_get() 時,都會建立一個新的私有號誌。

參數

key

max_acquire

可以同時取得號誌的行程數量設定為 max_acquire

permissions

號誌的權限。實際上,只有在行程發現它是目前唯一附加到號誌的行程時,才會設定此值。

auto_release

指定在請求關閉時是否應自動釋放號誌。

傳回值

成功時傳回正整數的號誌識別碼,失敗時傳回 false

更新日誌

版本 說明
8.0.0 成功時,此函式現在會傳回一個 SysvSemaphore 實例;先前傳回的是 resource
8.0.0 auto_release 的類型已從 int 變更為 bool

注意事項

警告

當使用 sem_get() 存取在 PHP 외부 建立的號誌時,請注意,該號誌必須已建立為一組 3 個號誌(例如,在呼叫 C 語言的 semget() 函式時,將 nsems 參數指定為 3),否則 PHP 將無法存取該號誌。

參見

新增註釋

使用者貢獻的註釋 9 則註釋

Dan East
3 年前
請注意,預設的 permissions 參數是八進位!因此,預設值 0666 與 666 或 0x666 不同。

如果將權限指定為十進位 666,則最終會導致權限阻止讀取號誌。症狀是您只能 sem_get 一次,後續的 sem_get 將會失敗(直到您使用 ipcrm 或 sem_remove 將其完全刪除)。

因此,以下所有都等同於預設值
sem_get ( 123, 1, 0666)
sem_get ( 123, 1, 438)
sem_get ( 123, 1, 0x1b6)

大多數 PHP 開發人員(包括我自己)很少使用八進位數字,因此數字 0666 很容易被誤認為 666 或 0x666。
soger
13 年前
實際上,看起來號誌並不是在請求關閉時自動釋放,而是在儲存其資源 ID 的變數被釋放時自動釋放。這是很大的區別。
kakkau at grr dot la
8 年前
設定 $key = 0 時,可以建立「無限」數量的號誌。

多次執行 sem_get
php > sem_get(0,0);

並檢查以下輸出的結果
$ ipcs -s

------ 號誌陣列 --------
key semid owner perms nsems
0x00000000 1277952 使用者 666 3
0x00000000 1310721 使用者 666 3

如您所見,有多個信號量設定為 key 0。
對於任何其他整數,sem_get 的運作符合預期。它會傳回另一個指向先前建立的信號量的資源 ID,並且不會建立另一個信號量。
kakkau at grr dot la
9 年前
對於那些在使用 sem_acquire() 處理由 sem_get() 產生的資源時遇到奇怪行為的人,請查看 sem_get() 的第四個參數 auto_release。它允許多次透過重新分配資源變數來獲取。

./multi.acquire.php
<?php
class Sem {
private
$key = null;
private
$res = null;
public function
__construct() {
$this->key = ftok(".",".");
$this->set_res();
$this->acquire();
}
public function
set_res() {
// 第四個參數 auto_released 預設為 1
$this->res = sem_get($this->key, 1, 0600, 1);
}
public function
acquire() {
echo
"acquired='".sem_acquire($this->res,true)."'\n";
}
}

$s = new Sem();
$s->set_res();
$s->acquire();

?>

$ php multi.acquire.php
acquired='1'
acquired='1'

為了避免預設情況下重新獲取,請將 sem_get() 的參數 auto_release 設定為 0,或檢查資源變數是否已設定,例如使用 is_null()。
Michael Z.
13 年前
當您使用 fileinode() 獲取唯一信號量 key(如在此或相關函數的某些註釋中建議)並結合版本控制軟體時,請注意:例如,SVN 似乎會更改 inode。使用此類檔案將導致您的互斥鎖無法可靠地運作,並且系統的信號量池將被填滿,直到進一步嘗試獲取信號量失敗為止。使用 linux-util-ng(可能在大多数發行版上)中的 ipcs 和 ipcrm 命令來檢查/修復相關問題。
neofutur
18 年前
使用 Gentoo PHP5 時,您需要新增 USE 旗標
sysvipc

請參閱
http://forums.gentoo.org/viewtopic-t-464175-highlight-semget+php.html

以及
http://overlays.gentoo.org/proj/php/
joeldg at listbid.com
21 年前
<?
// 感謝
// http://www.ecst.csuchico.edu/~beej/guide/ipc/shmem.html
$SHM_KEY = ftok("/home/joeldg/homeymail/shmtest.php", 'R');
$shmid = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$data = shm_attach($shmid, 1024);

$data = "test";
printf("共享內容:%s\n", $data);

shm_detach($data);
?>
joeldg AT listbid.com
21 年前
嘿,實際上我添加的上述註釋在技術上並不正確,它更多的是展示函數用法的想法。

$SHM_KEY = ftok("/home/joeldg/homeymail/shmtest.php", 'R');
$shmid = sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
$data = shm_attach($shmid, 1024);
// 我們現在有了共享記憶體區段

// 讓我們在其中放置一個變數
shm_put_var ($data, $inmem, "test");
// 現在讓我們取回它。即使在分岔的行程中,我們仍然可以
// 存取這個變數。
printf("共享內容:%s\n", shm_get_var($data, $inmem));

shm_detach($data);
ein at anti-logic dot com
17 年前
請注意,儘管設定了 max_acquire=1,也沒有辦法確保您對鎖有獨佔的存取權。

例如:
<?
$fp = sem_get(fileinode('lock_file', 100);
sem_acquire($fp);

$fp2 = sem_get(fileinode('lock_file', 1);
sem_acquire($fp2);
?>

第二次呼叫 sem_acquire 不會阻塞。因此,如果您有使用共享鎖(max_acquire > 1)的函式或行程,您仍然需要為寫入存取提供單獨的鎖定機制(例如 flock),這使得 sem_ 函式變得無用。

更多資訊:在 flock 中,對鎖定檔案的每個引用都有自己的選項(可以是共享、獨佔、阻塞、非阻塞等),但顯然 PHP 的 sem 函式只支援每個信號量的這些選項,而不是每個信號量引用。
To Top