9.11 A、虚拟地址格式:00001001 111100
B、
C、物理地址格式:010111 111100
D、
9.12A、虚拟地址格式:00001110 101001
B、
C、物理地址格式:010001101001
D、
9.13A、虚拟地址格式:00000001000000
B、
9.14
#include "csapp.h"int main(int argc, char const *argv[]){int fd;if ((fd = open("hello.txt", O_RDWR)) == -1){perror("Failed to open hello.txt");exit(EXIT_FAILURE);}struct stat stat_of_file;if (fstat(fd, &stat_of_file) == -1){perror("Failed to get stat of hello.txt");exit(EXIT_FAILURE);}char *p;if ((p = mmap(NULL, stat_of_file.st_size, PROT_WRITE, MAP_SHARED,fd, 0)) == (void *)-1){perror("Failed to mmap");exit(EXIT_FAILURE);}p[0] = 'J';return 0;}
9.15
9.16
9.17 罗列下修改的要点:
1、新增一个静态全局变量rover,保存上一次搜索的结果地址;在mm_init函数里初始化为堆的起始地址heap_listp
2、修改find_fit,从rover开始到堆尾,再从heap_listp到rover,搜索合适的空闲块。
3、修改mm_malloc,正确分配块后,将rover置为下一个空闲块。
4、mm_free需修改,修改coalesce,在合并时更新rover。
9.18 说明:用Header的倒数第二位表示是否为空闲位。如010表示上一个块已分配,000表示未分配。由于只在合并块时需要使用上一个块的大小。所以取消已分配块的Footer不影响算法的实现。由于细节的修改比较多,此处略过。
9.19 1)a:正确,假设申请一个大小的块,实际会分配,所以最高约有50%的空间浪费;
b:错误,无论是考虑平均,还是最差情况,两种算法的复杂度都与块数量呈线性关系;
c:错误,比如伙伴系统就不需要使用边界标记,空闲链表也不一定需要按地址递增排序;
d:错误,任何分配器都会有外部碎片。
2)a:错误,空闲块递减排列使得首次适配算法的匹配复杂度为O(1),性能是提升了;且不能避免外部碎片;
b:错误:最佳适配无论如何都要搜索整个链表,顺序安排无所谓;
c:错误:请求的是最接近请求大小的适配块;
d:正确:两者找到的肯定是同一个块,所以等价。
3)b:正确,保守是说会将垃圾当成可达块,而原因正是将一些非指针值,如int当作指针值,而错误地将一些垃圾标记位可达块,而不回收它。a)c)不保守的垃圾收集器也是可以这么做的,d)循环链表的垃圾块也是可能被回收的。
9.20 略