该文章用作个人纪录。

简要介绍一下两种内存管理算法:

1.小内存管理算法

采用不断分割的方法对内存进行动态分配,分为初始化,分割,释放三个步骤,为了简洁起见,笔者直接放图:

1
2
3
4
5
6


graph LR
A(头部)-->B(初始大内存块)-->C(尾部)


1
2
graph LR
A(头部)-->B(内存块)-->C(内存块)-->D(内存块)-->E(内存块)-->T(尾部)

这是整体思想,通过对初始内存块的不断切割,最终形成了各个不同的内存块。

四个函数,第一个init:

1
2
graph LR
A(头部)-->B(内存块)-->C(尾部)
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*sk
*ai
*ui
*ji
*ng
*/

void heap_init()
{

heap_node *firstnode;
//这行注释不要删除
//命名不要随便改,不然有概率导致数组最后八个字节出现segmentation fault问题

uint32_t start_heap ,end_heap;
//get start address
start_heap =(uint32_t) allheap;

/*byte aligment*/
if( (start_heap & aligment_byte) != 0){
start_heap += aligment_byte ;
start_heap &= ~aligment_byte;
theheap.allsize -= (size_t)(start_heap - (uint32_t)allheap);//byte aligment means move to high address,so sub it!
}

theheap.head.next = (heap_node *)start_heap;
theheap.head.blocksize = (size_t)0;

end_heap = ( start_heap + (uint32_t)config_heap);


/*byte aligment*/
if( (end_heap & aligment_byte) != 0){
end_heap += aligment_byte ;
end_heap &= ~aligment_byte;
theheap.allsize = (size_t)(end_heap - start_heap );

}
theheap.tail = (heap_node*)end_heap;
theheap.tail->blocksize = 0;
theheap.tail->next =NULL;

firstnode = (heap_node*)start_heap;
firstnode->next = theheap.tail;

firstnode->blocksize = theheap.allsize;

}

第二个malloc:

1
2
3
4
graph LR
A(头部)--从头开始找_直到找到符合大小的内存块-->B(内存块)-->C(内存块)-->D(内存块)-->E(内存块)-->T(尾部)


1
2
3
graph LR
G(链表起始)--把初始化的内存链表模型作为空闲内存块建立的链表-->F(结束)
A(prev)--在这条链表上找到符合条件的内存块-->B(use)-->C(new)

这条链表上就是空闲内存块链表,内存块被使用就被踢出这条链表,被释放就加入这条链表,如果内存块大于要申请的大小,就把多余的部分切割,然后加入这条内存链表。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

void *heap_malloc(size_t wantsize)
{
heap_node *prevnode;
heap_node *usenode;

heap_node *newnode;
size_t aligmentrequisize;

void *xReturn = NULL;

if(wantsize <= 0 )
{
printf("Error in function: %s at line: %d\n", __func__, __LINE__); \
exit(-1);

}


wantsize += heapstructSize;
if((wantsize & aligment_byte) != 0x00)
{
aligmentrequisize = aligment_byte - (wantsize & aligment_byte);
wantsize += aligmentrequisize;
}


if((wantsize / arm_max_memory) != 0)
{
printf("Error in function: %s at line: %d\n", __func__, __LINE__); \
exit(-1);

}

//I will add the TaskSuspend function ,that make there be a atomic operation
if(theheap.tail== NULL )
{
heap_init();
}

//

prevnode = &theheap.head;
usenode = theheap.head.next;


//the next is valid ?

while((usenode->blocksize) < wantsize )
{
prevnode = usenode;
usenode = usenode ->next;
}

//

if(usenode == theheap.tail)
{
printf("Error in function: %s at line: %d\n", __func__, __LINE__); \
exit(-1);
}

xReturn = (void*)(((uint8_t*)usenode) + heapstructSize);

prevnode->next = usenode->next ;
/*apart it!*/
if( (usenode->blocksize - wantsize) > MIN_size )
{
newnode = (void*)(((uint8_t*)usenode) + wantsize);

newnode->blocksize = usenode->blocksize - wantsize;
usenode->blocksize = wantsize;


newnode->next = prevnode->next ;
prevnode->next = newnode;

}


theheap.allsize-= usenode->blocksize;



if(theheap.allsize < 0U)
{
printf("Error in function: %s at line: %d\n", __func__, __LINE__); \
exit(-1);
}

usenode->next = NULL;

// I will write the TaskResume





if(usenode > theheap.tail)
{

printf("alheap : %d ,use: %d, tail: %d\n",allheap,usenode,theheap.tail);
printf("fuck : %s at line: %d\n", __func__, __LINE__);
exit(-1);
}


return xReturn;


}

第三个free:

1
2
3
4
graph LR
A(空闲内存块)-->D(空闲内存块)-->B(空闲内存块);

C(Insert)-->D(空闲内存块);

直接插入即可。

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
void heap_free(void *xret)
{
uint8_t *xFree = (uint8_t*)xret;
heap_node *xlink;

if(xFree == NULL)
{
printf("Error in function: %s at line: %d\n", __func__, __LINE__); \
exit(-1);
}

xFree -= heapstructSize;
xlink = (void*)xFree;
if(xlink->next != NULL)
{
printf("Error in function: %s at line: %d\n", __func__, __LINE__); \
exit(-1);
}

// I will tasksuspend
theheap.allsize += xlink->blocksize;
InsertFreeBlock((heap_node*)xlink);

// I will TaskResume


}

精髓在于InsertFreeBLOCK:

1
2
3
4
5
graph LR
A(开始)-->B(prev)-->C(next)-->D(结束);
E(Insert)-->G(?)


1
2
3
4
graph LR
A(start)-->B-->C(Insert)-->D-->E-->G(end);


后:

1
2
3
graph LR
A(start)--后相邻-->B-->C(Insert)-->E-->F(end);
D-->E;

等价于:

1
2
3
graph LR
A(start)--后相邻-->B-->C(Insert + D)-->E-->F(end);

前:

1
2
3
4
graph LR

A(start)--前相邻-->B-->D-->E-->F(end);
C(Insert)-->D;

等价于:

1
2
3
4
graph LR

A(start)--前相邻-->B(B+Insert)-->D-->E-->F(end);

前+后:注:B直接指向E

1
2
graph LR
A(start)--可以只考虑最终结果-->B--Insert + D-->E-->F(end);

等价于:

1
2
3
4
graph LR

A(start)--可以只考虑最终结果-->B(B + Insert +D)-->E-->F(end);

如果前后相邻是相互独立的,那么互不影响,如果不独立,通过后,前的顺序可以得到前后都相邻的结果,因此该顺序正确。

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
xInsertBlock->next = first_fitnode->next;
first_fitnode->next = xInsertBlock;

getaddr = (uint8_t*)xInsertBlock;
if((getaddr + xInsertBlock->blocksize) == (uint8_t*)(xInsertBlock->next))
{

if(xInsertBlock->next != theheap.tail )
{
xInsertBlock->blocksize += xInsertBlock->next->blocksize;
xInsertBlock->next = xInsertBlock->next->next;
}
else
{
xInsertBlock->next = theheap.tail;
}
}



getaddr = (uint8_t*)first_fitnode;

if((getaddr + first_fitnode->blocksize) == (uint8_t*) xInsertBlock)
{
first_fitnode->blocksize += xInsertBlock->blocksize;
first_fitnode->next = xInsertBlock->next;
}