正文
本文主要介绍内存的基本概念以及操作系统的内存管理算法。
一、内存的基本概念
内存是计算机系统中除了处理器以外最重要的资源,用于存储当前正在执行的程序和数据。内存是相对于CPU来说的,CPU可以直接寻址的存储空间叫做内存,CPU需要通过驱动才能访问的叫做外存。
二、ROM&RAM&Flash
内存一般采用半导体存储单元,分为只读存储器(ROM,Read Only Memory)、随机存储器(RAM,Random Access Memory)ROM一般只能读取不能写入,掉电后其中的数据也不会丢失。RAM既可以从中读取也可以写入,但是掉电后其中的数据会丢失。内存一般指的就是RAM。
ROM在嵌入式系统中一般用于存储BootLoader以及操作系统或者程序代码或者直接当硬盘使用。近年来闪存(Flash)已经全面代替了ROM在嵌入式系统中的地位,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程的特性,而且断电也不会丢失数据,同时可以快速读取数据。
从分配内存是否连续,可以分为两大类。
连续内存管理
非连续内存管理
将进程分散到多个不连续的内存空间中,可以减少内存碎片,内存使用率更高。如果分配的基本单位是页,则称为分页内存管理;如果基本单位是段,则称为分段内存管理。
当前的操作系统,普遍采用非连续内存管理方式。不过因为分配粒度较大,对于内存较小的嵌入式系统,一般采用连续内存管理。本文主要对嵌入式系统中常用的连续内存管理的分区式内存管理进行介绍。
固定分区
事先就把内存划分为若干个固定大小的区域。分区大小既可以相等也可以不等。固定分区易于实现,但是会造成分区内碎片浪费,而且分区总数固定,限制了可以并发执行的进程数量。 动态分区
根据进程的实际需要,动态地给进程分配所需内存。
动态分区管理一般采用空闲链表法,即基于一个双向链表来保存空闲分区。对于初始状态,整个内存块都会被作为一个大的空闲分区加入到空闲链表中。当进程申请内存时,将会从这个空闲链表中找到一个大小满足要求的空闲分区。如果分区大于所需内存,则从该分区中拆分出需求大小的内存交给进程,并将此拆分出的内存从空闲链表中移除,剩下的内存仍然是一个挂在空闲链表中的空闲分区。
空闲链表法有多种数据结构实现,这里介绍一种较为简单的数据结构。每个空闲分区的数据结构中包含分区的大小,以及指向前一个分区和后一个分区的指针,这样就能将各个空闲分区链接成一个双向链表。
First Fit(首次适应算法)
First Fit要求空闲分区链表以地址从小到大的顺序链接。分配内存时,从链表的第一个空闲分区开始查找,将最先能够满足要求的空闲分区分配给进程。
Next Fit(循环首次适应算法)
Best Fit(最佳适应算法)
Worst Fit(最坏适应算法)
Two LevelSegregated Fit(TLSF)
Buddysystems(伙伴算法)
1、计算一个i值,使得2i-1<n≤2i
2、在空闲分区大小为2i的空闲链表中查找
3、如果找到空闲块,则分配给进程
4、如果2i的空闲分区已经耗尽,则在分区大小为2i+1的空闲链表中查找
6、如果2i+1的空闲分区还是不存在,则继续查找大小为2i+2的空闲分区。如果找到,需要进行两次拆分。第一次拆分为两块大小为2i+1的分区,一块分区挂到大小为2i+1的空闲链表中,另一块分区继续拆分为两块大小为2i的空闲分区,一块分配给进程,另一块挂到大小为2i的空闲链表中
7、如果2i+2的空闲分区也找不到,则继续查找2i+3,以此类推
内存算法 | 优点 | 缺点 |
First Fit | 高地址空间大空闲块被保留 | 低地址空间被不断拆分,造成碎片;每次都从第一个空闲分区开始查找,增加了查找时的系统开销 |
Next Fit | 空闲分区分布比较均匀,算法开销小 | 缺乏大内存空闲块 |
Best Fit | 用最小内存满足要求,保留大内存空闲块 | 每次分配后所拆分出来的剩余空闲内存总是最小的,造成许多小碎片,算法开销大 |
Worst Fit | 每次分配后所拆分出来的剩余空闲内存仍较大,减少小碎片产生 | 缺乏大内存空闲块,算法开销大 |
TLSF | 查找效率高,时间复杂度小,碎片问题表现良好 | 内存回收时算法复杂,系统开销大 |
Buddy systems | 内部碎片比较严重 | 外部碎片较少 |
声明:本文转自LiteOS物联网操作系统
版权归原作者所有,进作为学术讨论与研究,如涉及作品版权问题,请及时与我们联系,谢谢!
最后
好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个赞~
bug菌唯一、永久、免费分享嵌入式技术知识平台~
推荐专辑 点击蓝色字体即可跳转
☞ MCU进阶专辑
☞ “bug说”专辑 ☞ 专辑|手撕C语言
☞ 专辑|经验分享