Linux内存管理和页面置换相关算法
文章目录
内存管理
伙伴系统
Linux内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生。Linux采用伙伴系统解决外部碎片的问题。
伙伴系统简介:
伙伴系统的宗旨就是用最小的内存块来满足内核的对于内存的请求。在最初,只有一个块,也就是整个内存,假如为1M大小,而允许的最小块为64K,那么当我们申请一块200K大小的内存时,就要先将1M的块分裂成两等分,各为512K,这两分之间的关系就称为伙伴,然后再将第一个512K的内存块分裂成两等分,各位256K,将第一个256K的内存块分配给内存,这样就是一个分配的过程。
Linux 采用这著名的伙伴系统算法来解决外部碎片的问题。把所有的空闲页框分组为 11 块链表,每一块链表分别包含大小为1,2,4,8,16,32,64,128,256,512 和 1024 个连续的页框。对1024 个页框的最大请求对应着 4MB 大小的连续RAM 块。每一块的第一个页框的物理地址是该块大小的整数倍。例如,大小为 16个页框的块,其起始地址是 16 * 2^12 (2^12 = 4096,这是一个常规页的大小)的倍数。 然后尽可能以最适合的方式满足程序内存需求。
算法实现:
依据算法简介,我们模拟一个链表数组,每一个链表代表一个类型的内存块,每当产生内存调用的需求时(例如要调用内存大小为a),进行判断,找到这样的情况:2i-1<2i ,然后查询第i个内存块链表,如果有没被占用的,则直接调用,设置为占用,否则向下个更大的2i+1内存块访问是否有内存块剩余,分配所需要的2i内存,将剩余的2i内存分配到上一个内存块链表尾部。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1nURRww-1622120569583)(C:\Users\wizard\AppData\Roaming\Typora\typora-user-images\1621996572305.png)]
伙伴系统的回收算法:
当出现内存回收的指令时,我们将内存回收时为了比面产生内存碎片,需要将内存进行合并。 当用户申请的内存块不再使用时,系统需要将这部分存储块回收,回收时需要判断是否可以和其它的空闲块进行合并。
在伙伴系统中每一个存储块都有各自的“伙伴”,当用户释放存储块时只需要判断该内存块的伙伴是否为空闲块,如果是则将其合并,然后合并的新的空闲块还需要同其伙伴进行判断整合。反之直接将存储块根据大小插入到可利用空间表中即可。
判断一个存储块的伙伴的位置时,采用的方法为:如果该存储块的起始地址为 p,大小为2k,则其伙伴所在的起始地址为: p-2k和p+2k;然后判断其大小是否为2k,若是,则是一个“伙伴”。
算法实现:
在每一个链表内加入其初始地址,当有内存块被回收时,判断在该内存块中链表中是否存在有空闲的“伙伴”,若有,则进行合并。伙伴的判断条件是其地址和该回收的内存地址合并后仍然可以内存连续。
代码实现(C++):
#include<bits/stdc++.h>
using namespace std;
struct L{
bool occupyed=0;//占用情况
int location;//模拟地址
L *next=NULL;
};
L li[11];
struct PI{
L *to;//指向的链表节点
int num;//存储大小
};
PI pi[105];
/**
2的次幂函数
*/
int pows(int power)
{
int data=1;
while(power)
{
power--;
data*=2;
}
return data;
}
/**
判断该内存块的占用情况
*/
L* pan(int i)
{
L *p;
p=li[i].next;
while(p)
{
if(p-&