lcc之内存分配
现在感觉这本书有些地方没有说透,如果自己的理解能力与基础知识够强的话,理解起来还好,如果不行的话,某些地方理解起来会相当的头疼。
现在来说说内存管理。当初看这一章的时候很快就过去了,感觉很多地方很好理解,当看到后面看不下去时,从头再仔细看时,发现当时很多没有注意到的细节问题。
在该书中图2-1我一直觉得这个图画错了,最后发现是我想当然了,其实这个图很正确,只是我没有理解正确。
文中把内存分成了三个大块。
这first仅仅表示这三块的头,即开始的地方, static struct block first[] = { { NULL }, { NULL }, { NULL } }, 每一个大块有若干block连接起来
static struct block *arena[] = { &first[0], &first[1], &first[2] }; arena代表每个大块的尾部,从头到尾中间的任何一块即使有空闲空间也不使用,这些空间被浪费了。
在上面的初始化中arena指向first中的各个项。
具体情况详见图2-1,其中另外一点需要注意的是f每一大块的第一个block中的avail和limit都是NULL表示头指针。
下面解释下allocate()函数。
简要说下步骤,首先从freeblock中开始找,freeblock是共享的,三个大块都可以从中来获取可分配的block,如果在freeblock中没有找到足够大小的block,于是就分配一个新的block,如果找到了足够大的block,则用该block。
void *allocate(n, a) unsigned long n; unsigned a; { struct block *ap; assert(a < NELEMS(arena)); assert(n > 0); ap = arena[a];//此时ap指向大块a中的最后一个block n = roundup(n, sizeof (union align)); //下面这段循环好阴险,先从freeblock中找,找不到再分配,感觉写的不太好,如果把else移出来就好理解多了 while (n > ap->limit - ap->avail) {
//这里的freeblock是共享的,三个大的块共写freeblock。 if ((ap->next = freeblocks) != NULL) { freeblocks = freeblocks->next; ap = ap->next;//指向freeblock中的block } else { unsigned m = sizeof (union header) + n + 10*1024; ap->next = malloc(m);//malloc return a address of the memory ap = ap->next; if (ap == NULL) { error("insufficient memory\n"); exit(1); } ap->limit = (char *)ap + m; }
//经过上面的if和else已经得到了满足大小的内存block(不论是从freeblock中分配得到的还是新分配的) ap->avail = (char *)((union header *)ap + 1); ap->next = NULL; arena[a] = ap; } ap->avail += n; return ap->avail - n; }
上面还有一个疑问,first代表头,arena代表尾,当分配一个block时,是怎么把若干block通过next联系起来的。