HelloOs总结之内存管理(上)

HelloOs总结之内存管理(上)

四、内存管理

   终于到了最难搞的两个部分了。下面我想说点废话,请忽略以下文字。
人,真的有懒惰心理、畏惧心理、拖延心理。尤其在没有什么直接奖励的情况下。说实话,这个部分已经拖了好久了,并不是因为没有时间,老实说,有的时候我宁愿看美剧,也不愿意总结这个部分的内容。(嘿嘿,可能大部分人都有这种想法吧。毕竟看美剧不累,总结这个,要花脑子。)我是越来越觉得,总结一个内容真的是很花精力,当然一个人活得知识或者说成长最快的时候应该也就是其总结,反思的时候。但是,累啊,说实话我并没有到达那种学习成瘾的境界,那种学习为乐的境界(虽然很多时候确实挺有意思的),这个时候,就需要靠着我的略显倔强的脾气和一些小小的技巧了。前者,性格使然,无法学习;后者就是当需要你完成原本不想要完成的任务时,许诺给自己点奖励,如果适当,身体内奋斗的肾上腺素就会战胜那份懒惰咯(以上方法,总结自《自控力》,不保证对每个人有效哦)。
   好了,废话说完了,下面开始说点正题吧。

   内存管理整个部分是HelloOS中的重点部分,也是难点部分。我打算分为以下几部分讲述。如下图4.1所示。
在这里插入图片描述
图4.1 内存管理思维导图

   其中
   (1)、内存规划使用图部分主要是讲64M内存的具体规划。
   (2)、MMU主要是虚拟内存和物理内存基本的映射。
   (3)、基本内存管理主要关于内存的设计、分配、回收等部分,主要包括伙伴算法和Slab系统


 

4.1 内存规划

   虽然对于设计整个操作系统来说,内存规划极其重要,但对于整篇文章的总结目标来说,内存规划部分并不是重点。下面就简要介绍些。
   整个系统采用的内存是64M大小的SDRAM。(当然在skyeye虚拟环境中,不需要了解具体的硬件环境)其各个部分的分配主要如下图4.2所示。
在这里插入图片描述
图4.2 64M内存分配图

   其中由于我们的S3C2410中SDRAM bank是放在0x30000000地址处的,所以64M内存空间的分布式0x30000000-0x33FFFFFF。这些地址空间主要分为以下几个部分:
   (1)高地址处的1M空间(0x32EFFFFF-0x34000000)是异常向量表和栈空间。异常向量表是上一章中中断部分提到的二级向量地址入口,如下图4.3所示。 栈空间主要是为各个模式的栈提前规划好的空间,其中主要是中断模式(irq)模式利用到了这部分空间。

在这里插入图片描述
图 4.3 高地址处的二级异常向量入口

   (2)、接下来的32M空间(0x31F00000-0x32EFFFFF)是用作用户空间的地址部分。这部分主要用来保存用户进程部分的PCB。同时,用户进程动态申请的空间也是在这一部分。这里顺便提一句,一般来说,用户进程的PCB应该单独放在一个内核部分所管理的区域,这样方便管理。这里,为了规划简单,就暂且放在一起了 ()。以后有机会的话,可以重新规划一下。
   (3)、再下面的16M空间是内核的地址空间(0x30F00000-0x31EFFFFF),作用基本和用户空间相同,不再赘述。
   (4)、接下来的13M(0x30200000-0x30EFFFFF)是内核的数据结构区。其中主要保存了系统主线程PCB,页表区域,page结构体区等等。下面还会对这一部分做深入介绍。
   (5)、最后的低端2M(0x30000000-0x301FFFFF)是整个系统的代码段和数据段部分。这里也简单提一下,由于HelloOs没有实现文件系统部分,所以用户程序被编译后也是保存在这个区域的。

   上面介绍了64M内存的主要部分。下面还有一个低端13M的部分。如下图4.4 所示。
在这里插入图片描述
图4.4 低端13M 内存规划图

   其中主要由如下几部分组成:
   (1)、顶端7M(0x30800000-0x32eFFFFF)空间暂未使用。
   (2)、主线程PCB处。占据1M空间(0x30700000-0x307FFFFF)。 这个主线程是整个系统的最开始的那个线程,,负责初始化所有的内容,以及生成其他线程。
   (3)、 下面是32M用户空间的page数据结构区,占据空间2M (0x30400000-0x306FFFFF)。这一部分主要是为了动态分配32M用户空间所需的描述结构体。
   (4)、再下面是16M内核空间的page数据结构区,占据2M (0x30300000-0x304FFFFF)。作用和上面的类似。
   (5)、最后一个低端的1M(0x30200000-0x302FFFFF)区域是页表区域。这个区域内主要是存储了整个系统所需内存空间的页表。具体的在MMU一节中会说明。


 

4.2 MMU

   ok,接下来说说关于MMU的那些事。
   其实在HelloOS中,也没用到太多关于MMU的东西,这里权且简单总结一些用到的知识点吧。
   首先,MMU 是内存管理单元,一般来说它都是和CPU配合工作的硬件设备,其主要的作用是地址映射和内存保护(有的CPU架构不把实现了这两个功能的单元叫做MMU)。
   所谓地址映射,简单来说就是将虚拟地址映射成物理地址的一种机制。从一个更高角度来看,它就是内存中的一张表(或者一个一维数组),这张表里存了很多项,每一项中都包括了虚拟地址对应的物理地址(当然,一般还会有一些其他的东西,比如说一些标志位、访问权限等),如下图4.5所示。当CPU发出虚拟地址的时候,MMU或者其他的地址转换结构会自动帮我们查找到对应的物理地址(当然,中间还需要进行一些简单的线性运算,不过这一般都是硬件帮我们自动完成的)。

在这里插入图片描述
图4.5 页表结构示意图

   这里要注意一点,上述的页表映射(虚拟地址映射到物理地址)的粒度并不是以字节为单位的,大多数操作系统是以页或者段为映射单位,即一个页表项存储了一个页(或者段)的映射关系。
   哦,好吧,这里还需要注意一点,开启了页表机制之后,CPU发出的就是虚拟地址了,也就是说CPU是不知道物理地址这回事的,它认为它所访问的就是物理地址,但实际上已经被MMU等转换成了实际的物理地址。
   而所谓的内存保护,更多的是MMU利用页表中存储的一些标志位或者访问权限来对内存区域(段或者页)进行保护。
   关于具体的页表映射,和内存保护,这里面还有不少知识点,有兴趣的,哦,不是,不了解的需要参考有关操作系统的资料学习一下,这儿就不赘述了。

   对于HelloOs来说,只用到了MMU中很少的一部分,介绍如下。
   为了简单起见,HelloOs中的虚拟地址和物理地址大部分都是一一对应的,也就是说页表项中虚拟地址对应和其对应的物理地址是相同的。那为什么还需要使用MMU呢?
   关于HelloOs中使用MMU有两个原因:
   一是我们的使异常向量表进行偏移。因为当发生某一个异常时,CPU会自动跳到地址的前几十个字节的位置去执行(如异常向量部分所述),但是我们的存储器是从0x30000000这个地址开始的,所以需要MMU将地址进行映射一下,把原本0地址开始的异常向量搬移到0x30000000位置处。(当然,也可以利用S3C2410中内置的4K SRAM做中转来达到转移的目的,但有些复杂,否决了)
   第二个原因就是,在以后实现系统调用的时候,需要用到内存保护单元隔离内核空间和用户空间。(比较尴尬的是,skyeye对内存保护做得不是很好,最后无法实现内存保护的功能,这点在下面还有论述)

   具体来说,如下图4.6所示,HelloOS映射了以下几个段(注意,S3C2410中的MMU支持页映射,也支持段映射,我们这儿为了简单明了,直接使用了段映射)

在这里插入图片描述
图4.6 MMU页表示意图

   上图就是HelloOs使用的地址空间,基本上就是虚拟地址和物理地址相对应的一种映射关系(除了低端2M的内存空间)。所以在后面的说明中就不用怎么考虑虚拟地址和物理地址的区别了。
   这里还有一点需要说明的是,对于ARM系统来说,其IO设备的地址是和普通的内存进行统一编址的。总共占据4G的地址空间。也就是说,我们访问一个地址,有可能是内存,也有可能是IO设备(说的准确些应该是控制IO设备的寄存器)。在HelloOs中映射了0x48000000-0x5aefffff的地址空间,用来访问IO。

   对于具体的如何使用MMU,也不是很难,参照对应相关的技术文档就可以。 这里就不多说了。简单说一点关于页表的设置问题,如上文中所述,这个页表其实就是内存中的一段数组,所谓设置页表,本质上就是填充这段数据空间内的数组项。

   好了,这一节暂且就到这吧。星期一早上七点半,新的一周开始了,还得努力加油啊。


 

   内存管理这一章内容比较多,这里先到这儿。下一章是基本内存管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值