little kernel中的memory管理

在lk中通过我们一般通过malloc来申请内存
void *malloc(size_t size)
{
return heap_alloc(size, 0);
}
malloc 直接调用heap_alloc 来申请。
lk_main函数中通过调用heap_init来初始由于malloc申请的heap
void heap_init(void)
{
LTRACE_ENTRY;


// set the heap range
theheap.base = (void *)HEAP_START;
theheap.len = HEAP_LEN;


// initialize the free list
list_initialize(&theheap.free_list);


// create an initial free chunk
heap_insert_free_chunk(heap_create_free_chunk(theheap.base, theheap.len));
}


可以看到这个函数一开始就要设置heap 需要管理的memory的start 和 size
这两个宏定义如下:
#define HEAP_START ((unsigned long)&_end)
#define HEAP_LEN ((size_t)&_end_of_ram - (size_t)&_end)
_end 和 _end_of_ram 又是在下面的文件中定义的  


system-onesegment.ld
__data_end = .;


/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }


. = ALIGN(4);
_end = .;


. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = .;

可以看到需要用户自己定义MEMBASE 和 MEMSIZE 变量
我们继续看heap_init
会调用下面的函数初始free list
// initialize the free list
list_initialize(&theheap.free_list);
可见这个时候free list是空的
static inline void list_initialize(struct list_node *list)
{
list->prev = list->next = list;
}
继续看是如何插入chunk的
// create an initial free chunk
heap_insert_free_chunk(heap_create_free_chunk(theheap.base, theheap.len));
其中heap_create_free_chunk 的实现如下,
struct free_heap_chunk *heap_create_free_chunk(void *ptr, size_t len)
{
DEBUG_ASSERT((len % sizeof(void *)) == 0); // size must be aligned on pointer boundary


struct free_heap_chunk *chunk = (struct free_heap_chunk *)ptr;
chunk->len = len;


return chunk;
}
可知lk中是用chunk 来管理memory的,刚开始的时候只有一个很大的chunk
heap_insert_free_chunk的实现如下:
static struct free_heap_chunk *heap_insert_free_chunk(struct free_heap_chunk *chunk)
{
#if DEBUGLEVEL > INFO
vaddr_t chunk_end = (vaddr_t)chunk + chunk->len;
#endif


// dprintf("%s: chunk ptr %p, size 0x%lx, chunk_end 0x%x\n", __FUNCTION__, chunk, chunk->len, chunk_end);


struct free_heap_chunk *next_chunk;
struct free_heap_chunk *last_chunk;


// walk through the list, finding the node to insert before
list_for_every_entry(&theheap.free_list, next_chunk, struct free_heap_chunk, node) {
if (chunk < next_chunk) {
DEBUG_ASSERT(chunk_end <= (vaddr_t)next_chunk);


list_add_before(&next_chunk->node, &chunk->node);


goto try_merge;
}
}


// walked off the end of the list, add it at the tail
list_add_tail(&theheap.free_list, &chunk->node);


// try to merge with the previous chunk
try_merge:
last_chunk = list_prev_type(&theheap.free_list, &chunk->node, struct free_heap_chunk, node);
if (last_chunk) {
if ((vaddr_t)last_chunk + last_chunk->len == (vaddr_t)chunk) {
// easy, just extend the previous chunk
last_chunk->len += chunk->len;

// remove ourself from the list
list_delete(&chunk->node);

// set the chunk pointer to the newly extended chunk, in case 
// it needs to merge with the next chunk below
chunk = last_chunk;
}
}


// try to merge with the next chunk
if (next_chunk) {
if ((vaddr_t)chunk + chunk->len == (vaddr_t)next_chunk) {
// extend our chunk
chunk->len += next_chunk->len;


// remove them from the list
list_delete(&next_chunk->node);
}
}


return chunk;
}
这个函数首先会根据chunk的地址,来将chunk插入到free list的位置中,这里也可以知道free list 中的chunk 是按地址排序的
这个函数后面的部分会试图对已存在的chunk进行合并,类似kernel中的buddy system
前面讲过malloc 直接调用heap_alloc来申请内存
void *heap_alloc(size_t size, unsigned int alignment)
{
void *ptr;

LTRACEF("size %zd, align %d\n", size, alignment);


// alignment must be power of 2
if (alignment & (alignment - 1))
return NULL;


// we always put a size field + base pointer + magic in front of the allocation
size += sizeof(struct alloc_struct_begin);

// make sure we allocate at least the size of a struct free_heap_chunk so that
// when we free it, we can create a struct free_heap_chunk struct and stick it
// in the spot
if (size < sizeof(struct free_heap_chunk))
size = sizeof(struct free_heap_chunk);


// round up size to a multiple of native pointer size
size = ROUNDUP(size, sizeof(void *));


// deal with nonzero alignments
if (alignment > 0) {
if (alignment < 16)
alignment = 16;


// add alignment for worst case fit
size += alignment;
}


// critical section
enter_critical_section();


// walk through the list
ptr = NULL;
struct free_heap_chunk *chunk;
list_for_every_entry(&theheap.free_list, chunk, struct free_heap_chunk, node) {
DEBUG_ASSERT((chunk->len % sizeof(void *)) == 0); // len should always be a multiple of pointer size


// is it big enough to service our allocation?
if (chunk->len >= size) {
ptr = chunk;


// remove it from the list
struct list_node *next_node = list_next(&theheap.free_list, &chunk->node);
list_delete(&chunk->node);


if (chunk->len > size + sizeof(struct free_heap_chunk)) {
// there's enough space in this chunk to create a new one after the allocation
struct free_heap_chunk *newchunk = heap_create_free_chunk((uint8_t *)ptr + size, chunk->len - size);


// truncate this chunk
chunk->len -= chunk->len - size;


// add the new one where chunk used to be
if (next_node)
list_add_before(next_node, &newchunk->node);
else
list_add_tail(&theheap.free_list, &newchunk->node);
}


// the allocated size is actually the length of this chunk, not the size requested
DEBUG_ASSERT(chunk->len >= size);
size = chunk->len;


ptr = (void *)((addr_t)ptr + sizeof(struct alloc_struct_begin));


// align the output if requested
if (alignment > 0) {
ptr = (void *)ROUNDUP((addr_t)ptr, alignment);
}


struct alloc_struct_begin *as = (struct alloc_struct_begin *)ptr;
as--;
as->magic = HEAP_MAGIC;
as->ptr = (void *)chunk;
as->size = size;


break;
}
}


LTRACEF("returning ptr %p\n", ptr);


// heap_dump();


exit_critical_section();


return ptr;
}


这个函数前一部分size,例如需要在size基础上加上alloc_struct_begin的size,用于管理chunk
size 要至少4byte对其等
后办法通过list_for_every_entry 遍历free list 找到size满足用户申请的size后,将chunk的起始地址返回
给用户.







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值