看csapp寫記憶體 Clerk

來源:互聯網
上載者:User

標籤:

目標:實現一個放置策略為首次適配,併合策略為立即併合基於隱式空閑鏈表的記憶體 Clerk。


這裡使用memlib.c包提供的儲存空間系統模型,該模型允許我們在不干涉已存在的malloc包的情況下運行分配器,也就是說封裝了malloc函數。

memlib.h

void mem_init(void);void *mem_sbrk(int incr);


memlib.c:(封裝了malloc函數)

#include <stdio.h>#include <stdlib.h>#include "csapp.h"#define MAX_HEAP (1 << 30)static char *mem_heap;     /* Points to first byte of heap */ static char *mem_brk;      /* Points to last byte of heap plus 1 */static char *mem_max_addr; /* Max legal heap addr plus 1*/ void mem_init(void){    mem_heap = (char *)Malloc(MAX_HEAP);    mem_brk = (char *)mem_heap;                   mem_max_addr = (char *)(mem_heap + MAX_HEAP); }/*  * mem_sbrk - Simple model of the sbrk function. Extends the heap  *    by incr bytes and returns the start address of the new area. In *    this model, the heap cannot be shrunk. */void *mem_sbrk(int incr) {    char *old_brk = mem_brk;    if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) {errno = ENOMEM;fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n");return (void *)-1;    }    mem_brk += incr;    return (void *)old_brk;}

mm.h

/*************************************************************************    > File Name: mm.h    > Author: connan_d    > Mail: [email protected]     > Created Time: 2015年05月07日 星期四 10時40分49秒    > 定義了記憶體 Clerk的介面 ************************************************************************/int mm_init();//初始化void *mm_malloc(size_t size);//分配記憶體void mm_free(void *bp);//回收記憶體

mm.c

/*************************************************************************    > File Name: mm.c    > Author: connan_d    > Mail: [email protected]     > Created Time: 2015年05月07日 星期四 10時50分51秒 ************************************************************************/#include<stdio.h>#include "mm.h"#include "memlib.h"static void *extend_heap(size_t words);//拓展堆的可用空間,返回原堆頂地址(mem_brk),失敗返回NULLstatic void *coalesce(void *bp);//併合bp指向塊的前後塊,返回併合後的塊指標static void *find_fit(size_t size);//尋找第一個空間大於size的空閑塊,返回其地址,未找到時,返回NULLstatic void place(void *bp, size_t asize);//分割find_fit返回的塊,建立塊結構//宏定義#define WSIZE 4#define DSIZE 8#define CHUNKSIZE (1<<12)//每次拓展堆的大小#define MAX(x, y) ((x) > (y) ? (x) : (y))#define PACK(size, alloc) ((size) | (alloc))//將塊大小和標誌位整合到一個字中#define GET(p)(*(unsigned int *)(p))//返回p指向的字#define PUT(p, val) (*(unsigned int *)(p) = (val))//將值壓入p指向的字#define GET_SIZE(p)(GET(p) & ~0x7)//返回頭或尾部的高29位,即該塊的大小#define GET_ALLOC(p)(GET(p) & 0x1)//返回標誌位#define HDRP(bp)((char *)bp - WSIZE)//返回塊的頭部#define FTRP(bp)((char *)bp + GET_SIZE(bp) - DSIZE)//返回塊的尾部#define NEXT_BLKP(bp)((char *)(bp) + GET_SIZE((char *)bp - WSIZE))//當前當塊的下一塊#define PREV_BLKP(bp)((char *)bp - GET_SIZE((char *)bp - DSIZE))//返回但前塊的上一塊static void *heap_listp;//指向第一個塊(序言塊)//介面int mm_init(void)//初始化,成功返回0,失敗返回{mem_init();if ( (heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)return -1;PUT(heap_listp, 0);PUT(heap_listp + WSIZE, PACK(8, 1));//序言塊頭部PUT(heap_listp + 2*WSIZE, PACK(8, 1));//序言塊尾部PUT(heap_listp + 3*WSIZE, PACK(0, 1));//結尾塊heap_listp += 2*WSIZE;if (extend_heap(CHUNKSIZE/WSIZE) == NULL)return -1;return 0;}void mm_free(void *bp)//釋放bp指向塊的記憶體{size_t size = GET_SIZE(HDRP(bp));PUT(HDRP(bp), PACK(size, 0));PUT(FTRP(bp), PACK(size, 0));coalesce(bp);//併合前後塊}void *mm_malloc(size_t size)//分配size位元組大小的塊,返回指向塊的指標{size_t asize;//調整過的sizesize_t extendsize;void *bp;if (size == 0)return NULL;if (size < DSIZE)asize = 2 * DSIZE;elseasize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);if ( (bp = find_fit(asize)) != NULL){place(bp, asize);return bp;}extendsize = MAX(asize,  CHUNKSIZE);if ( (bp = extend_heap(extendsize/WSIZE)) == NULL )return NULL;place(bp, asize);return bp;}//工具函數定義static void *extend_heap(size_t words)//拓展堆的可用空間,返回原堆頂地址(mem_brk),失敗返回NULL{char *bp;size_t size;size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;//保持雙字對齊if ((long)(bp = mem_sbrk(size)) == -1)return NULL;PUT(HDRP(bp), PACK(size, 0));PUT(FTRP(bp), PACK(size, 0));PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));return (void *)bp;}static void *coalesce(void *bp)//併合bp指向塊的前後塊,返回併合後的塊指標{size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(bp)));//上一塊是否分配size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));//下一塊是否分配size_t size;if (prev_alloc && next_alloc) {return bp;}    else if (prev_alloc && !next_alloc){size += GET_SIZE(HDRP(NEXT_BLKP(bp)));PUT(HDRP(bp), PACK(size, 0));PUT(FTRP(bp), PACK(size,0));} else if (!prev_alloc && next_alloc) {size += GET_SIZE(HDRP(PREV_BLKP(bp)));PUT(FTRP(bp), PACK(size, 0));PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));bp = PREV_BLKP(bp);}else{size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));bp = PREV_BLKP(bp);}return bp;}static void *find_fit(size_t size)//尋找第一個空間大於size的空閑塊,返回其地址,未找到時,返回NULL{void *bp;for (bp = heap_listp; GET_SIZE(bp) > 0; bp = NEXT_BLKP(bp)){if (GET_SIZE(HDRP(bp)) >= size && GET_ALLOC(HDRP(bp)) != 1)//返回第一塊未分配且空間大於size的空閑塊return bp;}return NULL;}static void place(void *bp, size_t asize)//分割find_fit返回的塊,建立塊結構{size_t bsize = GET_SIZE(HDRP(bp));if ( (bsize - asize) > 2*DSIZE )//最小塊為16位元組,分割塊{PUT(HDRP(bp), PACK(asize, 1));PUT(FTRP(bp), PACK(asize, 1));bp = NEXT_BLKP(bp);PUT(HDRP(bp), PACK(bsize - asize, 0));PUT(FTRP(bp), PACK(bsize - asize, 0));}else//不用分割{PUT(HDRP(bp), PACK(asize, 1));PUT(FTRP(bp), PACK(asize, 1));}}

mmTest.c

/*************************************************************************    > File Name: mmTest.c    > Author: connan_d    > Mail: [email protected]     > Created Time: 2015年05月07日 星期四 14時23分30秒 ************************************************************************/#include<stdio.h>#include "mm.h"int main(){mem_init();                                     //初始化模型mm_init();                                     //初始化分配器int *a = mm_malloc(sizeof(int));//測試int*a = 1;char *b = mm_malloc(sizeof(char));//測試char*b = 'z';double *c = mm_malloc(sizeof(double));        //測試double*c = 2.0;printf("a = %d\nb = %c\nc = %f\n", *a, *b, *c);}

編譯連結時需要csapp.h標頭檔:gcc -o mmtest mmTest.c mm.c memlib.c -lpthread

結果:


看csapp寫記憶體 Clerk

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.