#include <stdio.h>
#define MEM_SIZE 128
static char mem[MEM_SIZE];
#define MINBLK 16
struct block {
struct block * next;
size_t length;
char data[0];
};
//维护一个空闲链表
static struct block * free_list = NULL;
void malloc_init(void)
{
free_list = (struct block *)mem;
free_list->next = NULL;
free_list->length = MEM_SIZE - sizeof(struct block);
}
void * malloc(size_t size)
{
//需要做字节对齐,下边详细分析【1】
//先确定空间大小
size = (size + 7) & ~7;
struct block * prev = (struct block *) &free_list;
struct block * cur = free_list;
//检查每一个块,如果不为空,看看块的大小是否可以满足size要求
while (cur != NULL) {
//直到找到一个满足要求的块
if (cur->length >= size) break;
prev = cur;
cur = cur->next;
}
//没有满足要求的块,malloc失败
if (cur == NULL)
return NULL;
//如果满足size的块比请求大小大很多,可以将此块分成两块,变成另一个空闲块
if ((cur->length - size) >= MINBLK) {
struct block * temp = (struct block *)(cur->data + size);
temp->next = cur->next;
temp->length = cur->length - size - sizeof(struct block);
prev->next = temp;
cur->length = size;
} else {
//不进行分块,直接使用掉本块
prev->next = cur->next;
}
return cur->data;
}
void free(void * ptr)
{
if (ptr == NULL)
return;
struct block * temp = (struct block *)((char *)ptr - sizeof(struct block));
char * tempn = (char *)ptr + temp->length; // 和temp物理上相邻的下一个block的地址
struct block * prev = (struct block *) &free_list;
struct block * cur = free_list;
char * curn; // 和cur物理上相邻的下一个block的地址
// 考虑多种情况,完成free函数
// ... ...
}
void malloc_state(void)
{
printf("free blocks:\n");
struct block * ptr;
for (ptr = free_list; ptr != NULL; ptr = ptr->next) {
int i;
printf("%p:", ptr);
for (i = 0; i < ptr->length; i++) {
printf("=");
}
printf(" ");
}
printf("\n");
}
void malloc_test(void)
{
}
int main(int argc, const char *argv[])
{
malloc_init();
malloc_test();
return 0;
}
【1】在C语言中,CPU在读取数据数据的时候,是成块的读取的,如果可以在一次读取中就把数据全部读出,可以提高读取效率,如果要读两次说明存储有问题,通过字节对齐可以是数据都可以在一次读取中读到。
- 如果变量a和b紧挨着的话,b会存储在1-5Bytes上,而读取的时候是每4Byetes进行读取,则需要先读取0-4Bytes再读取4-8Bytes才可以获得b变量的数据,而上述存储方式就可以避免这种情况,通过空余一些空间,实现字节对齐。
- malloc函数在分配空间的时候同样需要考虑字节对齐,对齐方式是地址为8的倍数,例如当申请1-8大小的空间的时候,都需要为其分配大小为8的空间
- 也就是只需要将size转换成二进制和
1111 1111 1111 1000
进行与操作即可,可以保证最后三位为0,即可保证8的倍数,但是,为了避免1-7的size直接对齐为0,需要将size+7
再进行与操作