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

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

注意:

注意:如果您要打开现有的内存段,则第三个和第四个参数应输入为 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 个注释

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

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

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

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 2293762 user 600 1024 0
0x00000000 2326531 user 600 1024 0

对于任何与标志“n”结合使用的整数 <> 0,shmop_open 都按文档说明工作。它会失败。
4
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);
?>

抱歉,我的英语不太好 :)
1
Craig Manley
19 年前
致:macmaster at pobox dot com

澄清一些新的困惑:你说 shm 键是 8 个字节长。据我所知,它是 4 个字节(32 位)。
查看下面 Linux 上 ipcs 的输出,看看我的意思。

------ Shared Memory Segments --------
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
1
erelsgl at gmail dot com
16 年前
=== 检查共享内存是否存在 ===
Mitchell_Shnier at ieee dot orgZ 提供的解决方案在我的计算机上不起作用 - 我收到警告“Invalid flag ac”。

为了检查共享内存是否存在,您只需使用“a”或“w”标志打开它,同时使用“@”运算符隐藏警告
<?php
@$shid = shmop_open($systemId, "a", 0666, 0);
if (!empty(
$shid)) {
...
共享内存存在
} else {
...
共享内存不存在
}
?>
1
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("Couldn't create shared memory segment.");
?>
0
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(): 无法附加或创建共享内存段 'Invalid argument' 在 php shell 代码第 1 行
PHP 堆栈跟踪
PHP 1. {main}() php shell 代码:0
PHP 2. shmop_open(0, 'w', 384, 10) php shell 代码:1
0
thanks at forthefish dot com
10 年前
在 Windows 上,这些共享内存函数有点奇怪,因为 sem_get() 及其朋友以及任何类型的同步对象都不可用(截至 PHP 5.5.5),无法在访问之前执行正确的锁定。一个核心 PHP 开发人员需要为 Windows 编写一些 sem_get() 的包装器,就像他们为 shmop 所做的那样,以真正完善此功能。

Windows 上的 shmop 实现非常巧妙 - 作者基本上将 POSIX 函数的变体移植到 Windows 等效的原型。
0
Chris Petersen
20 年前
请注意,如果您尝试使用设置为零的键调用 shmop_open,shmop_open 似乎会工作,您可以写入它,但您将无法从中读取或删除它。如果您不小心,您可以继续这样做 - 在“零”处创建越来越多的共享内存块,直到您最终开始收到错误,说 php 无法访问或创建共享内存块,您将不得不重新启动您的机器以释放所有这些“零”块。
-1
Colin Paterson
8 年前
如果您将主脚本作为用户“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 "Couldn't create shared memory segment\n";
}
To Top