总述
Lvgl有一套自己的内存管理,在指定大小的内存上做内存的申请与释放操作,从而控制整个内存使用。
原理
类似链表的方式实现内存单元的串连,内存布局如下:
lv_mem_ent_t 数据结构
typedef union {
struct {
MEM_UNIT used : 1; /* 1: if the entry is used*/
MEM_UNIT d_size : 31; /* Size off the data (1 means 4 bytes)*/
} s;
MEM_UNIT header; /* The header (used + d_size)*/
} lv_mem_header_t;
typedef struct {
lv_mem_header_t header;
uint8_t first_data; /*First data byte in the allocated data (Just for easily create a pointer)*/
} lv_mem_ent_t;
使用first_data字段地址作为内存分配使用的起始地址,通过在first_data地址偏移d_size可以找到下一个内存单元
uint8_t * data = &act_e->first_data;
next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size];
内存分配:
通过初始的内存单元依次查找符合申请内存大小的未使用的内存单元,后从中截断形成分配给用户使用的内存单元和未使用的内存单元
lv_mem_ent_t * e = NULL;
/* Search for a appropriate entry*/
do {
/* Get the next entry*/
e = ent_get_next(e);
/*If there is next entry then try to allocate there*/
if(e != NULL) {
//判断是否有足够的内存大小,如果有则进行截断分配
alloc = ent_alloc(e, size);
}
/* End if there is not next entry OR the alloc. is successful*/
} while(e != NULL && alloc == NULL);
内存释放;
将used字段清零,并累计释放达到一定次数后,进行空闲内存单元合并处理,减少内存碎片
static uint16_t full_defrag_cnt = 0;
full_defrag_cnt++;
if(full_defrag_cnt < LV_MEM_FULL_DEFRAG_CNT) {
/* Make a simple defrag.
* Join the following free entries after this*/
//合并相邻的内存单元
lv_mem_ent_t * e_next;
e_next = ent_get_next(e);
while(e_next != NULL) {
if(e_next->header.s.used == 0) {
e->header.s.d_size += e_next->header.s.d_size + sizeof(e->header);
}
else {
break;
}
e_next = ent_get_next(e_next);
}
}
else {
full_defrag_cnt = 0;
lv_mem_defrag();
}
总结
一般的内存管理以及Flash的存储管理,基本原理与此类似,基本都是数据头加数据体再基于链表数据结构进行管理。
注意: 内存分配的时候并不是刚好申请需要的大小,一般都是基于某个大小进行对齐处理,这样 能提高访问效率