此代码:
shmop_delete();
shmop_close();
不会删除共享内存。一个实验:
$shmid = @shmop_open(1234, 'a', 0, 0);
var_dump($shmid);
产量
bool(false)
当然。但
$shmid = shmop_open(5678, 'c', 0644, 10);
...
shmop_delete($shmid);
shmop_close($shmid);
...
$shmid = @shmop_open(5678, 'a', 0, 0);
var_dump($shmid);
产量
int(157)
为什么不删除呢?如何删除共享内存?我在Windows 7上运行apache。
答案 0 :(得分:5)
SHM在Windows中本身不可用,因此PHP尝试在内部使用Windows文件映射在其“线程安全资源管理器”(TSRM)中模拟它,这是一个丑陋的黑客攻击(/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;
其中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可以提供帮助 - 您可以使用CreateFileMapping&amp;来自Win32-API的朋友可以更直接地使用它。但是,我从来没有对它进行过测试,在PECL中它说它没有被维护,所以要小心。它当然也不便携。
您也可以尝试将shmop_*
内容包装到您自己的库中,并将自己的deleted-flag放在内存段的开头 - 毕竟TSRM在内部做了类似的事情。但是你可能会遇到一个相关的错误:我想我记得有人报告说他无法创建一个shmop_open()
的段,该段大于使用相同键创建的最后一段。