🆕 创建和销毁slab内存池的函数、从slab内存池分配内存对象的函数

This commit is contained in:
fslongjin 2022-02-23 23:33:07 +08:00
parent d5eb9e8a27
commit 5bac5bc096
2 changed files with 397 additions and 0 deletions

294
kernel/mm/slab.c Normal file
View File

@ -0,0 +1,294 @@
#include "slab.h"
/**
* @brief
*
* @param size
* @param constructor
* @param destructor
* @param arg
* @return struct slab*
*/
struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg)
{
struct slab *slab_pool = (struct slab *)kmalloc(sizeof(struct slab), 0);
// BUG
if (slab_pool == NULL)
{
kBUG("slab_create()->kmalloc()->slab == NULL");
return NULL;
}
memset(slab_pool, 0, sizeof(struct slab));
slab_pool->size = SIZEOF_LONG_ALIGN(size);
slab_pool->count_total_using = 0;
slab_pool->count_total_free = 0;
// 直接分配cache_pool结构体避免每次访问都要检测是否为NULL提升效率
slab_pool->cache_pool = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
// BUG
if (slab_pool->cache_pool == NULL)
{
kBUG("slab_create()->kmalloc()->slab->cache_pool == NULL");
kfree(slab_pool);
return NULL;
}
memset(slab_pool->cache_pool, 0, sizeof(struct slab_obj));
// dma内存池设置为空
slab_pool->cache_dma_pool = NULL;
// 设置构造及析构函数
slab_pool->constructor = constructor;
slab_pool->destructor = destructor;
list_init(&slab_pool->cache_pool->list);
// 分配属于内存池的内存页
slab_pool->cache_pool->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
// BUG
if (slab_pool->cache_pool->page == NULL)
{
kBUG("slab_create()->kmalloc()->slab->cache_pool == NULL");
kfree(slab_pool->cache_pool);
kfree(slab_pool);
return NULL;
}
// page_init(slab_pool->cache_pool->page, PAGE_KERNEL);
slab_pool->cache_pool->count_using = 0;
slab_pool->cache_pool->count_free = PAGE_2M_SIZE / slab_pool->size;
slab_pool->count_total_free = slab_pool->cache_pool->count_free;
slab_pool->cache_pool->vaddr = phys_2_virt(slab_pool->cache_pool->page->addr_phys);
// bitmap有多少有效位
slab_pool->cache_pool->bmp_count = slab_pool->cache_pool->count_free;
// 计算位图所占的空间 占用多少byte按unsigned long大小的上边缘对齐
slab_pool->cache_pool->bmp_len = ((slab_pool->cache_pool->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
// 初始化位图
slab_pool->cache_pool->bmp = (ul *)kmalloc(slab_pool->cache_pool->bmp_len, 0);
// BUG
if (slab_pool->cache_pool->bmp == NULL)
{
kBUG("slab_create()->kmalloc()->slab->cache_pool == NULL");
free_pages(slab_pool->cache_pool->page, 1);
kfree(slab_pool->cache_pool);
kfree(slab_pool);
return NULL;
}
// 将位图清空
memset(slab_pool->cache_pool->bmp, 0, slab_pool->cache_pool->bmp_len);
return slab_pool;
}
/**
* @brief
* slab对象是空的时候才能销毁
* @param slab_pool
* @return ul
*
*/
ul slab_destroy(struct slab *slab_pool)
{
struct slab_obj *slab_obj_ptr = slab_pool->cache_pool;
if (slab_pool->count_total_using)
{
kBUG("slab_cache->count_total_using != 0");
return ESLAB_NOTNULL;
}
struct slab_obj *tmp_slab_obj = NULL;
while (!list_empty(&slab_obj_ptr->list))
{
tmp_slab_obj = slab_obj_ptr;
// 获取下一个slab_obj的起始地址
slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
list_del(&tmp_slab_obj->list);
kfree(tmp_slab_obj->bmp);
page_clean(tmp_slab_obj->page);
free_pages(tmp_slab_obj->page, 1);
kfree(tmp_slab_obj);
}
kfree(slab_obj_ptr->bmp);
page_clean(slab_obj_ptr->page);
free_pages(slab_obj_ptr->page, 1);
kfree(slab_obj_ptr);
kfree(slab_pool);
return 0;
}
/**
* @brief SLAB内存池中的内存对象
*
* @param slab_pool slab内存池
* @param arg
* @return void*
*/
void *slab_malloc(struct slab *slab_pool, ul arg)
{
struct slab_obj *slab_obj_ptr = slab_pool->cache_pool;
struct slab_obj *tmp_slab_obj = NULL;
// slab内存池中已经没有空闲的内存对象进行扩容
if (slab_pool->count_total_free == 0)
{
tmp_slab_obj = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
// BUG
if (tmp_slab_obj == NULL)
{
kBUG("slab_malloc()->kmalloc()->slab->tmp_slab_obj == NULL");
return NULL;
}
memset(tmp_slab_obj, 0, sizeof(struct slab_obj));
list_init(&tmp_slab_obj->list);
tmp_slab_obj->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
// BUG
if (tmp_slab_obj->page == NULL)
{
kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->page == NULL");
kfree(tmp_slab_obj);
return NULL;
}
tmp_slab_obj->count_using = 0;
tmp_slab_obj->count_free = PAGE_2M_SIZE / slab_pool->size;
tmp_slab_obj->vaddr = phys_2_virt(tmp_slab_obj->page->addr_phys);
tmp_slab_obj->bmp_count = tmp_slab_obj->count_free;
// 计算位图所占的空间 占用多少byte按unsigned long大小的上边缘对齐
tmp_slab_obj->bmp_len = ((tmp_slab_obj->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
tmp_slab_obj->bmp = (ul *)kmalloc(tmp_slab_obj->bmp_len, 0);
// BUG
if (tmp_slab_obj->bmp == NULL)
{
kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->bmp == NULL");
free_pages(tmp_slab_obj->page, 1);
kfree(tmp_slab_obj);
return NULL;
}
memset(tmp_slab_obj->bmp, 0, tmp_slab_obj->bmp_len);
list_add(&slab_pool->cache_pool->list, tmp_slab_obj);
slab_pool->count_total_free += tmp_slab_obj->count_free;
slab_obj_ptr = tmp_slab_obj;
}
// 扩容完毕或无需扩容,开始分配内存对象
int tmp_md;
do
{
if (slab_obj_ptr->count_free == 0)
{
slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
continue;
}
for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
{
// 当前bmp对应的内存对象都已经被分配
if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
{
i += 63;
continue;
}
// 第i个内存对象是空闲的
tmp_md = i % 64;
if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << tmp_md)) == 0)
{
// 置位bmp
*(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << tmp_md);
// 更新当前slab对象的计数器
++(slab_obj_ptr->count_using);
--(slab_obj_ptr->count_free);
// 更新slab内存池的计数器
++(slab_pool->count_total_using);
--(slab_pool->count_total_free);
if(slab_pool->constructor!=NULL)
{
// 返回内存对象指针(要求构造函数返回内存对象指针)
return slab_pool->constructor((char* )slab_obj_ptr->vaddr +slab_pool->size*i, arg);
}
// 返回内存对象指针
else return (void*)((char*)slab_obj_ptr->vaddr+slab_pool->size*i);
}
}
} while (slab_obj_ptr != slab_pool->cache_pool);
// should not be here
kBUG("slab_malloc() ERROR: can't malloc");
// 释放内存
if(tmp_slab_obj!=NULL)
{
list_del(&tmp_slab_obj->list);
kfree(tmp_slab_obj->bmp);
page_clean(tmp_slab_obj->page);
free_pages(tmp_slab_obj->page,1);
kfree(tmp_slab_obj);
}
return NULL;
}
/**
* @brief slab内存池中的对象
*
* @param slab_pool
* @param addr
* @param arg
* @return ul
*/
ul slab_free(struct slab* slab_pool, void* addr, ul arg)
{
}
/**
* @brief
*
* @param size
* @param flags flag
* @return void*
*/
void *kmalloc(unsigned long size, unsigned long flags)
{
// @todo: 内存分配函数
}
/**
* @brief
*
* @param address
* @return unsigned long
*/
unsigned long kfree(void *address)
{
// @todo: 通用内存释放函数
}

103
kernel/mm/slab.h Normal file
View File

@ -0,0 +1,103 @@
#pragma once
#include "mm.h"
#include "../common/glib.h"
#include "../common/printk.h"
#include "../common/kprint.h"
#define SIZEOF_LONG_ALIGN(size) ((size + sizeof(long) - 1) & ~(sizeof(long) - 1))
#define SIZEOF_INT_ALIGN(size) ((size + sizeof(int) - 1) & ~(sizeof(int) - 1))
// SLAB存储池count_using不为空
#define ESLAB_NOTNULL 101
struct slab_obj
{
struct List *list;
// 当前slab对象所使用的内存页
struct Page *page;
ul count_using;
ul count_free;
// 当前页面所在的线性地址
void *vaddr;
// 位图
ul bmp_len; // 位图的长度(字节)
ul bmp_count; // 位图的有效位数
ul *bmp;
};
// slab内存池
struct slab
{
ul size;
ul count_total_using;
ul count_total_free;
// 内存池对象
struct slab_obj *cache_pool;
// dma内存池对象
struct slab_obj *cache_dma_pool;
// 内存池的构造函数和析构函数
void *(*constructor)(void *vaddr, ul arg);
void *(*destructor)(void *vaddr, ul arg);
};
/**
* @brief
*
* @param size
* @param flags flag
* @return void*
*/
void *kmalloc(unsigned long size, unsigned long flags);
/**
* @brief
*
* @param address
* @return unsigned long
*/
unsigned long kfree(void * address);
/**
* @brief
*
* @param size
* @param constructor
* @param destructor
* @param arg
* @return struct slab*
*/
struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg);
/**
* @brief
* slab对象是空的时候才能销毁
* @param slab_pool
* @return ul
*
*/
ul slab_destroy(struct slab * slab_pool);
/**
* @brief SLAB内存池中的内存对象
*
* @param slab_pool slab内存池
* @param arg
* @return void*
*/
void* slab_malloc(struct slab *slab_pool, ul arg);
/**
* @brief slab内存池中的对象
*
* @param slab_pool
* @param addr
* @param arg
* @return ul
*/
ul slab_free(struct slab* slab_pool, void* addr, ul arg);