您的位置:首页 > 其它

用两个哈希表加链表实现malloc

2009-07-30 11:06 363 查看
QZone Editor
.dump{}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//mini_malloc.h头文件

#include <stdio.h>

#include <stdlib.h>

#define MAXMEM 10000

#define HASHSIZE 100

#define NODESIZE sizeof(Node)

typedef struct Node {

char _use;

size_t _size;

struct Node *_prev;

struct Node *_next;

struct Node *_freeprev;

struct Node *_freenext;

struct Node *_usedprev;

struct Node *_usednext;

} Node;

extern Node *usedHashTable[HASHSIZE];

extern Node *freeHashTable[HASHSIZE];

extern Node *L;

extern char *P;

void *mini_malloc(size_t size);

void mini_free(void *addr);

­
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//mini_malloc.c内存分配与释放

/*

设计要求:要求用两个哈希表加链表实现malloc,其中一个哈希管理空闲内存,一个哈希管理占用内存,

     当发生冲突时用采用链表解决冲突。

设计思路:

     freeHash函数设计思路

     空闲内存以100个字节为一个跨度分部在freeHashTable上,比如:空闲内存字节数为1~100则

     放在freeHashTable表第0项,空闲内存字节数为101~200则放在freeHashTable表第1项,依此

     类推。当发生冲突时,按内存字节数从小到大以链表方式排列插入freeHashTable相应项中。

     以此保证每次查找到的满足需求的空闲内存字节数是所有满足需求的空闲内存中最接近需求的,

     在某些情况下可以一定程度减少内存浪费。

     usedHash函数设计思路

     在usedHashTable中没有做特需设计,就是一个普通的哈希链表。当发生冲突时push到

     usedHashTable相应项的最前面,以提高插入时的效率。

主要变量:P 总内存块(10000字节)

     L 总链表

     usedHashTable[HASHSIZE] 占用内存哈希表

     freeHashTable[HASHSIZE] 空闲内存哈希表

*/

#include "mini_malloc.h"

char *P = '/0';

Node *L = NULL;

Node *usedHashTable[HASHSIZE] = {NULL};

Node *freeHashTable[HASHSIZE] = {NULL};

//将指定节点按从小到大排序方式插入到相应的freeHashTable项中

void insertFree(Node **pNode);

//将指定节点插入到相应的usedHashTable项最前面

void pushUsed(Node **pNode);

//删除freeHashTable中相应的节点

void delFree(Node **pNode);

//删除usedHashTable中相应的节点

void delUsed(Node **pNode);

//删除总链表L中相应的节点

void delMain(Node **pNode);

//mini_malloc初始化

void init_malloc();

//根据指定的freeHashTable项与指定的内存字节数,查找符合需求的内存并返回其内存地址

void *find_malloc(Node *head, size_t size);

//freeHash函数,按需求内存字节数size生成一个freeHashTable的key

int freeHash(size_t size);

//usedHash函数,按给定的内存地址addr生成一个usedHashTable的key

int usedHash(void *addr);

void init_malloc();

int freeHash(size_t size) {

return ((size - 1) / HASHSIZE) % HASHSIZE;

}

int usedHash(void *addr) {

return ((int)addr) % HASHSIZE;

}

void init_malloc() {

P = (char *)malloc(MAXMEM);

//初始化总链表

L = (Node *)P;

L->_use = '/0';

L->_size = (size_t)(MAXMEM - NODESIZE);

L->_prev = NULL;

L->_next = NULL;

L->_freeprev = NULL;

L->_freenext = NULL;

L->_usedprev = NULL;

L->_usednext = NULL;

//将空闲内存挂载到freeHashTable中

freeHashTable[freeHash((size_t)L->_size)] = L;

}

void *find_malloc(Node *head, size_t size) {

size_t fsize = 0;

while (head) {

fsize = head->_size; //当前节点可用内存字节数

if (fsize >= size) { //如果当前节点可用内存字节数满足需求字节数

head->_use = '1'; //将当前节点标记为占用

pushUsed(&head); //将当前节点push到usedHashTable中

delFree(&head); //从freeHashTable中删除当前节点

//如果当前节点可用内存字节数减去需求字节数,剩余字节数可以建立一个新节点

if (fsize - size > NODESIZE) {

//修改head节点字节数为需求字节数

head->_size = size;

//新建节点

Node *pNode = (Node *)((char *)head + NODESIZE + size);

//标记节点内存为空闲

pNode->_use = '/0';

//新建节点内存字节数为剩余字节数

pNode->_size = fsize - size - NODESIZE;

//将新建节点插入到L中

pNode->_prev = head;

pNode->_next = NULL;

pNode->_freeprev = NULL;

pNode->_freenext = NULL;

pNode->_usedprev = NULL;

pNode->_usednext = NULL;

if (head->_next != NULL) {

pNode->_next = head->_next;

head->_next->_prev = pNode;

}

head->_next = pNode;

//将新建节点插入到freeHashTable中

insertFree(&pNode);

}

return (void *)((char *)head + NODESIZE);

}

head = head->_freenext;

}

return NULL;

}

void *mini_malloc(size_t size) {

if (L == NULL)

init_malloc();

//根据需求size获取freeHashTable的key

int key = freeHash(size);

void *T;

//查找满足需求的freeHashTable项,将当前key项为NULL时,查询下一项

while (key < HASHSIZE) {

T = find_malloc(freeHashTable[key], size);

if (T != NULL) {

return T;

}

++key;

}

return NULL;

}

void mini_free(void *addr) {

//根据addr减去NODESIZE获取实际addr对应的节点地址所对应的usedHashTable的key

int key = usedHash((void *)((char *)addr - NODESIZE));

Node *head = usedHashTable[key];

while (head) {

if ((Node *)((char *)addr - NODESIZE) == head) {

head->_use = '/0';

Node *pNode = head;

//将当前节点从usedHashTable中删除

delUsed(&head);

//当前节点的下一节点内存为空闲时,则合并它

if (head->_next != NULL && head->_next->_use == '/0') {

//将此节点从freeHashTable中删除

delFree(&(head->_next));

//将此节点从总链表L中删除

delMain(&(head->_next));

}

//当前节点的前一节点内存为空闲时,则合并它

if (head->_prev != NULL && head->_prev->_use == '/0') {

//将pNode指向新的节点地址

pNode = head->_prev;

//将head的前一节点从freeHashTable中删除

delFree(&pNode);

//将head从总链表L中删除

delMain(&head);

}

//将新释放的节点插入到freeHashTable中

insertFree(&pNode);

return;

}

head = head->_usednext;

}

}

void insertFree(Node **pNode) {

if (*pNode == NULL)

return;

int key = freeHash((*pNode)->_size);

Node *head = freeHashTable[key];

if (head == NULL) {

freeHashTable[key] = *pNode;

freeHashTable[key]->_freeprev = NULL;

freeHashTable[key]->_freenext = NULL;

return;

}

while (head) {

if (head->_size > (*pNode)->_size) {

if (head->_freeprev == NULL) {

(*pNode)->_freenext = freeHashTable[key];

freeHashTable[key]->_freeprev = *pNode;

freeHashTable[key] = *pNode;

freeHashTable[key]->_freeprev = NULL;

}

else {

(*pNode)->_freenext = head;

(*pNode)->_freeprev = head->_freeprev;

head->_freeprev->_freenext = *pNode;

head->_freeprev = *pNode;

}

return;

}

if (head->_freenext != NULL) {

head = head->_freenext;

}

else {

break;

}

}

head->_freenext = *pNode;

(*pNode)->_freeprev = head;

(*pNode)->_freenext = NULL;

}

void pushUsed(Node **pNode) {

if (*pNode == NULL)

return;

int key = usedHash((void *)(*pNode));

Node *head = usedHashTable[key];

if (head == NULL) {

usedHashTable[key] = *pNode;

usedHashTable[key]->_usedprev = NULL;

usedHashTable[key]->_usednext = NULL;

}

else {

while (head) {

if (head == *pNode) {

head->_use = (*pNode)->_use;

head->_size = (*pNode)->_size;

return;

}

head = head->_usednext;

}

(*pNode)->_usednext = usedHashTable[key];

usedHashTable[key]->_usedprev = *pNode;

usedHashTable[key] = *pNode;

usedHashTable[key]->_usedprev = NULL;

}

}

void delFree(Node **pNode) {

if (*pNode == NULL)

return;

int key = freeHash((*pNode)->_size);

Node *head = freeHashTable[key];

while (head) {

if (head == *pNode) {

if (head->_freeprev != NULL) {

if (head->_freenext != NULL) {

head->_freeprev->_freenext = head->_freenext;

head->_freenext->_freeprev = head->_freeprev;

}

else {

head->_freeprev->_freenext = NULL;

}

}

else {

if (head->_freenext != NULL) {

freeHashTable[key] = head->_freenext;

freeHashTable[key]->_freeprev = NULL;

}

else {

freeHashTable[key] = NULL;

}

}

return;

}

head = head->_freenext;

}

}

void delUsed(Node **pNode) {

if (*pNode == NULL)

return;

int key = usedHash((void *)(*pNode));

Node *head = usedHashTable[key];

while (head) {

if (head == *pNode) {

if (head->_usedprev != NULL) {

if (head->_usednext != NULL) {

head->_usedprev->_usednext = head->_usednext;

head->_usednext->_usedprev = head->_usedprev;

}

else {

head->_usedprev->_usednext = NULL;

}

}

else {

if (head->_usednext != NULL) {

usedHashTable[key] = head->_usednext;

usedHashTable[key]->_usedprev = NULL;

}

else {

usedHashTable[key] = NULL;

}

}

return;

}

head = head->_usednext;

}

}

void delMain(Node **pNode) {

Node *T = *pNode;

if (T == NULL)

return;

if (T->_prev != NULL) {

T->_prev->_size = T->_prev->_size + T->_size + NODESIZE;

if (T->_next != NULL) {

T->_prev->_next = T->_next;

T->_next->_prev = T->_prev;

}

else {

T->_prev->_next = NULL;

}

}

else {

printf("ERROR./n");

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: