读30天自制操作系统有感,顺便回应米油兄

先说下对这本书的感受。诚然作者写得很风趣浅显,但里面内容涉及硬件体系结构、汇编、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;
}

 

不知道以上注释能否释米油兄的惑。


算法图附上

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值