高端内存的理解

 

前几天灵光一闪,外加看了篇关于高端内存的理解文章,搞懂了高端内存作用。

来谈谈高端内存的作用,仅仅是作用,原理要涉及代码(这里自己抽象个东西解释下)。

 

不考虑PAE,并且是x83_32

 

首先谈谈对于 “32位” 的一点理解。简单说来,对于32-bit os,如果你想读写内存(简单来说就是int a; a = 4),首先你要定位到你要读写的内存的具体位置,就是内存地址了,

但是这个内存地址的数值有着一些限制,就是 0x00000000~0xffffffff,这里刚好是32-bit

数据大小(0xffffffff = 2 ^ 32 - 1)。那么好了,32-bit os可以定位内存范围就是0~4GB范围内任何地址空间。

 

但是这么有限的4GB地址空间 要被划分成2个部分 即用户态地址空间 和 内核态地址空间,而如果用户太地址空间要去划分3GB(0x00000000~0xbfffffff),那么留给内核态的地址空间就只有1GB了(就是0xc0000000~0xffffffff)。

现在问题来了,内核态下如果要读写内存,那么就需要通过这有限的1GB内存地址空间去定位我们实际物理内存,然而实际物理内存大小是不确定的,而对于现在2G以上内存条漫天飞的情况,我们那1GB的内存空间就显的力不从心了。

 

为了解决这个问题该怎么办呢?

首先,我们来考虑先如果就用内核地址空间直接映射实际物理内存,那么我们就忍痛丢到超过1GB以上的所用物理内存空间,方法很简单,内核地址设为x ,实际物理内存地址设为y,

那么 y = f(x)= x - 0xc0000000, 因为x范围只有1GB, 所以y范围也是1GB。现在好了,我们只能跟高端游戏说byebye了,再大的内存条买来只能用到1GB。

+---+ 4G         +---+

 | x  |  ------+    |     |

+---+ 3G    |    +---+

 |     |          |    |     |

+---+ 2G    |    +---+

 |     |          |    |     |

+---+ 1G    |    +---+

 |     |         +-->| y  |

+---+ 0            +---+ 

 

但是,从上面分析,我们也发现了解决问题方法,就是 x 到 y 映射的函数是 f:线性映射,太过简单暴力了。那如果我们买了个2GB的内存,当我们想用到超过内存1GB以上的物理空间怎么办呢,非常好办:y = g(x)= x - 0xc0000000 + 1GB 就行了,只不过现在只能用物理内存范围是:1GB~2GB,而无法使用0~1GB。 当我们又想用0~1GB的时候该怎么办呢,很简单,我们更改映射函数g就可以了。这样改来改去,显然是会影响系统效率的,没办法想多用内存,就是需要牺牲一点效率(用时间换空间)。

+---+ 4G           +---+

 | x |  ------+      |     |

+---+ 3G    |      +---+

 |    |          |      |     |

+---+ 2G    |      +---+

 |    |          +->  |  y |

+---+ 1G            +---+

 |    |                  |     |

+---+ 0              +---+ 

 

既然大体方法找到了,具体实现起来还是有很多要考虑的,比如是否可以找到一个对于效率减小最少的映射方法呢?(这里我就不继续想下去了,直接看看内核里面怎么做的)

在linux中,地址空间映射是这样的,把0xc0000000~0xffffffff这1GB内核地址空间划分成2个部分低端的796MB + 高端的128MB,低端796MB就使用f映射,直接映射到物理内存的前796MB上,而高端128MB就用来随时变更g来映射到物理内存超过796MB的范围上,这里对应了3种映射算法:动态映射,永久内核映射,临时映射,具体实现我就不讲了。

 

说下“映射”是什么,其实就是x86的内存分页机制,我们只要通过修改分页的页表项就可达到更改 “映射” 的目的。(可以参考intel手册)

另外在调试kernel时候,如果遇到 BUG: Unable handle page request at 0x????????, 如果这里0x????????<0xc0000000 就要注意了,这里你使用的变量地址不在内核空间,定是某个地方地址用错,或者指针使用出错!


附上一篇讲的比较贴近内核的文章,感觉我自己写的太过抽象了:

http://blog.csdn.net/littlehedgehog/archive/2008/08/19/2796669.aspx


查看系统内存映射:

# dmesg | grep "Memory:" -n -A 8

你可能感兴趣的:(kernel,hacking)