golang 内存分配

本文深入探讨了Golang内存分配器的结构,包括cache、central和heap三个模块。介绍了内存分配的入口函数runtime·mallocgc,以及内存分配的流程。文章详细讲解了MCache、MHeap和MCentral的实现,强调了cache的内存分配和释放逻辑,以及central如何处理内存不足的情况。此外,还概述了MHeap的内存管理,包括从操作系统申请内存和管理span。
摘要由CSDN通过智能技术生成

内存布局结构图

   从上述结构图来看,内存分配器还是有一点小复杂的,但根据具体的逻辑层次可以拆分成三大模块--cache,central,heap,然后一个一个的模块分析下去,逻辑就显得特别清晰明了了。位于结构图最下边的Cache就是cache模块部分;central模块对应深蓝色部分的MCentral,central模块的逻辑结构很简单,所以结构图就没有详细的绘制了;Heap是结构图中的核心结构,对应heap模块,也可以看出来central是直接被Heap管理起来的,属于Heap的子模块。

   在分析内存分配器这部分源码的时候,首先需要明确的是所有内存分配的入口,有了入口就可以从这里作为起点一条线的看下去,不会有太大的障碍。这个入口就是malloc.goc源文件中的runtime·mallocgc函数,这个入口函数的主要工作就是分配内存以及触发gc(本文将只介绍内存分配),在进入真正的分配内存之前,此入口函数还会判断请求的是小内存分配还是大内存分配(32k作为分界线);小内存分配将调用runtime·MCache_Alloc函数从Cache获取,而大内存分配调用runtime·MHeap_Alloc直接从Heap获取。入口函数过后,就会真正的进入到具体的内存分配过程中去了。

    在真正进入内存分配过程之前,还需要了解一下整个内存分配器是如何创建的以及初始化成什么样子。完成内存分配器创建初始化的函数是runtime·mallocinit,看一下简化的源码:

void runtime·mallocinit(void)
{
	// 创建mheap对象,这个是直接从操作系统分配内存。heap是全局的,所有线程共享,
       一个Go进程里只有一个heap。
	if((runtime·mheap = runtime·SysAlloc(sizeof(*runtime·mheap))) == nil)
		runtime·throw("runtime: cannot allocate heap metadata");

	// 64位平台,申请一大块内存地址保留区,后续所有page的申请都会从这个地址区里分
        配。这个区就是结构图中的arena。 
	if(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) {
		arena_size = MaxMem;
		bitmap_size = arena_size / (sizeof(void*)*8/4);
		p = runtime·SysReserve((void*)(0x00c0ULL<<32), bitmap_size + arena_size);
	}

	// 初始化好heap的arena以及bitmap。
	runtime·mheap->bitmap = p;
	runtime·mheap->arena_start = p + bitmap_size;
	runtime·mheap->arena_used = runtime·mheap->arena_start;
	runtime·mheap->arena_end = runtime·mheap->arena_start + arena_size;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值