malloc是C语言中动态内存分配的核心函数,在Linux系统下实现自己的malloc可以帮助深入理解内存管理机制。下面我将介绍如何实现一个简单的malloc。
自定义malloc需要管理堆内存空间,主要涉及以下概念:
sbrk或mmap从操作系统获取更多内存#include <unistd.h>
#include <stddef.h>
// 内存块头结构
struct block_meta {
size_t size;
struct block_meta *next;
int free;
};
#define META_SIZE sizeof(struct block_meta)
struct block_meta *global_base = NULL;
// 查找空闲块
struct block_meta *find_free_block(struct block_meta **last, size_t size) {
struct block_meta *current = global_base;
while (current && !(current->free && current->size >= size)) {
*last = current;
current = current->next;
}
return current;
}
// 请求更多内存
struct block_meta *request_space(struct block_meta *last, size_t size) {
struct block_meta *block;
block = sbrk(0);
void *request = sbrk(size + META_SIZE);
if (request == (void*) -1) {
return NULL; // sbrk失败
}
if (last) { // NULL on first request
last->next = block;
}
block->size = size;
block->next = NULL;
block->free = 0;
return block;
}
// malloc实现
void *malloc(size_t size) {
struct block_meta *block;
if (size <= 0) {
return NULL;
}
if (!global_base) { // 第一次调用
block = request_space(NULL, size);
if (!block) {
return NULL;
}
global_base = block;
} else {
struct block_meta *last = global_base;
block = find_free_block(&last, size);
if (!block) { // 没有找到空闲块
block = request_space(last, size);
if (!block) {
return NULL;
}
} else { // 找到空闲块
block->free = 0;
}
}
return (block+1); // 返回数据区指针
}
// free实现
void free(void *ptr) {
if (!ptr) {
return;
}
struct block_meta *block_ptr = (struct block_meta*)ptr - 1;
block_ptr->free = 1;
}
上述实现非常简单,实际生产环境的malloc需要考虑更多因素:
现代malloc实现通常使用mmap而非sbrk:
- mmap可以分配任意位置的匿名内存
- 更灵活的内存管理
- 可以单独释放映射的内存
可以使用以下方法测试:
int main() {
int *arr = (int*)malloc(10 * sizeof(int));
for (int i = 0; i < 10; i++) {
arr[i] = i;
}
free(arr);
return 0;
}
实现一个完整的malloc是一个复杂的任务,上述代码仅展示了基本原理。实际项目中建议使用成熟的malloc实现如glibc的ptmalloc、Google的tcmalloc或Facebook的jemalloc。