一:ready

The only file you will be modifying and handing in is mm.c.

实验文件:

mm.c 我们需要填写的文件
mdriver.c 用于测试我们的程序
memlib.c 模拟内存系统,含有mem_sbrk等函数

需要填写的函数:

int mm_init(void)
void *mm_malloc(size_t size)
void mm_free(void *ptr);
void *mm_realloc(void *ptr, size_t size);

实验要求及一些注意事项:

  1. 在本实验中,尽量将所有的结构(链表头等)放在堆内存当中,尽量少定义全局变量。
  2. 64位与32位的问题。我们运行的机器应该是64位的,但是在目前csapp官网的makefile文件中有 -m 32 的编译选项,也就是说所有的指针均为32位,即占用4个字节,这点要注意。在某些linux系统中,电脑中可能没有对应的32位的库,因此在编译的时候会显示找不到库,根据自身系统自行下载即可。
  3. 本实验要求实现8-bytes对齐,也就是说,mm_malloc返回的指针均为8的倍数。
  4. 建议在确定好block的组织方式后,完成mm_check()函数,用于检查堆内存是否出现问题。
  5. 建议将trace文件夹放在mdriver所在文件夹中,并且更改config.h文件当中TRACEDIR的宏定义为#define TRACEDIR “traces/“。make之后就可以直接运行./mdriver进行全部测试也可以使用./mdriver -f 命令对某个文件进行测试
  6. 对于一些奇怪的段错误,不妨采用打印堆内存的信息,或者模拟指令,或者自己造一个小文件进行测试等。

开始前需理解的概念:

    1. 三种适配方式:
   - fitst fit
   - next fit
   - best fit
  2. 三种空闲列表的组织方式
   - implicit free list
   - explicit free list
   - segregated free list
  3. 两种合并的方式
   - immediate coalescing
   - deferred coalescing
  4. 两种内存碎片
   - internal fragmentation
   - external fragmentation
  5. 空间列表的排序方式
   - size order
   - address order

适配方式

first fit: 最为直接的办法。扫描所有的块,只要当前块的大小满足要求就使用,速度较快。
但容易导致空闲列表中前面的块被不断地细分,而后面的一些块却一直迟迟得不到利用。
second fit: 扫描的时候,每次从上一次扫描的下一个块开始,这样可以使得整个列表的块都可以被使用,
这使得效率更高。然而,实际应用中,作用也很有限,容易产生很大的空间浪费,造成大量碎片。
best fit:这种方式最大的好处是可以充分地利用空间。找到所有满足要求的块中最小的那一个,
这样可以很大程度上避免浪费。当然,这也使得时间成本较高,尤其是如果空间链表的组织方式
不太恰当的话,容易导致每次都要遍历一整个列表。
在本实验中,要拿到高分一般采用的是best fit。

列表的组织方式

implicit free list:这种方式最为简单,直接将所有的块(不管是否有分配)串在一起,然后遍历。这种方式可也使得块最小可以达到8 bytes。当然,这种方式效率很低,尤其是当块的数量较多的时候。

explicit free list:在每一个free 块中保存两个指针,将所有空闲的块组成一个双向链表。和隐式相比,这种方式最大的好处在于我们不需要遍历已经分配的块,速度上快了很多,当然,由于需要保存指针,所以每一个块最小为16 bytes。