先说下对这本书的感受。诚然作者写得很风趣浅显,但里面内容涉及硬件体系结构、汇编、c语言、数据结构与算法、操作系统原理。
这些每一门都可以写一本厚书,就算作者只提及那些要用时才学的相关内容,但说实话,如果一点也不懂当入门用的话,很多会看不懂。
这本书的优点就是具体、实用,所做的一切用代码表现,可以看得到。不像以上那些专业的内容太抽像了,很难想像。
对真正想学好计算机技术的人,建议先略读一遍各学科书,再读30天自制os,从这本书里找出各学科里谈及的内容,回头再看那些讲理论的书,一下子就领悟了。
看到目前,我认为作者最高明的地方是解决问题的办法,还有转成代码里的算法。有的时候不能不说太高明了。自学后分解弄懂容易,但要让目前水平的我自己写出来,我知道我做不到。
说下我辅助看30天学好os的相关书: 于渊的自制一个操作系统、 386设计师写的保护方式下的80386及其编程、tanenbaum的现代操作系统第三版、c父的c语言程序设计
感谢以上牛人的书。让我获益多多。
先声明,我也才看到第十天的叠加处理。
第十章 作者提到不管是鼠标叠加或移动,还是窗口叠加或移动,全是用图层解决。
作者的注释很精简,精简到文字就写具体算法看代码,造成的后果就是那些图层算法要停止阅读进行研究。
下面是写给米油的http://blog.csdn.net/h397916230/article/details/11265373
第九章 操作系统内核简单内存管理
前提摘要:
作者写道内存管理用表来管理比用字节数组和位来管理来得快速。表其实就是数据结构上的用数组实现的线性表
作者在代码里要做的是
1.用memtest函数获取电脑物理内存有多大,获得的内存大小保存在memtotal变量中
2. 用 memman_init函数 对struct MEMMAN 内存管理结构进行初始化,
3. 对内存中空闲的内存地址在 struct MEMMAN 中生成两条记录
memman_free(memman, 0x00001000, 0x0009e000); // 1MB以下的空闲内存
memman_free(memman, 0x00400000, memtotal - 0x00400000); // 4兆以上到物理内存上限间的空闲内存
作者用这个memman_free内存释放函数在 struct FREEINFO free[MEMMAN_FREES] 表中生成两条记录,就是把空闲内存在 struct FREEINFO free[MEMMAN_FREES] 中注册
4. 之后,之后就是如果操作系统内核相关代码要用内存(比如后面图层叠加就要用),进程要用内存,就要用memman_alloc 和 memman_free来申请和释放。memman_alloc 和 memman_free这两个函数就是在struct
FREEINFO free[MEMMAN_FREES]这个数组中添加和删除项。当然算法要进行比较,比较是否可以和在struct FREEINFO free[MEMMAN_FREES]这个数组中的相关项进行合并
正如作者所说第九章代码没解决在内存存在大量碎片,struct FREEINFO free[MEMMAN_FREES] 数组用完MEMMAN_FREES条数后的解决方法,第九章只是单纯的在lostsize, losts中统计一下,直接放弃这次要释放的内
存。
理解了以上,就可以理解作者的代码了。以下给出memman_free伪码加解释
struct FREEINFO {
unsigned int addr, size;
};
//这个FREEINFO结构定义了可用内存的开始地址及范围
struct MEMMAN {
int frees, maxfrees, lostsize, losts;
struct FREEINFO free[MEMMAN_FREES];
};
//这个结构就是内存管理结构。struct FREEINFO free[MEMMAN_FREES]这个数组用来保存空闲内存的FREEINFO结构。
//lostsize, losts这两个变量是统计内存存在大量碎片struct FREEINFO free[MEMMAN_FREES] 数组用完MEMMAN_FREES条数后的相关数据
//frees这个变量是说目前struct FREEINFO free[MEMMAN_FREES]里有多少条记录。书上注释写的是“可用信息数目”,一直不理解,后来一看代码,看懂了。
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
{ unsigned int i, a;
for (i = 0; i < man->frees; i++) {
if (man->free[i].addr > addr) {
break;
}
}
//要释放的内存的地址 addr与 man->free[i].addr进行比较,循环的结果就是找到这个addr要插到struct FREEINFO free[MEMMAN_FREES] 数组中的哪个地方。
//相当于free[i - 1].addr < addr < free[i].addr
// 以下代码段说的是: 要释放的addr既要与上一个条目进行比较,也要与下一条目进行比较
// 以下的代码是说 要释放的内存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 - 1]这个上一个条目已经包含释放的内存了。
man->frees--; // frees减一,可用内存条数减一个
for (; i < man->frees; i++) {
man->free[i] = man->free[i + 1]; // 减掉的下一条man->free[i]被合并到上一条,当然空出来了,就把后面的条目移动上来嘛
}
}
}
return 0;
}
}
// 以下代码就是说,要释放的内存addr不可以与上一个条目合并,但可以与下一条目合并
if (i < man->frees) {
if (addr + size == man->free[i].addr) { // 如果要释放的内存结束地址等于下一个条目的内存的起始地址
man->free[i].addr = addr;
man->free[i].size += size; // 那就合并呗
return 0;
}
}
// 以下代码就是说 要释放的内存addr既不可以与上一个条目合并,也不可以与下一个条目合并,,那就,,那就,,插入呗。 整一个数组式线性表嘛。
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; //更新最大值 。 这里我一直想不通,为什么要调个 maxfrees呢。干嘛用?谁解释个。
}
// 以下代码最简单了,
man->free[i].addr = addr;
man->free[i].size = size;
return 0;
}
// 要释放的内存addr既不可以与上一个条目合并,也不可以与下一个条目合并,而且运气很差,struct FREEINFO free[MEMMAN_FREES] 数组用完MEMMAN_FREES条数,然后,直接放弃,不加入条目了,只做统计。
man->losts++;
man->lostsize += size;
return -1;
}
不知道以上注释能否释米油兄的惑。
算法图附上