php:删除Windows上的共享内存

use*_*714 4 php shared-memory php-extension

这段代码:

shmop_delete();
shmop_close();
Run Code Online (Sandbox Code Playgroud)

不删除共享内存.一个实验:

$shmid = @shmop_open(1234, 'a', 0, 0);
var_dump($shmid);
Run Code Online (Sandbox Code Playgroud)

产量

bool(false)
Run Code Online (Sandbox Code Playgroud)

当然.但

$shmid = shmop_open(5678, 'c', 0644, 10);
...
shmop_delete($shmid);
shmop_close($shmid);
...
$shmid = @shmop_open(5678, 'a', 0, 0);
var_dump($shmid);
Run Code Online (Sandbox Code Playgroud)

产量

int(157)
Run Code Online (Sandbox Code Playgroud)

为什么不删除呢?如何删除共享内存?我在Windows 7上运行apache.

esc*_*ram 5

SHM在Windows中不是本机可用的,因此PHP尝试在其"线程安全资源管理器"(TSRM)中通过内部使用Windows文件映射来模拟它,这是一个丑陋的黑客(/TSRM/tsrm_win32.c).

因此,shmop扩展也在Windows系统上使用TSRM for SHM. shmop_delete()使用shmctl()IPC_RMID命令来标记销毁存储器段,但是IPC_RMID是在仿真通过以下方式实现的:

    switch (cmd) {
            [...]
            case IPC_RMID:
                    if (shm->descriptor->shm_nattch < 1) {
                            shm->descriptor->shm_perm.key = -1;
                    }
                    return 0;
Run Code Online (Sandbox Code Playgroud)

shm_nattch该段所附加的进程数在哪里(或至少是TSRM认为的数量).通过设置shm_perm.key为-1,后续访问将shmget()被阻止,直到Windows文件映射被销毁.但是,当调用此代码时shmop_delete(),始终至少PHP进程本身附加到内存段,因此它实际上什么都不做.只有在您致电后才会分段shmop_close()

所以你的答案是:在没有修复PHP的情况下,在Windows上,你无法删除共享内存.

您可以将其归咎于TSRM中的SHM仿真,它不是正确的,或者在shmop扩展上用于盲目使用它.

您可以尝试无条件地删除if和设置shm_perm.key为-1并重新编译PHP.它只能破坏shmop扩展本身,sysvshm扩展或可能不与PHP一起分发的其他扩展.

请随意向http://bugs.php.net/上的PHP bugtracker报告,并由更熟悉PHP内部的人修复.

在此期间,也许http://www.php.net/w32api可以提供帮助 - 你可以用更直接的方式使用Win32-API中的CreateFileMapping和朋友.但是,我从来没有对它进行过测试,在PECL中它表示没有进行测试,所以要小心.它当然也不便携.

您也可以尝试将这些shmop_*东西包装到您自己的库中,并将您自己的deleted-flag放在内存段的开头 - 毕竟TSRM在内部执行类似的操作.但是你可能遇到一个相关的错误:我想我记得有人报告说他无法创建一个shmop_open()比使用相同密钥创建的最后一个段更大的段.