其实还是比较简单的,只是纯代码可能不好理解,加上图片就好理解了
情况1(左部合并)
要释放的内存块(绿色内存区域)左边是空闲的,就将它和左边合并,由于没有内存块数量的变化,就不需要移动内存块,对应的代码部分如下
if (i > 0) {
/* 前がある */
if (man->free[i - 1].addr + man->free[i - 1].size == addr) {
/* 前のあき領域にまとめられる */
man->free[i - 1].size += size;
情况2(左右合并)
只考虑到上面的左部合并是不够的,当左右都有空闲内存块的时候,先合并到左部Free[i-1],再将Free[i]合并到新的Free[i-1],但是由于内存块数量减少了,移动内存块,这里旧的Free[i]被合并了,就需要将空闲内存块的数量-1(对应代码中的man->frees–),除此之外,还需要将之后的Free[i+1]复制到Free[i],同理Free[i+2]复制到Free[i+1],.(递归复制下去)…,复制完最后一块的时候,
代码如下
if (i > 0) {
/* 前がある */
if (man->free[i - 1].addr + man->free[i - 1].size == addr) {
/* 前のあき領域にまとめられる */
man->free[i - 1].size += size;
if (i < man->frees) {
/* 後ろもある */
if (addr + size == man->free[i].addr) {
/* なんと後ろともまとめられる */
man->free[i - 1].size += man->free[i].size;
/* man->free[i]の削除 */
/* free[i]がなくなったので前へつめる */
man->frees--;
for (; i < man->frees; i++) {
man->free[i] = man->free[i + 1]; /* 構造体の代入 */
}
}
}
return 0; /* 成功終了 */
}
}
情况3(右部合并)
如果不是上面的情况,即Free[i-1]不在释放的内存块左侧,空闲内存块Free[i]恰好在右侧,就将内存块合并到右侧Free[i],由于没有内存块数量变化,依旧不用移动内存块。
代码如下
/* 前とはまとめられなかった */
if (i < man->frees) {
/* 後ろがある */
if (addr + size == man->free[i].addr) {
/* 後ろとはまとめられる */
man->free[i].addr = addr;
man->free[i].size += size;
return 0; /* 成功終了 */
}
}
情况4(新建内存块)
如果不是上面的情况,即Free[i-1]不在释放的内存块左侧,Free[i]也不在该内存块右侧,就只能新建一个内存块,由于内存块数量改变,需要移动内存块。
首先我们需要考虑一件事,这个新建的内存块放在哪里?
因为Free[i-1]及之前都不能移动,所以只好对Free[i]及其之后下手了。
所以先而从末尾**Free[man->frees]**开始(这是空白的,因为数组是从0开始的,man->frees只表示空闲数量,所以Free[man->frees-1]才是第man->frees个有实际信息的元素),复制Free[man->frees-1]的内容到Free[man->frees],递归下去直到Free[i]复制到Free[i+1]的内容,将空闲内存块数量+1(man->frees++),,然后将Free[i]设置为刚刚释放的内存块(绿色部分)。
/* 前にも後ろにもまとめられない */
if (man->frees < MEMMAN_FREES) {
/* free[i]より後ろを、後ろへずらして、すきまを作る */
for (j = man->frees; j > i; j--) {
man->free[j] = man->free[j - 1];
}
man->frees++;
if (man->maxfrees < man->frees) {
man->maxfrees = man->frees; /* 最大値を更新 */
}
man->free[i].addr = addr;
man->free[i].size = size;
return 0; /* 成功終了 */
}
情况5(超过最大空闲块数量)
由于数组Free的最大长度有限,最大空闲块数量也有限,被设置为MEMMAN_FREES=4090
#define MEMMAN_FREES 4090 /* これで約32KB */
对应结构体
struct MEMMAN { /* メモリ管理 */
int frees, maxfrees, lostsize, losts;
struct FREEINFO free[MEMMAN_FREES];
};
超过的部分将会被记录到内存丢失信息中
/* 後ろにずらせなかった */
man->losts++;
man->lostsize += size;
return -1; /* 失敗終了 */