《30天自制操作系统》学习笔记——第九天

        第九天,咱们来说说内存管理。

                                《30天自制操作系统》学习笔记——第九天_第1张图片

       很明显的,再次感受到《数据结构》的重要性。

       首先我们来进行内存检查,即确定内存容量。用memtest函数实现。在确定容量前,首先要暂时让486以后的CPU的cache功能无效。为了确定CPU是386还是486以上,利用二者eflag的18位即可判断。486以上是AC标志位,386没有此位。因此把1写到此为后再读出检验,若是1则是486以上,若是0,则是386。接下来,memtest_sub具体实现确定容量的工作。它的功能是调查从start地址到end地址的范围内,能够使用的内存的末尾地址。并且注意一点,这个检查程序被编译器误读,应该由汇编语言编写。

       内存检查完了,接下来该管理了。内存管理的基础,一是内存分配,一是内存释放。

       作者和我们一起探究了寻找较好的管理方式的方法。我觉得这个过程也是很有启发性的,所以不能只是简单地总结最后的选择。

       方法一)作者提出最简单的管理方法。我们把所有内存单元以4KB为单位分割。然后建立数组。若已用,值为1;若未用,值为0。这种方法很简单,但是有很大的压缩空间。因为记录一个单元的状态的只有0,1两种,也就是说1位就够了。这就是方法二。

       方法三)采用列表管理的方法,把类似“从xx号地址开始的yy字节是空的”这种信息都列在表里。这种方法不仅省内存,而且在分配和释放大块内存时都很迅速。

       方法四)方法三有一个缺点,当可用空间被搞得零零散散,怎么都归纳不到一块儿时,会将1000条可用空间管理信息全部用完。方法四在方法三的基础上,若发生管理空间用完现象,则割舍掉小块内存,等有空余后,再找回来。

       具体的allocfree的函数,还是要看源程序,并且注意一些细节问题。如在分配时,若正好用完,则减少一条可用信息。又如在释放时,若连着头,则归到上一条,连着尾则归到下一条,若头尾都连,则连尾一起归到头,若头尾都不连,则新插入一条信息。实际操作起来是很容易写错的哦,可以自己试试看。

       此处附上源程序:

struct FREEINFO {	/* あき情報 */
	unsigned int addr, size;
};


struct MEMMAN {		/* メモリ管理 */
	int frees, maxfrees, lostsize, losts;
	struct FREEINFO free[MEMMAN_FREES];
};


unsigned int memman_alloc(struct MEMMAN *man, unsigned int size)
/* 確保 */
{
	unsigned int i, a;
	for (i = 0; i < man->frees; i++) {
		if (man->free[i].size >= size) {
			/* 十分な広さのあきを発見 */
			a = man->free[i].addr;
			man->free[i].addr += size;
			man->free[i].size -= size;
			if (man->free[i].size == 0) {
				/* free[i]がなくなったので前へつめる */
				man->frees--;
				for (; i < man->frees; i++) {
					man->free[i] = man->free[i + 1]; /* 構造体の代入 */
				}
			}
			return a;
		}
	}
	return 0; /* あきがない */
}



int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
/* 解放 */
{
	int i, j;
	/* まとめやすさを考えると、free[]がaddr順に並んでいるほうがいい */
	/* だからまず、どこに入れるべきかを決める */
	for (i = 0; i < man->frees; i++) {
		if (man->free[i].addr > addr) {
			break;
		}
	}
	/* free[i - 1].addr < addr < free[i].addr */
	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; /* 成功終了 */
		}
	}
	/* 前とはまとめられなかった */
	if (i < man->frees) {
		/* 後ろがある */
		if (addr + size == man->free[i].addr) {
			/* 後ろとはまとめられる */
			man->free[i].addr = addr;
			man->free[i].size += size;
			return 0; /* 成功終了 */
		}
	}
	/* 前にも後ろにもまとめられない */
	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; /* 成功終了 */
	}
	/* 後ろにずらせなかった */
	man->losts++;
	man->lostsize += size;
	return -1; /* 失敗終了 */
}


你可能感兴趣的:(《30天自制操作系统》学习笔记——第九天)