PHP のメモリ マネージャーは階層型です。このマネージャーには、ストレージ層、ヒープ層、emalloc/efree 層の 3 つの層があります。ストレージ層は実際には、malloc() や mmap() などの関数を通じてシステムからメモリを適用し、free() 関数を通じて要求されたメモリを解放します。
通常、ストレージ層によって適用されるメモリブロックは比較的大きいですが、ここで適用される大規模なメモリは、ストレージ層の構造によって必要とされる大規模なメモリを指すものではなく、ヒープ層がストレージの割り当てメソッドを呼び出す場合にのみ適用されます。セグメント形式のメモリに適用されるストレージ層の役割は、メモリ割り当て方法をヒープ層に対して透過的にすることです。
まずストレージ層の構造を見てみましょう:
<ol class="dp-xml"> <li class="alt"><span><span>/* Heaps with user defined storage */ </span></span></li> <li><span>typedef struct _zend_mm_storage zend_mm_storage; </span></li> <li class="alt"><span> </span></li> <li><span>typedef struct _zend_mm_segment { </span></li> <li class="alt"><span> size_t size; </span></li> <li><span> struct _zend_mm_segment *next_segment; </span></li> <li class="alt"><span>} zend_mm_segment; </span></li> <li><span> </span></li> <li class="alt"><span>typedef struct _zend_mm_mem_handlers { </span></li> <li><span> const char *name; </span></li> <li class="alt"><span> zend_mm_storage* (*init)(void *params); //初始化函数 </span></li> <li><span> void (*dtor)(zend_mm_storage *storage); //析构函数 </span></li> <li class="alt"><span> void (*compact)(zend_mm_storage *storage); </span></li> <li><span> zend_mm_segment* (*_alloc)(zend_mm_storage *storage, size_t size); //内存分配函数 </span></li> <li class="alt"><span> zend_mm_segment* (*_realloc)(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size); //重新分配内存函数 </span></li> <li><span> void (*_free)(zend_mm_storage *storage, zend_mm_segment *ptr); //释放内存函数 </span></li> <li class="alt"><span>} zend_mm_mem_handlers; </span></li> <li><span> </span></li> <li class="alt"><span>struct _zend_mm_storage { </span></li> <li><span> const zend_mm_mem_handlers *handlers; //处理函数集 </span></li> <li class="alt"><span> void *data; </span></li> <li><span>}; </span></li> </ol>
メモリ割り当て方法、呼び出される関数は _zend_mm_storage 構造体に設定された処理関数であり、メモリはセグメントの形式で表現されます。
4 つのメモリ スキーム
PHP には、ストレージ層に 4 つのメモリ割り当てスキーム (malloc、win32、mmap_anon、mmap_zero) があります。デフォルトでは、ZEND_WIN32 マクロが設定されている場合は、malloc がメモリの割り当てに使用され、HeapAlloc がメモリの割り当てに呼び出されます。残りの 2 つのメモリ スキームは、変数を設定することで変更できます。 。
公式の説明は次のとおりです:
Zend MM は、ZEND_MM_MEM_TYPE および ZEND_MM_SEG_SIZE 環境変数を使用して調整できます。デフォルト値は「malloc」および「256K」です。ターゲット システムに応じて、「mmap_anon」、「 mmap_zero」および「win32」ストレージマネージャー。
コードでは、これら 4 つのメモリ割り当てスキームに対して、zend_mm_mem_handlers の各処理関数がそれぞれ実装されています。マッチングコードの簡単な説明は次のとおりです:
<ol class="dp-xml"> <li class="alt"><span><span>/* 使用mmap内存映射函数分配内存 写入时拷贝的私有映射,并且匿名映射,映射区不与任何文件关联。*/ </span></span></li> <li><span># define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} </span></li> <li class="alt"><span> </span></li> <li><span>/* 使用mmap内存映射函数分配内存 写入时拷贝的私有映射,并且映射到/dev/zero。*/ </span></li> <li class="alt"><span># define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} </span></li> <li><span> </span></li> <li class="alt"><span>/* 使用HeapAlloc分配内存 windows版本 关于这点,注释中写的是VirtualAlloc() to allocate memory,实际在程序中使用的是HeapAlloc*/ </span></li> <li><span># define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free} </span></li> <li class="alt"><span> </span></li> <li><span>/* 使用malloc分配内存 默认为此种分配 如果有加ZEND_WIN32宏,则使用win32的分配方案*/ </span></li> <li class="alt"><span># define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free} </span></li> <li><span> </span></li> <li class="alt"><span>static const zend_mm_mem_handlers mem_handlers[] = { </span></li> <li><span>#ifdef HAVE_MEM_WIN32 </span></li> <li class="alt"><span> ZEND_MM_MEM_WIN32_DSC, </span></li> <li><span>#endif </span></li> <li class="alt"><span>#ifdef HAVE_MEM_MALLOC </span></li> <li><span> ZEND_MM_MEM_MALLOC_DSC, </span></li> <li class="alt"><span>#endif </span></li> <li><span>#ifdef HAVE_MEM_MMAP_ANON </span></li> <li class="alt"><span> ZEND_MM_MEM_MMAP_ANON_DSC, </span></li> <li><span>#endif </span></li> <li class="alt"><span>#ifdef HAVE_MEM_MMAP_ZERO </span></li> <li><span> ZEND_MM_MEM_MMAP_ZERO_DSC, </span></li> <li class="alt"><span>#endif </span></li> <li><span> {NULL, NULL, NULL, NULL, NULL, NULL} </span></li> <li class="alt"><span>}; </span></li> </ol>
1