欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

浅谈PHP源码三十二:PHP内存池中的emalloc/efree层与堆(heap)层

程序员文章站 2022-05-04 20:35:55
...
这篇文章主要介绍了关于浅谈PHP源码三十二:PHP内存池中的emalloc/efree层与堆(heap)层,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

浅谈PHP源码三十二:PHP内存池中的emalloc/efree层与堆(heap)层
emalloc/efree层是整个内存体系中最上层结构,它通过与堆层的交换使用PHP自带的内存管理机制。如果有设置USE_ZEND_ALLOC为0,则直接使用malloc/free等函数直接操作内存。
这里将从emalloc与efree两个函数的实现解析emalloc/efree层与堆层的交互,及堆层对于内存的管理机制。

【emalloc】
emalloc函数是从zend_alloc.h 70行开始。
emalloc是一个宏,其对应了_emalloc函数。
在_emalloc函数中,如果未使用zend的内存管理机制,则直接调用malloc函数,否则调用

_zend_mm_alloc_int
[emalloc() -> _emalloc() -> _zend_mm_alloc_int() ]

在_zend_mm_alloc_int函数中,程序会处理真实需要的内存小于或大于等于ZEND_MM_MAX_SMALL_SIZE(272)两种情况,如果小于ZEND_MM_MAX_SMALL_SIZE,则会搜索free_buckets,看是否有合适的内存块,如果可以在free_buckets中找到合适的块使用,同直接跳转到zend_mm_finished_searching_for_block,否则执行zend_mm_search_large_block()

[emalloc() -> _emalloc() -> _zend_mm_alloc_int() -> zend_mm_search_large_block()]
zend_mm_search_large_block函数用来在large_free_buckets中查找合适的内存块。其中当对于ZEND_MM_LARGE_BUCKET_INDEX(true_size)大小的没有找到时,需要查找更大块列表中的最小块。

如果在大块列表和小块列表中都没有,则需要从剩余列表块中查找,如果找到,则同样跳转到zend_mm_finished_searching_for_block
如果三个列表中都没有找到,则需要重新增加内存分配。此时调用storage层的分配函数进行分配,其中内存的大小,如果需要分配的内存大于block_size,则需要根据大小重新计算,否则直接分配block_size大小的内存。
分配内存完后,需要重新整理堆,此时需要重新计算堆中的内存大小,将新分配的内存添加到segments_list的前面。

如果在上面的操作中是直接跳转到zend_mm_finished_searching_for_block,则需要将使用了的内存块从对应的列表中移除(此处应该是一个标记的过程,伪移除)

接下来,根据剩下的内存大小,将其移到空闲列表或剩余列表。

最后返回分配的块。

在emalloc整个过程中,有以下一些注意点。
ZEND_MM_BUCKET_INDEX(true_size)定位在bucket中的位置,这个值大于等于0,小于32。
其实现如下:

#define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))

free_bitmap和large_free_bitmap的值都是0到31。

【efree】
efree函数是从zend_alloc.h 72行开始。
efree是一个宏,其对应了_efree函数。
在_efree函数中,如果未使用zend的内存管理机制,则直接调用free函数,否则调用_

zend_mm_free_int
[efree() -> _efree() -> _zend_mm_free_int() ]

堆首先将整个堆的大小减少,如果当前块的后一个块是空闲块,则将后一个空闲块从空闲块列表中删除并与当前块合并,如果当前块的前一个块是空闲块,则将前一个空闲块从空闲块列表中删除并与当前块合并,指针指向前一个空闲块。如果此时当前块是开始的块,则调用zend_mm_del_segment将整段内存清除,如果不是开始块,则将合并后的块添加到空闲块列表。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础

浅谈PHP源码三十:PHP内存池中的存储层

浅谈PHP源码二十九:关于接口的继承

以上就是浅谈PHP源码三十二:PHP内存池中的emalloc/efree层与堆(heap)层的详细内容,更多请关注其它相关文章!