• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

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

php 搞代码 3年前 (2022-01-22) 23次浏览 已收录 0个评论

这篇文章主要介绍了关于浅谈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内存池中的堆(heap)层基础本文来源gaodai#ma#com搞*!代#%^码$网!搞代gaodaima码

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

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

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


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:浅谈PHP源码三十二:PHP内存池中的emalloc/efree层与堆(heap)层

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址