一、总体设计
1.1 需求概述
按照需求分析的规格要求,需要提供内存的申请、回收、查看内存空间分布情况、支持多个非连续内存区间的管理、提供对MPU的支持,相同硬件平台下任意复杂环境的内存申请、回收时间在允许的范围内。
Fans-rt的内存管理分为系统全局内存管理、内核对象内存池管理、应用全局堆管理和任务局部堆管理。
1.2系统全局内存管理概述
在计算机系统中,可能同时存在多个非连续的内存区间,例如X86系统E820表中的多个内存块、单片机系统上的片上内存和片外内存。Fans-rt 将每一个内存区间作为一个内存域(Region)进行管理,系统可以同时存在多个不同大小的域。系统初始化时将每个域划分为若干个大小相等的块,这些大小相等的块称为页面(Page),页的大小可以通过编译配置选项进行配置,在同一个系统中所有页面的容量均是相等的。为了管理域中的页面,fans-rt 为每一个域初始化一个表,称为页表,表中的每一个表项(称为页表项)用于描述它所对应的页面的使用情况、该页面在段中的位置(边界页需要描述是左边界还是右边界,中间页该值不使用),段中的页数量等信息。页面的分配使用BUDDY算法,对于首页需要在页表项中描述上一个段的尾页号,对于尾页,需要描述下一个段的首页号,所有页数相同的空闲段形成一个链表以便在分配时,能够从指定页数的空闲链表中快速分配。已被分配给应用程序使用的段形成一个使用链表,释放时将段从使用链表中摘除重新挂到空闲链表中,释放时发现空闲伙伴段应当合并为更大的空闲段。
Region以及Region中的Page的管理由内存管理服务(MMS)统一提供,MMS服务可以通过编译配置选项打开或关闭,在启用MMS的系统中,所有内存分配活动均需要首先通过MMS分配内存段,如有必要再将分配到的段初始化为堆,再从堆中进行分配。在硬件条件允许的情况下,MMS应该提供内存保护功能,应用程序只允许访问(写)分配给应用程序的段,未分配或非分配给当前任务的段禁止访问。
注:fans-rt所管理的内存页只是为方便管理(分配、释放)而划分的大小一致的内存块,不等价于某些处理器平台上所支持的页式内存管理中所描述的内存页。
图2-1为Region布局图(不包括行布局),不可用区域以上部分为片上内存(Region[0]),不可用区域以下部分为片外内存(Region[1])。Fans-RT需要提供对多个Region的管理,Region的大小由芯片的能力决定,每一个Region有一个专门的页管理器负责该Region中页面的分配回收。
图2-1
1.3内核对象内存池管理概述
内核对象内存池需要管理各种不同大小的内核对象的而分配、释放、查找等,这些对象包括IPC对象、任务上下文对象、堆栈对象等,对象可以分为命名对象和无名对象。
命名对象:命名对象是指必须命名的对象(对象拥有一个唯一的名称),系统中的命名对象使用链表串联,在分配对象时通过链表搜索是否已存在同名对象,如果已有同名对象,则分配失败。释放时需要从链表中摘除被释放对象。
无名对象:无名对象是指不需命名的对象,分配对象时不需要检查对象名是否已经存在,直接从POOL中进行分配,无名对象的分配和释放必须满足O1的时间复杂度需求。
对象管理采用二级索引管理方式,相同大小的对象使用一个对象容器(Container)进行管理,每个容器中有若干个池(POOL),每个POOL中有若干个块(BLOCK),同一个容器中的块大小是相同的,不同类的对象如果大小一致,则由同一个容器进行管理。对于每一个容器需要管理多少个块可以通过编译配置选项进行配置,对象容器也有独立的数据结构描述当前容器所管理的POOL和BLOCK数量,在同一个系统中允许不同的容器所管理的块数量存在差异。
在开启MMS服务的系统中,系统初始化对象管理服务(OMS)时,应当根据配置从MMS服务中申请不同的段来初始化不同大小的对象容器,在分配对象时,从相应大小的对象容器中进行分配。
在关闭MMS服务的系统中,对象管理服务的所有对象容器的内存空间由静态数组分配。
对象管理服务所管理的对象均为内核对象,任何应用程序不能直接获得该对象的指针,在硬件条件支持的情况下,应当提供对内核对象的保护,任何应用程序不能直接对内核对象进行写操作,需要访问内核对象必须调用对象管理服务。
1.4应用全局堆管理概述
应用全局堆由从系统中分配的段被堆管服务(HMS)初始化后形成,全局堆初始化完成后,堆的所有内存空间将失去保护,系统中所有任务均可对全局堆中的内存空间进行读写操作,所以全局堆的管理数据和所管理的堆空间应做到完全分离,以保证应用程序的设计缺陷不会影响到整个系统的安全。
在全局堆的管理上,HMS与MMS使用一致的方法,所以分配和释放算法应当使用相同的代码。
1.5任务局部堆管理概述
在任务初始化时,根据初始化参数对任务局部堆进行初始化,局部堆的初始化、分配、释放等动作均在应用层完成。局部堆使用BUDDY算法进行分配,堆被划分成若干个大小相等的块,每一个行的首块和尾块用于记录该行的属性信息,这些属性包括该行的使用情况,该行的块数量,对于行首,需要记录行尾块指针、上一个行的尾块指针,对于行尾需要记录行首块指针、下一个行的尾块指针。每行的第二个块开始到倒数第二个块为止为分配给应用程序的内存空间。所有页数相同的空闲行形成一个空闲链表以便在分配时,能够从指定块数的空闲链表中快速分配。已被分配给应用程序使用的行形成一个使用链表,释放时将行从使用链表中摘除重新挂到空闲链表中,释放时发现空闲伙伴行应当合并为更大的空闲行。
1.6内存保护概述
Fans-rt 提供对MPU和MMU的支持。
在拥有MPU的处理器上,内核特权级可以访问所有Region的内存空间。对于应用程序,需要提供至少四个可访问内存区域:
1. 堆栈区,当前任务的堆栈区域对于当前任务必须是可读可写的,但不能对其他任务的堆栈区域进行读写。
2. 全局堆区域,所有应用程序均可对全局堆的内存空间进行读写。
3. 局部堆区域,当前任务的局部堆对于当前任务是可读可写的,但任务不能访问其他任务的局部堆。
4. 应用层静态变量区:代码中的静态变量在编译后形成的区域,任务可以对该区域进行访问。
在拥有MMU的处理器上,所有任务使用相同的内存地址空间(物理地址映射完全一致),系统为每一个任务准备一个页目录表(粗页表-X86称为页目录表,ARM称为粗页表),用于描述当前任务对内存每个页面的访问权限,任务发生切换时,更换页目录表。不提供虚拟内存支持,缺页按照非法访问处理。