php:删除Windows上的共享内存 [英] php: delete shared memory on windows

查看:228
本文介绍了php:删除Windows上的共享内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码:

shmop_delete();
shmop_close();

不删除共享内存.实验:

doesn't delete shared memory. An experiment:

$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.

Why not deleted yet? How can I delete shared memory? I'm running apache on windows 7.

推荐答案

SHM在Windows中本身不可用,因此PHP会尝试通过内部使用Windows文件映射在其线程安全资源管理器"(TSRM)中对其进行仿真.是一个丑陋的骇客(/TSRM/tsrm_win32.c).

SHM is not natively available in Windows, so PHP tries to emulate it in its "thread safe resource manager" (TSRM) by using Windows File Mappings internally, which is an ugly hack (/TSRM/tsrm_win32.c).

因此,shmop扩展程序也将TSRM用于Windows系统上的SHM. shmop_delete()shmctl()一起使用shmctl()来标记已损坏的内存段,但是在以下仿真中,IPC_RMID是通过以下方式实现的:

Therefore, the shmop extension uses the TSRM for SHM on Windows systems, too. shmop_delete() uses shmctl() with the IPC_RMID command to mark the memory segment destroyed, however IPC_RMID is implemented in the following way in the emulation:

    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 File Mapping.但是,当从shmop_delete()调用此代码时,至少在内存段上始终附加有PHP进程本身,因此它实际上什么也没做.仅在调用shmop_close()

where shm_nattch is the number of processes the segment is attached to (or at least what number the TSRM believes it to be). By setting shm_perm.keyto -1, subsequent access by shmget() is blocked until the Windows File Mapping is destroyed. However, when this code is called from shmop_delete(), there's always at least the PHP process itself attached to the memory segment, so it effectively does nothing at all. The segment is only detached after you call shmop_close()

因此,您的答案是:在Windows中,如果不修复PHP,就无法删除共享内存.

So your answer is: Without fixing PHP, on Windows, you can't delete shared memory.

您可以将其归咎于TSRM中的SHM仿真(可能不正确),也可以归咎于shmop扩展名(盲目使用).

You can blame it on either on the SHM emulation in the TSRM, which is not posixly correct, or on the shmop extension for blindly using it.

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

You can try to remove the if and set shm_perm.key to -1 unconditionally and recompile PHP. It can only break the shmop extension itself, the sysvshm extension or probably other extensions not distributed with PHP.

可以随时通过 http://bugs.php.net/向PHP Bugtracker报告该问题.并由更熟悉PHP内部原理的人修复.

Feel free to report that to the PHP bugtracker at http://bugs.php.net/ and have it fixed by someone more familiar with PHP internals.

同时,也许 http://www.php.net/w32api 可以帮助-您可以使用CreateFileMapping&从Win32-API的朋友中以更直接的方式使用它.但是,我从未测试过它,并且在PECL中它说没有维护,所以要小心.当然,它也不是便携式的.

In the meantime, maybe http://www.php.net/w32api could help - you could use CreateFileMapping & friends from the Win32-API in a more direct manner with it. However, I have never tested it and in PECL it says it is not maintained , so be careful. It is also of course not portable.

您还可以尝试将shmop_*内容包装到您自己的库中,并将您自己的Deleted标志放在内存段的开头-毕竟TSRM在内部执行类似的操作.但是随后您可能会遇到一个相关的错误:我想我记得有人报告他无法使用shmop_open()创建一个大于使用相同键创建的最后一个细分的细分.

You could also try to wrap the shmop_* stuff into your own library and put your own deleted-flag in the beginning of the memory segment - the TSRM does something similar internally after all. But then you could run into a related bug: I think I remember someone reporting that he couldn't create a segment with shmop_open() that was bigger than the last segment created using the same key.

这篇关于php:删除Windows上的共享内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆