自写malloc函数的实现

转向自己的博客----》》》》》》原博客地址

z_malloc.c

#include "z_malloc.h"

#include <string.h>
__align(MALLOC_EX_BLOCK_SIZE) uint8 malloc_ex_mem[MALLOC_EX_MEM_SIZE] ={0};
uint32 manager_ex_table[MALLOC_EX_MANAGER_TABLE] = { 0 };

void init_EXmem(void){
	uint32 i;
	for(i=0;i<MALLOC_EX_MANAGER_TABLE;i++){
		manager_ex_table[i]=0;
	}
}
///申请内存
static void* _EXmalloc(uint32 size){
	uint32 i_need_block_num;//需要的block数量
	float f_nedd_blcok_num;
	uint32 i;
	uint32 find_block_num=0;//找到的空的块
	uint32 temp;
	uint8 flag=0;

	f_nedd_blcok_num=size/(float)MALLOC_EX_BLOCK_SIZE;
	i_need_block_num=size/MALLOC_EX_BLOCK_SIZE;	
	if(f_nedd_blcok_num>i_need_block_num){//向上进位
		i_need_block_num+=1;
	}
	for(i=0;i<MALLOC_EX_MANAGER_TABLE;){
		if(manager_ex_table[i]==0){
			find_block_num++;
			if(find_block_num==i_need_block_num){
				flag=1;
				break;				
			}
			i++;
		}else{
			find_block_num=0;
			i+=manager_ex_table[i];
		}
	}
	if(flag!=1||i>=MALLOC_EX_MANAGER_TABLE){//没有找到,或者超出了
		return NULL;
	}
	i-=i_need_block_num-1;
//	if(i!=0){
//		i-=i_need_block_num;
//	}
	for(temp=i;temp<i+i_need_block_num;temp++){
		if(temp==i){
			manager_ex_table[i]=i_need_block_num;
		}else{
			manager_ex_table[temp]=1;
		}
	}
	return (void*)(&(malloc_ex_mem[MALLOC_EX_BLOCK_SIZE*i]));	
}
static void _EXfree(void* mem_addr){
	if(mem_addr==NULL){return ;}
	uint32 free_size;
	uint32 i_mem_offset=(uint32)mem_addr-(uint32)malloc_ex_mem;
	uint32 i_manager_offset=i_mem_offset/MALLOC_EX_BLOCK_SIZE;
	uint32 i;
	if(i_manager_offset>MALLOC_EX_MANAGER_TABLE){
		return ;
	}
	free_size=manager_ex_table[i_manager_offset];
	for(i=i_manager_offset;i<free_size+i_manager_offset;i++){
		manager_ex_table[i]=0;
	}
}
u32 getMemBlockRealSize(void *mem_addr){
	uint32 i_mem_size=(uint32)mem_addr-(uint32)malloc_ex_mem;
	uint32 i_manager_offset=i_mem_size/MALLOC_EX_BLOCK_SIZE;
	return manager_ex_table[i_manager_offset]*MALLOC_EX_BLOCK_SIZE;
}
void* EXmalloc(uint32 size){
	void * res;
	u32 ecz;
	res=_EXmalloc(size);
	return  res;
}
void* EXcalloc(u32 num,u32 size){
	void *mem= EXmalloc(num*size);
	if(mem!=NULL){
		memset(mem,0,size);
	}
	return mem;
}

void EXfree(void* mem_addr){
	u32 ecz;
	_EXfree(mem_addr);
}
void *EXrealloc (void *ptr, u32 new_size ){
	void * new_pt;
	u32 _t_new_size;
	if(ptr==NULL){
		new_pt=EXmalloc(new_size);
		return new_pt;
	}else{
		new_pt=EXmalloc(new_size);
		_t_new_size=getMemBlockRealSize(ptr);
		memcpy(new_pt,ptr,_t_new_size>new_size?new_size:_t_new_size);
		EXfree(ptr);
	}
	return new_pt;
}
	

z_malloc.h

#ifndef _MEM_H__
#define _MEM_H__
#include "stm32f10x.h"                  // Device header

#include "type.h"

#define MALLOC_EX_MEM_SIZE (80*1024)
#define MALLOC_EX_BLOCK_SIZE (32)
#define MALLOC_EX_MANAGER_TABLE (MALLOC_EX_MEM_SIZE/MALLOC_EX_BLOCK_SIZE)

void init_EXmem(void);
void* EXmalloc(uint32 size);
void EXfree(void* mem_addr);
void *EXrealloc(void *ptr, u32 new_size );
void* EXcalloc(u32 num,u32 size);


#endif

 

<think>我们正在讨论malloc函数实现方式。根据引用[2],malloc函数需要分配一段连续的内存,满足特定要求。同时,引用[1]提到malloc有两种实现方式:使用brk或mmap。下面我将详细解释malloc实现原理。 </think>### malloc函数的具体实现原理 malloc函数的内存分配主要通过两种系统调用来实现:brk和mmap,具体实现机制如下: #### 1. 底层系统调用 - **brk系统调用**:通过移动堆顶指针(`program break`)来扩展进程的堆空间。当程序启动时,堆空间初始化为0,首次调用malloc时通过brk分配一大块内存作为"内存池"[^1]。 - **mmap系统调用**:直接在进程的虚拟地址空间中创建匿名内存映射区,通常用于大内存分配(如超过128KB的请求)[^1]。 #### 2. 内存管理核心机制 malloc采用**空闲链表(free list)** 管理已分配和空闲的内存块,包含四个关键技术: 1. **隐式链表**:在每个内存块头部存储元数据(块大小和分配状态),通过指针算术遍历所有块 ``` +------------+-------------------+ | 块大小(32b) | 分配标志(1b) | → 用户数据区 +------------+-------------------+ ``` 2. **显式空闲链表**:维护单独的空闲块链表,通过`prev`/`next`指针连接,加速搜索 3. **分离空闲链表**:按大小分类多个空闲链表(如<256B, 256B-1KB等) 4. **内存对齐**:通常按8/16字节对齐以满足CPU访问要求 #### 3. 分配流程 1. 检查请求大小,对齐后计算实际需要的内存大小(含元数据) 2. 在空闲链表中搜索足够大的块: - **首次适应(First-fit)**:遍历链表选择第一个满足的块 - **最佳适应(Best-fit)**:遍历选择最小的满足块 3. 找到块后: - 若剩余空间≥最小块大小,进行**分割(splitting)** - 更新块头部信息和空闲链表 4. 若空闲链表无合适块: - 小内存:通过brk扩展堆空间 - 大内存(>128KB):通过mmap创建新映射区 5. 返回用户可用空间的起始地址 #### 4. 关键特性 - **虚拟内存分配**:分配的是虚拟地址空间,首次访问时触发缺页异常分配物理页[^1] - **边界标记(Boundary Tag)**:在内存块首尾都存储大小信息,支持双向合并 - **快速释放合并**:free时自动检查相邻块是否空闲,立即合并防止碎片化 - **线程安全**:现代实现通过互斥锁或线程本地缓存(如tcache)保证并发安全 #### 5. 性能优化 - **slab分配器**:针对小对象预分配内存池(如glibc的malloc使用bins机制) - **延迟释放**:不立即归还系统内存,保留在空闲链表复用 - **mmap阈值调整**:可通过mallopt设置mmap的使用阈值 > 示例:简单隐式链表实现 ```c // 内存块头部结构 struct block_meta { size_t size; struct block_meta *next; int free; }; void *malloc(size_t size) { if (size <= 0) return NULL; struct block_meta *block = find_free_block(&global_base, size); if (!block) { block = request_space(size); if (!block) return NULL; } else { block->free = 0; } return (block + 1); // 返回用户数据区 } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值