日期:2014-05-16  浏览次数:20683 次

linux0.11内存memory.c一些函数的简单的注释(一)
memory.c中一些函数自己的一些自己看法,有错大家指出来。或者是更好的解释可以个提出来呀。有什么问题也可以向rentiansheng@163.com发邮件,

谢谢大家。

1. 设置页表、页目录的位置

boot/head.s

_pg_dir:              // 页目录将会存放在这里。因为这句话出现head.s第一个有效代码的位置,因为head.s移动到内存物理0的位置,所以页目录的位置存放在0x0000处

org 1000h           // 从偏移0x1000 处开始是第1 个页表

pg0:

org 2000h           // 从偏移0x2000 处开始是第2 个页表

pg1:

org 3000h           // 从偏移0x3000 处开始是第3 个页表

pg2:

org 4000h           // 从偏移0x4000 处开始是第4 个页表

pg3:

org 5000h           //这句话主要是让下面的代码在第4个页表占用的内存外,因为第4个页表要占用0x4000-0x5000所以这些位置不能存放代码。

问题,页表可以在内存的任意位置吗?

错,页表可以在内存中通过分级,而不存储在一起,但是每一个页表的起始地址必须在4KB边界上,先看下图页目录的存储结构

 

原因一:我们看到页目录中用来表示页表地址只有10位置,但是现在要表示一个32位页表项的其实地址肯定是做不到,但是我们发现每一个页目录有1024个表,每一个4个字节,正好是占12位(2^10*2^2=2*12),这样的话,如果从4KB的边界开始存放页表,其实不用存储后面的地址,

原因二:从2KB边界开始存放,一个页目录对应的页表项可以用一个页面存储,不必分到两个页面,方便内存的分页管理。

 

下面的几句代码是对页目录和页表项所在的内存单元清零。主要是避免脏数据对以后代码进行页面转换的时候的影响,给所有的页表项赋首地址的。

       setup_paging:

       movl $1024*5,%ecx          //一个页目录,4个页表项,每一个1024项,

//设置的循环的次数,即使填充次数,

       xorl %eax,%eax                 //stosl使用的参数

       xorl %edi,%edi                  // 页目录从0x000 地址开始。即使页表和页目录的首地址,

       cld;rep;stosl                       //cld:清除EFALGS中方向的标志位置,rep  循环,循环次数有ecx决定, stosl:将eax的值保存到ES:EDI指向的地址中,由于没有设置标志 EDI 每次自增4

 

 

//7 = 111b,可知道设置了,第0、1、2位,分表示存在、用户可读写

//下面主要的功能使用来填充页目录项的

//填充页目录,所管理页表项的地址,即使页目录所管理第1个页表的值,在这//里即使 pg0的地址,+7表示页表项的属性,因为后12位不表示地址,因为每//一个页表项占4个自己,所以第2个页目录的地址是pg_dir+4,第2个是页目录//的地址是pg_dir+4,

       movl $pg0+7,pg_dir              

   movl $pg1+7,pg_dir+4            

       movl $pg2+7,pg_dir+8            

       movl $pg3+7,pg_dir+12          

 //下面填写页表项的内容呀,首先从最后一个开始填写的,即是pg3页目录的最//后1个页表项的地址

       movl $pg3+4092,%edi      //计算pg3页目录的最后1个页表项的地址,最后

//1个页表位置在pg3+4KB-4B的位置,所以位置是//pg3+4096-4

       movl $0xfff007,%eax        //设置最后一个页表项的地址,16M-4K+7,其中

                                                 //其中16M-4KB表示地址,7表示存在,用户可读写

       std        //设置方向位,使用stosl是edi值递减4

1:    stosl    &n