【 聲明:著作權,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】
固定記憶體方式是最簡單的方法,也是最容易想到的方法。所謂的固定記憶體,就是所有分配的記憶體單元都是一致的。不管你申請的記憶體大小是多少,它都有一個最小的記憶體。因此,你申請的記憶體都會轉化為單元記憶體的倍數。所以,演算法會根據申請的記憶體計算出一個合適的申請記憶體,
int get_best_fit_size(int size){ int bestSize = UNIT_SIZE; while(bestSize < size && bestSize != MEMORY_SIZE) { bestSize <<= 1; } if(MEMORY_SIZE == bestSize) { return 0; } return bestSize;}
有了合適的記憶體大小之後,你還需要判斷是否有合適的記憶體。關鍵就是檢查記憶體flag標記,判斷是否存在連續的記憶體,有的話就分配給你;如果沒有,那也沒辦法。這裡為了簡單,我們就用了最快分配的原則,找到一個合適的記憶體就立馬返回。
int check_if_buffer_exist(int bufferSize, char* pStart){ int number = bufferSize / UNIT_SIZE; int index; for(index = 0; index < number; index ++) { if(&pStart[index] >= ((char*)pMemAddr + TOTAL_UNIT)) return 0; if(0 != pStart[index]) return 0; } return 1 ;}
當然分配到了記憶體之後,我們就需要進行標記,即註明當前記憶體已經分配了;當然在釋放的時候我們還要把這些標記給清除出去。
void set_memory_used_flag(int bufferSize, char* pData, char flag){ int offset = (pData - (char*)pMemAddr - TOTAL_UNIT - MEM_SIZE_UNIT) / UNIT_SIZE; int index; for(index = 0; index < (bufferSize / UNIT_SIZE); index ++) { ((char*) pMemAddr + offset )[index] = flag; }}
有了所有的這些條件,其實我們就可以有一個基本的記憶體配置函數了。下面我們會給出一個完整的記憶體配置案例,記憶體的空間內容是這樣安排的:(1)記憶體標誌;(2)記憶體大小標記;(3)記憶體空間。其實(1)和(2)事實上都是管理記憶體的內容,但是也是必須分配的部分。打個比方來說,我們知道國家是需要向公民收稅的,但是收的稅不可能全部進國庫。因為收稅本身是有成本的,你必須把這一部分錢提前拿出來。
/******************************************************** memory alloc & free file********************************************************/#include <stdio.h>#include <malloc.h>#include <string.h>/******************************************************** macro definition********************************************************/#define MEMORY_SIZE (0x1 << 24)#define UNIT_SIZE (0x1 << 12)#define TOTAL_UNIT (MEMORY_SIZE / UNIT_SIZE)#define MEM_SIZE_UNIT (TOTAL_UNIT << 2)/******************************************************** global data definition********************************************************/static void* pMemAddr;/******************************************************** function: initial memory module function********************************************************/void memory_init(){ int index; /* alloca memory */ pMemAddr = (void*)malloc(MEMORY_SIZE); if(NULL == pMemAddr) return; /* initial global data */ memset(pMemAddr, 0, MEMORY_SIZE); /* set mng memory flag */ for(index = 0; index < ((TOTAL_UNIT + UNIT_SIZE - 1 ) / UNIT_SIZE) ; index++) *((char*)pMemAddr + index) = 1;}/******************************************************** function: find best size for the memory********************************************************/int get_best_fit_size(int size){ int bestSize = UNIT_SIZE; while(bestSize < size && bestSize != MEMORY_SIZE) { bestSize <<= 1; } if(MEMORY_SIZE == bestSize) { return 0; } return bestSize;}/******************************************************** function: check if buffer still exists********************************************************/int check_if_buffer_exist(int bufferSize, char* pStart){ int number = bufferSize / UNIT_SIZE; int index; for(index = 0; index < number; index ++) { if(&pStart[index] >= ((char*)pMemAddr + TOTAL_UNIT)) return 0; if(0 != pStart[index]) return 0; } return 1 ;}/******************************************************** function: process memory allocation********************************************************/char* _mem_malloc(int bufferSize){ int index; for(index = 0; index < TOTAL_UNIT; index ++) { if(check_if_buffer_exist(bufferSize, (char*)pMemAddr + index)) break; } if(TOTAL_UNIT == index) return NULL; return (char*)pMemAddr + TOTAL_UNIT + MEM_SIZE_UNIT + UNIT_SIZE * index;}/******************************************************** function: set the applied memory size********************************************************/void set_memory_size(int bufferSize, char* pData){ int offset = (pData - (char*)pMemAddr - TOTAL_UNIT - MEM_SIZE_UNIT) / UNIT_SIZE; int number = bufferSize / UNIT_SIZE; ((int*)((char*) pMemAddr + TOTAL_UNIT ))[offset] = number;}/******************************************************** function: get the applied memory size from address********************************************************/int get_memory_size(char* pData){ int offset = (pData - (char*)pMemAddr - TOTAL_UNIT - MEM_SIZE_UNIT) / UNIT_SIZE; return ((int*)((char*) pMemAddr + TOTAL_UNIT))[offset];}/******************************************************** function: set memory used flag********************************************************/void set_memory_used_flag(int number, char* pData, char flag){ int offset = (pData - (char*)pMemAddr - TOTAL_UNIT - MEM_SIZE_UNIT) / UNIT_SIZE; int index; for(index = 0; index < number; index ++) { ((char*) pMemAddr + offset )[index] = flag; }}/******************************************************** function: allocate memory from buffer********************************************************/void* mem_malloc(int size){ int bufferSize; char* pData; if(0 == size) return NULL; bufferSize = get_best_fit_size(size); if(0 == bufferSize) return NULL; if(NULL == (pData = _mem_malloc(bufferSize))) return NULL; set_memory_used_flag(bufferSize / UNIT_SIZE, pData, 1); set_memory_size(bufferSize, pData); return (void*)pData;}/******************************************************** function: free memory to buffer********************************************************/void mem_free(char* pData){ int number; if(NULL == pData) return; if(pData >= (char*) pMemAddr && pData < ((char*) pMemAddr + TOTAL_UNIT + MEM_SIZE_UNIT)) return; if(0 == (number = get_memory_size(pData))) return; set_memory_size(0, pData); set_memory_used_flag(number, pData, 0);}/******************************************************** function: free all memory********************************************************/void memory_exit(){ free(pMemAddr);}/******************************************************** function: file entry starts here********************************************************/int main(int argc, char* argv[]){ memory_init(); memory_exit(); return 1;}