CSAPP第九章家庭作业参考答案

(CSAPP第三版系列)导航篇传送门


9.12 对于下面的地址,重复习题9.11:

虚拟地址: 0x03a9 

A. 虚拟地址格式


B. 地址翻译

参数

VPN

0xE

TLB索引

0x2

TLB标记

0x3

TLB命中?(是/否)

缺页?(是/否)

PPN

0x11

C. 物理地址格式


D. 物理地址引用

参数

字节偏移

0x1

缓存索引

0xA

缓存标记

0x11

缓存命中?(是/否)

返回的缓存字节

——


9.14 编写一个C程序,使用mmap将hello.txt的内容改变为“Jello,world!\n”。

程序如下(已经过运行测试):

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main()
{
    int fd = open("hello.txt",O_RDWR,0);
    char *start = mmap(NULL,1,PROT_WRITE,MAP_SHARED,fd,0);
    close(fd);
    if(start == MAP_FAILED)
		printf("error!\n");
	else
	{
		*start = 'J';
    	munmap(start,1);
		return 0;
	}
}


9.16确定下面对齐要求和块格式的每个组合的最小块大小。

对齐要求

已分配块

空闲块

最小块大小(字节)

单字

头部和脚部

头部和脚部

16

单字

头部,但是没有脚部

头部和脚部

12

双字

头部和脚部

头部和脚部

16

双字

头部,但是没有脚部

头部和脚部

16


9.18修改分配器,使得空闲块需要头部和脚部,而已分配块只需要头部。

mm.c文件:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "mm.h"
#include "memlib.h"

/* $begin mallocmacros */
/* Basic constants and macros */
#define WSIZE       4       /* Word and header/footer size (bytes) */ //line:vm:mm:beginconst
#define DSIZE       8       /* Double word size (bytes) */
#define CHUNKSIZE  (1<<12)  /* Extend heap by this amount (bytes) */  //line:vm:mm:endconst

#define MAX(x, y) ((x) > (y)? (x) : (y))

/* Pack a size and allocated bit into a word */
#define PACK(size, alloc)  ((size) | (alloc)) //line:vm:mm:pack

/* Read and write a word at address p */
#define GET(p)       (*(unsigned int *)(p))            //line:vm:mm:get
#define PUT(p, val)  (*(unsigned int *)(p) = (val))    //line:vm:mm:put

/* Read the size and allocated fields from address p */
#define GET_SIZE(p)  (GET(p) & ~0x7)                   //line:vm:mm:getsize
#define GET_ALLOC(p) (GET(p) & 0x1)                    //line:vm:mm:getalloc
#define GET_PREVIOUS_ALLOC(p) (GET(p) & 0x2) /* ! CHANGED ! */

/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp)       ((char *)(bp) - WSIZE)                      //line:vm:mm:hdrp
#define FTRP(bp)       ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) //line:vm:mm:ftrp

/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp)  ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) //line:vm:mm:nextblkp
#define PREV_BLKP(bp)  ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) //line:vm:mm:prevblkp
/* $end mallocmacros */

/* Global variables */
static char *heap_listp = 0;  /* Pointer to first block */
static char *rover;           /* Next fit rover */

/* Function prototypes for internal helper routines */
static void *extend_heap(size_t words);
static void place(void *bp, size_t asize);
static void *find_fit(size_t asize);
static void *coalesce(void *bp);

/*
 * mm_init - Initialize the memory manager
 */
/* $begin mminit */
int mm_init(void)
{
    /* Create the initial empty heap */
    if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1) //line:vm:mm:begininit
        return -1;
    PUT(heap_listp, 0);                          /* Alignment padding */
    PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 0x1 | 0x2)); /* Prologue header */
    PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 0x1 | 0x2)); /* Prologue footer */
    PUT(heap_listp + (3*WSIZE), PACK(0, 0x1 | 0x2));     /* Epilogue header */
    heap_listp += (2*WSIZE);                     //line:vm:mm:endinit
    /* $end mminit */

    rover = heap_listp;
    /* $begin mminit */

    /* Extend the empty heap with a free block of CHUNKSIZE bytes */
    if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
        return -1;
    return 0;
}
/* $end mminit */

/*
 * mm_malloc - Allocate a block with at least size bytes of payload
 */
/* $begin mmmalloc */
void *mm_malloc(size_t size)
{
    size_t Wsize;      /* round up to an WSIZE */ /* ! CHANGED ! */
    size_t Dsize;      /* DSIZE after align WSIZE */ /* ! CHANGED ! */

    size_t asize;      /* Adjusted block size */
    size_t extendsize; /* Amount to extend heap if no fit */
    char *bp;

    /* $end mmmalloc */
    if (heap_listp == 0){
        mm_init();
    }
    /* $begin mmmalloc */
    /* Ignore spurious requests */
    if (size == 0)
        return NULL;

    Wsize = (size + (WSIZE-1)) / WSIZE; /* ! CHANGED ! */
    Dsize = Wsize/2 + 1; /* ! CHANGED ! */
    asize = DSIZE * Dsize; /* ! CHANGED ! */

    /* Search the free list for a fit */
    if ((bp = find_fit(asize)) != NULL) {  //line:vm:mm:findfitcall
        place(bp, asize);                  //line:vm:mm:findfitplace
        return bp;
    }

    /* No fit found. Get more memory and place the block */
    extendsize = MAX(asize,CHUNKSIZE);                 //line:vm:mm:growheap1
    if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
        return NULL;                                  //line:vm:mm:growheap2
    place(bp, asize);                                 //line:vm:mm:growheap3
    return bp;
}
/* $end mmmalloc */

/*
 * mm_free - Free a block
 */
/* $begin mmfree */
void mm_free(void *bp)
{
    /* $end mmfree */
    if (bp == 0)
        return;

    /* $begin mmfree */
    size_t size = GET_SIZE(HDRP(bp));
    /* $end mmfree */
    if (heap_listp == 0){
        mm_init();
    }
    /* $begin mmfree */

    if (GET_PREVIOUS_ALLOC(HDRP(bp))) /* ! CHANGED ! */
    {
        PUT(HDRP(bp), PACK(size, 0x2));
    }
    else
    {
        PUT(HDRP(bp), PACK(size, 0));
    }
    PUT(FTRP(bp), PACK(size, 0)); /* ! CHANGED ! */
    /* pack next block */
    *HDRP(NEXT_BLKP(bp)) &= ~0x2; /* ! CHANGED ! */
    coalesce(bp);
}

/* $end mmfree */
/*
 * coalesce - Boundary tag coalescing. Return ptr to coalesced block
 */
/* $begin mmfree */
static void *coalesce(void *bp)
{
    size_t prev_alloc = GET_PREVIOUS_ALLOC(HDRP(bp)); /* ! CHANGED ! */
    size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
    size_t size = GET_SIZE(HDRP(bp));

    if (prev_alloc && next_alloc) {            /* Case 1 */
        return bp;
    }

    else if (prev_alloc && !next_alloc) {      /* Case 2 */
        size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
        PUT(HDRP(bp), PACK(size, 0x2)); /* ! CHANGED ! */
        PUT(FTRP(bp), PACK(size,0)); /* ! CHANGED ! */
    }

    else if (!prev_alloc && next_alloc) {      /* Case 3 */
        size += GET_SIZE(HDRP(PREV_BLKP(bp)));
        PUT(FTRP(bp), PACK(size, 0));

        if (GET_PREVIOUS_ALLOC(HDRP(PREV_BLKP(bp)))) /* ! CHANGED ! */
        {
            PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0x2));
        }
        else
        {
            PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
        }
        bp = PREV_BLKP(bp); /* ! CHANGED ! */
    }

    else {                                     /* Case 4 */
        size += GET_SIZE(HDRP(PREV_BLKP(bp))) +
            GET_SIZE(FTRP(NEXT_BLKP(bp)));

        if (GET_PREVIOUS_ALLOC(HDRP(PREV_BLKP(bp)))) /* ! CHANGED ! */
        {
            PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0x2));
        }
        else
        {
            PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
        }
        PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
        bp = PREV_BLKP(bp);
    }
    /* $end mmfree */
    /* Make sure the rover isn't pointing into the free block */
    /* that we just coalesced */
    if ((rover > (char *)bp) && (rover < NEXT_BLKP(bp)))
        rover = bp;
    /* $begin mmfree */
    return bp;
}
/* $end mmfree */

/*
 * mm_realloc - Naive implementation of realloc
 */
void *mm_realloc(void *ptr, size_t size)
{
    size_t oldsize;
    void *newptr;

    /* If size == 0 then this is just free, and we return NULL. */
    if(size == 0) {
        mm_free(ptr);
        return 0;
    }

    /* If oldptr is NULL, then this is just malloc. */
    if(ptr == NULL) {
        return mm_malloc(size);
    }

    newptr = mm_malloc(size);

    /* If realloc() fails the original block is left untouched  */
    if(!newptr) {
        return 0;
    }

    /* Copy the old data. */
    oldsize = GET_SIZE(HDRP(ptr));
    if(size < oldsize) oldsize = size;
    memcpy(newptr, ptr, oldsize);

    /* Free the old block. */
    mm_free(ptr);

    return newptr;
}

/*
 * The remaining routines are internal helper routines
 */

/*
 * extend_heap - Extend heap with free block and return its block pointer
 */
/* $begin mmextendheap */
static void *extend_heap(size_t words)
{
    char *bp;
    size_t size;

    /* Allocate an even number of words to maintain alignment */
    size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; //line:vm:mm:beginextend
    if ((long)(bp = mem_sbrk(size)) == -1)
        return NULL;                                        //line:vm:mm:endextend

    /* Initialize free block header/footer and the epilogue header */
    if (GET_PREVIOUS_ALLOC(HDRP(bp))) /* ! CHANGED ! */
    {
        PUT(HDRP(bp), PACK(size, 0x2));
    }
    else
    {
        PUT(HDRP(bp), PACK(size, 0));
    }
    PUT(FTRP(bp), PACK(size, 0));         /* Free block footer */   //line:vm:mm:freeblockftr
    PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); /* New epilogue header */ //line:vm:mm:newepihdr
    /* Coalesce if the previous block was free */
    return coalesce(bp);                                          //line:vm:mm:returnblock
}
/* $end mmextendheap */

/*
 * place - Place block of asize bytes at start of free block bp
 *         and split if remainder would be at least minimum block size
 */
/* $begin mmplace */
/* $begin mmplace-proto */
static void place(void *bp, size_t asize)
/* $end mmplace-proto */
{
    size_t csize = GET_SIZE(HDRP(bp));

    if ((csize - asize) >= DSIZE) { /* ! CHANGED ! */
        if (GET_PREVIOUS_ALLOC(HDRP(bp))) /* ! CHANGED ! */
        {
            PUT(HDRP(bp), PACK(asize, 0x2|0x1));
        }
        else
        {
            PUT(HDRP(bp), PACK(asize, 0x1));
        }
        PUT(FTRP(bp), PACK(asize, 1));
        bp = NEXT_BLKP(bp);
        PUT(HDRP(bp), PACK(csize-asize, 0x2)); /* ! CHANGED ! */
        PUT(FTRP(bp), PACK(csize-asize, 0));
    }
    else {
        if (GET_PREVIOUS_ALLOC(HDRP(bp))) /* ! CHANGED ! */
        {
            PUT(HDRP(bp), PACK(csize, 0x2|0x1));
        }
        else
        {
            PUT(HDRP(bp), PACK(csize, 0x1));
        }
        PUT(FTRP(bp), PACK(csize, 1));  /* ! CHANGED ! */
        *HDRP(NEXT_BLKP(bp)) |= 0x2; /* ! CHANGED ! */
    }

}
/* $end mmplace */

/*
 * find_fit - Find a fit for a block with asize bytes
 */
static void *find_fit(size_t asize)
{
    /* Next fit search */
    char *oldrover = rover;

    /* Search from the rover to the end of list */
    for ( ; GET_SIZE(HDRP(rover)) > 0; rover = NEXT_BLKP(rover))
        if (!GET_ALLOC(HDRP(rover)) && (asize <= GET_SIZE(HDRP(rover))))
            return rover;

    /* search from start of list to old rover */
    for (rover = heap_listp; rover < oldrover; rover = NEXT_BLKP(rover))
        if (!GET_ALLOC(HDRP(rover)) && (asize <= GET_SIZE(HDRP(rover))))
            return rover;

    return NULL;  /* no fit found */
}
/* $end mmfirstfit */


猜你喜欢

转载自blog.csdn.net/qq512028505/article/details/79129703