2024年PHP开发者大会日本站

shmop_open

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

shmop_open创建或打开共享内存块

描述

shmop_open(
    int $key,
    string $mode,
    int $permissions,
    int $size
): Shmop|false

shmop_open() 可以创建或打开共享内存块。

参数

key

共享内存块的系统ID。可以以十进制或十六进制形式传递。

mode

您可以使用的标志

  • "a" 用于访问(为shmat设置SHM_RDONLY)当您需要以只读方式打开现有的共享内存段时,使用此标志
  • "c" 用于创建(设置IPC_CREATE)当您需要创建一个新的共享内存段,或者如果存在具有相同键的段,则尝试以读写方式打开它时,使用此标志
  • "w" 用于读写访问 当您需要读取和写入共享内存段时,使用此标志,在大多数情况下使用此标志。
  • "n" 创建一个新的内存段(设置IPC_CREATE|IPC_EXCL)当您想要创建一个新的共享内存段,但如果已经存在具有相同标志的段,则失败时,使用此标志。这对于安全目的非常有用,使用它可以防止竞争条件漏洞。

permissions

您希望分配给内存段的权限,这些权限与文件的权限相同。权限需要以八进制形式传递,例如 0644

size

您希望创建的共享内存块的大小(以字节为单位)

注意:

注意:如果您正在打开现有的内存段,则第3个和第4个参数应输入为0。

返回值

成功时,shmop_open() 将返回一个 Shmop 实例,您可以使用它来访问您创建的共享内存段。失败时返回 false

错误/异常

如果 mode 无效,或者 size 小于或等于零,则会抛出 ValueError 异常。其他失败情况下,将发出 E_WARNING

变更日志

版本 描述
8.0.0 成功时,此函数现在返回一个 Shmop 实例;以前,返回的是 resource
8.0.0 如果 mode 无效,或者 size 小于或等于零,则会抛出 ValueError 异常;以前会发出 E_WARNING,并且函数返回 false

范例

示例 #1 创建一个新的共享内存块

<?php
$shm_key
= ftok(__FILE__, 't');
$shm_id = shmop_open($shm_key, "c", 0644, 100);
?>

此示例使用 ftok() 返回的系统ID打开了一个共享内存块。

参见

添加备注

用户贡献的笔记 9条笔记

kakkau at grr dot la
8年前
在*nix系统上,当设置$key = 0时,shmop_open能够创建“无限”数量的段。

在交互式shell中两次执行以下命令后
php > $res = shmop_open(0,"n",0600,1024);

列出当前存在的内存段
$ ipcs -m

------ 共享内存段 --------
key shmid owner perms bytes nattch status
0x00000000 2293762 user 600 1024 0
0x00000000 2326531 user 600 1024 0

对于任何与标志“n”结合使用的整数 <> 0,shmop_open都按文档记录的那样工作。它会失败。
daniele_dll at yahoo dot it
20年前
有一个小的ftok函数。此函数未包含在Windows的php中,因此我直接从linux glibc 2.3.2源代码中获取了它。我希望这能有所帮助。
这是代码

<?php
function ftok($pathname, $proj_id) {
$st = @stat($pathname);
if (!
$st) {
return -
1;
}

$key = sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id & 0xff) << 24)));
return
$key;
}

echo
ftok($_SERVER["SCRIPT_FILENAME"], 250);
?>

对不起,我的英语不好 :)
Craig Manley
19年前
致:macmaster at pobox dot com

为了消除一些新的混淆:你说shm密钥是8字节长。据我所知,它是4字节(32位)。
查看下面Linux上ipcs的输出,看看我的意思。

------ 共享内存段 --------
key shmid owner perms bytes nattch status
0x6e6a694d 65538 mijnbel 644 65536 0
0x326e794d 98307 mijnbel 644 65536 0
0x62417347 131076 smsklap 644 65536 0
erelsgl at gmail dot com
17年前
=== 检查共享内存是否存在 ===
Mitchell_Shnier at ieee dot orgZ提供的解决方案在我的电脑上不起作用——我收到警告“无效标志ac”。

为了检查共享内存是否存在,您只需使用“a”或“w”标志打开它,同时使用“@”运算符隐藏警告
<?php
@$shid = shmop_open($systemId, "a", 0666, 0);
if (!empty(
$shid)) {
...
共享内存存在
} else {
...
共享内存不存在
}
?>
Filippo Fadda
9年前
我在Mac OS X Lion上遇到了同样的问题,该问题影响XP并在下面描述。

要解决此问题,请在“a”标志之前使用“n”。避免使用“c”标志。

<?php
$str
= 'Hello World';

shm_key = ftok($_SERVER['PHP_SELF']);

if (@
$shm_id = shmop_open($shm_key, 'a', 0644, 0))
shmop_delete($shm_id);

$shm_id = shmop_open($shm_key, 'n', 0644, strlen($str));

if (
$shmId) {
shmop_write($shmId, $str, 0);
shmop_close($shmId);
}
else
throw new
RuntimeException("无法创建共享内存段.");
?>
kakkau at grr dot la
6年前
无法使用键0重新连接到段。对于任何其他键(例如1),标志都能正常工作。

php > $soid = shmop_open(0,"n",0600,10);
php > $soid = shmop_open(0,"w",0600,10);
PHP警告:shmop_open(): 无法附加或创建共享内存段“无效参数”在php shell代码第1行
PHP堆栈跟踪
PHP 1. {main}() php shell代码:0
PHP 2. shmop_open(0, 'w', 384, 10) php shell代码:1
thanks at forthefish dot com
11年前
这些共享内存函数在Windows上有点傻,在Windows上(截至PHP 5.5.5)没有sem_get()及其相关函数或任何类型的同步对象可用于在访问之前执行正确的锁定。核心PHP开发人员需要为Windows编写一些sem_get()的包装器,就像他们为shmop所做的那样,才能真正完善此功能。

Windows的shmop实现非常巧妙——作者基本上将POSIX函数的变体移植到Windows等效原型。
Chris Petersen
21年前
请注意,如果您尝试使用设置为零的键来shmop_open,shmop_open似乎会工作,您可以写入它,但您将无法从中读取或删除它。如果您不小心,您可以继续这样做——在“零”处创建越来越多的共享内存块,直到最终您确实会收到错误消息,说php无法访问或创建共享内存块,您将不得不重新启动机器才能释放所有这些“零”块。
Colin Paterson
9年前
如果您正在将主脚本作为例如“root”用户运行,但需要以另一个用户(来自主脚本)例如“www-data”的身份打开共享内存段,则可以使用此方法

exec("sudo -u www-data php -r 'shmop_open(0xee4, "c", 0770, 100);'"); //以用户www-data身份创建共享内存段

$SharedMemorySegment = shmop_open(0xee4, "c", 0770, 100);
if (!$SharedMemorySegment) {
echo "无法创建共享内存段\n";
}
To Top