原创 写代码的篮球球痴 嵌入式Linux 2020-06-26

收录于话题

#Linux

130个

内存大小计算

我们拿32位系统来举个栗子

2^32 = ‭4,294,967,296‬ bytes

‭4,294,967,296‬ bytes / 1024 = ‭4,194,304‬ kbytes

4,194,304‬ kbytes / 1024= ‭4,096‬ M

‭4,096‬ M /1024 =  4G

物理内存如何分页?

分段和分页计算机内存管理的两种方式,这里我只讨论分页。

比如是 4G的内存,我们一个页的大小是 4K,那可以分成多少个页呢?

通过一系列复杂而且不为人知的计算

4,194,304‬ kbytes / 4 = ‭1,048,576

所以分页后的物理内存应该是这样排列的


Linux内存,先看这篇文章_嵌入式MMU是什么?

如果操作系统是一家银行,那MMU就是这家银行的资金仓库管理员,所有要申请资金的人都要通过管理员才能拿到钱。

Linux内存,先看这篇文章_嵌入式_02

我们说的MMU就是内存管理单元,所有什么乱七八糟的虚拟地址最后都是都需要经过MMU这个内存管家把虚拟地址转换成物理地址来操作的。

顺便说一句,并不是所有的支票都可以转成钱的,有些也可能是空头支票,操作系统给应用的虚拟内存,这些虚拟内存并不是都能转换成相对应的物理内存的

分页模式下的虚拟地址转换成物理地址对应图

上面分页的问题

如果是32的系统,我们4G的内存,分成4KB一个页,那需要多少个页呢?

4,194,304‬ kbytes / 4 = ‭1,048,576‬

我们上面已经计算出来了,如果一个虚拟地址和物理地址的映射关系需要4个字节来存储,那我们需要多少空间呢?

1,048,576‬  x 4bytes = ‭4,194,304‬ bytes /1024 = ‭4,096‬ k / 1024 = 4M

就是说我们一个映射关系需要 4M的内存,我们操作系统开一个进程就需要开一个映射表,如果我我们开100个进程就需要400M内存,这样的话,我们的操作系统的内存会非常非常吃紧。

所以,操作系统的开发大牛们就发明了多级页表这个东西,多级页表的作用就是为了省空间,每当读到这里,我每每感叹,自己比别人是笨了多少个等级啊。

为什么需要4个字节来存一个页表项呢?因为是32为地址,一个字节是8位,4个字节刚好是32位,所以就需要4个字节存储页表项。

有人会问,这4K存的是物理地址还是虚拟地址呢?

大家想一下,物理地址的分页在系统启动的时候已经确定好了,物理地址是没有必要分多次的。所以这个存的是虚拟地址。

多级页表

然后,大神们就设计出这样的分页方式

多级页表划分

我们上面说了,如果只用一级分页的话,导致一个问题是需要的太多的空间来存储映射关系了,那现在改成使用32bit不同的bit来寻址,需要多少内存来存储呢?

2^10 = 1024bytes = 1k

一个页表大小是 4 K ,我们是一个字节一个字节的偏移的,所以一个页我们一定需要 12个bit做偏移来获取页中的具体位置,所以我们必须要留12bits给页表偏移使用。

既然页表偏移使用12bit,那页目录和页表各分到10bits。

1024 * 1024 = ‬ ‭1,048,576‬

1,048,576‬  x 4 k = ‭4,194,304‬ k

‭4,194,304‬ k / 1024 = 4096M = 4G

这样分是不是很牛,计算出来就刚刚好等于 4G 内存

那页表项我们需要多少内存空间呢?

页目录一共是 2^10 = 1024 项,每一项代表一个页目录表的编号,一个页目录表我们需要4个字节来表示,所以占用的存储空间应该是 1024 * 4bytes = 4K 大小。

同理页表也是一样,需要4K大小的存储空间

偏移量这个是不需要存储的,我们只要知道了前面两个位置,再加上偏移量,就能准确知道内存的具体位置了

Linux内存,先看这篇文章_嵌入式_03

我们把这种分段方式想象成一本书,就很好理解了。比如,我们要在新华字典查某个字的时候,我们需要在目录里面找这个字在哪一页,这个就需要一个页目录表。然后,我们找到确定的页数后,再通过页表找到在哪一行。最后,我们通过偏移量找到这个字跟行首偏移多少个字。

我们这样就能找到确定的字了。

如下图Linux内存,先看这篇文章_嵌入式_04




推荐阅读:专辑|Linux文章汇总专辑|程序人生