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() 函数时将 3 指定为 nsems 参数),否则 PHP 将无法访问信号量。

参见

添加注释

用户贡献的注释 9 条注释

Dan East
3 年前
请注意,默认权限参数为八进制!因此,默认值 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 user 666 3
0x00000000 1310721 user 666 3

如您所见,使用键 0 设置了多个信号量。
对于任何其他整数,sem_get 都按预期工作。它返回另一个指向先前创建的信号量的资源 ID,并且不会创建另一个信号量。
kakkau at grr dot la
9 年前
对于那些在使用 sem_get() 生成的资源上使用 sem_acquire() 时遇到奇怪行为的人。查看 sem_get() 的第 4 个参数 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() {
// 第 4 个参数 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() 获取唯一的信号量键(如某些关于此函数或相关函数的注释中所建议)并结合使用版本控制软件时,请注意:例如,SVN 似乎会更改 inode。使用此类文件将导致您的互斥锁无法可靠地工作,并且您的系统信号量池将被填充,直到进一步尝试获取信号量将失败。使用来自 linux-util-ng(在大多数发行版上)的 ipcs 和 ipcrm 命令来检查/修复相关问题。
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_aquire 不会阻塞。因此,如果您有使用共享锁(>1 max_acquire)的函数或进程,您仍然需要为写入访问提供单独的锁机制(例如 flock),这使得 sem_ 函数变得毫无用处。

更多信息,在 flock 中,对锁文件的每个引用都有其自己的选项(可以是共享的、独占的、阻塞的、非阻塞的等),但显然 php 的 sem 函数仅支持每个信号量的这些选项,而不是每个信号量引用。
To Top