4

このコード:

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を実行しています。

4

1 に答える 1

5

SHM は Windows でネイティブに利用できないため、PHP は内部で Windows ファイル マッピングを使用して「スレッド セーフ リソース マネージャー」(TSRM) で SHM をエミュレートしようとしますが、これは醜いハック (/TSRM/tsrm_win32.c) です。

したがって、shmop 拡張機能は、Windows システムでも SHM に TSRM を使用します。 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 エミュレーションのせいにすることができますが、これは間違いなく正しいものではありません。

を削除して無条件に -1ifに設定shm_perm.keyし、PHP を再コンパイルしてみてください。shmop 拡張機能自体、sysvshm 拡張機能、またはおそらく PHP で配布されていない他の拡張機能のみを壊すことができます。

http://bugs.php.net/の PHP バグトラッカーに気軽に報告し、PHP の内部に詳しい人に修正を依頼してください。

当面は、http: //www.php.net/w32api が役立つかもしれません。Win32-API の CreateFileMapping とフレンドを、より直接的な方法で使用できます。ただし、私はそれをテストしたことがなく、PECL では保守されていないと書かれているので、注意してください。もちろん持ち運びもできません。

また、独自のライブラリにそれらをラップして、メモリ セグメントの先頭に独自の削除済みフラグを配置することもできshmop_*ます。TSRM は内部で同様のことを行います。shmop_open()しかし、その後、関連するバグに遭遇する可能性があります:同じキーを使用して作成された最後のセグメントよりも大きいセグメントを作成できなかったと誰かが報告したことを覚えていると思います。

于 2012-09-23T23:08:49.377 に答える