kmalloc & kfree

有了 Buddy System 和 SLab 分配器,我们便能够去做真正的分配内存与释放内存的操作了——也即 malloc 和 free。本部分源码解析即讲解 Chcore 的内核中 kmalloc/kfree,这里的 k 表示 kernel,即专用于内核空间分配/释放的函数

直接上源码!

源码

kmalloc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void *kmalloc(unsigned long size)
{
size_t real_size;
void *ret;
ret = _kmalloc(size, true, &real_size);
return ret;
}

/* Currently, BUG_ON no available memory. */
void *_kmalloc(size_t size, bool is_record, size_t *real_size)
{
void *addr;
int order;

if (unlikely(size == 0))
return ZERO_SIZE_PTR;

if (size <= SLAB_MAX_SIZE) {
addr = alloc_in_slab(size, real_size);
#if ENABLE_MEMORY_USAGE_COLLECTING == ON
if(is_record && collecting_switch) {
record_mem_usage(*real_size, addr);
}
#endif
} else {
if (size <= BUDDY_PAGE_SIZE)
order = 0;
else
order = size_to_page_order(size);
addr = get_pages(order);
}

return addr;
}

kfree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void kfree(void *ptr)
{
_kfree(ptr, true);
}

void _kfree(void *ptr, bool is_revoke_record)
{
struct page *page;

if (unlikely(ptr == ZERO_SIZE_PTR))
return;

page = virt_to_page(ptr);
#if ENABLE_MEMORY_USAGE_COLLECTING == ON
if (collecting_switch && is_revoke_record) {
revoke_mem_usage(ptr);
}
#endif
if (page && page->slab)
free_in_slab(ptr);
else if (page && page->pool)
buddy_free_pages(page->pool, page);
else
kwarn("unexpected state in %s\n", __func__);
}

解析

有了之前 Buddy System 和 SLab 提供的接口,实现这两个函数便简单多了,参数检查过后,直接用一个分支结构即可解决

kmalloc

  • 参数检查
  • 看需要分配的 size 大小,若小于 SLAB_MAX_SIZE 则使用 SLab 分配器的接口分配内存
  • 若大于,则使用伙伴系统的接口分配内存(包装在 get_pages 函数里的,这里没有列出)
  • 返回分配得到的地址指针

kfree

  • 参数检查
  • 根据地址拿到它所属的 page
  • 看 page 的属性,如果它有 slab,则说明是 slab 里的 page,交由 slab 接口处理
  • 如果它有 pool,则说明是伙伴系统的 page,交由伙伴系统接口处理

kmalloc & kfree
http://example.com/2025/02/15/kmalloc-kfree/
作者
思源南路世一劈
发布于
2025年2月15日
许可协议