实验三. 内存管理
二、实验内容
假定页面大小为4K,物理内存128M,设计并实现一个内存分配和回收的程序,使用C语言或Python语言编写程序实现这个程序并进行测试。
要求:(1)至少5个进程;
(2)要求有空块管理;
(3)要求有一个逻辑地址到物理地址的变换。
四、程序代码
4.1 代码主要思想及设计原理
1. 在main函数中调用内存分配, 地址使用(包含地址转换) , 内存释放函数.
2. 在全局变量中有基本的页大小和内存大小定义,也有进程类的定义和进程队列的定义.
3. init初始化函数为根据输入的进程数创建需要随机数个大小的内存,然后计算分配页面.(随机数服从一个高斯函数),也包含随机初始化页的占用情况.
4. 内存分配使用最先适应算法,即在位视图中查找,找到空块就填入,占用.
5. 内存释放,直接释放资源,修改位视图.
4.2 程序代码
#include <iostream>
#include <random>
#include <chrono>
#include <cmath>
#define PAGESIZE 4000
#define MEMORYSIZE 128000000
using namespace std;
int bitview[32000];//页的位视图,1表示被占用
int freeBlocksCount;
class process
{
public:
int pid;
int needmemory;
int needpage;
int pagetable[128];
};
int psum;
process p[128];//进程总数量在这里修改
void createProcess(int psum);
void initBitView(){
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);
// 第一个参数为高斯分布的平均值,第二个参数为标准差
std::normal_distribution<double> distribution(0.0, 15.0 * PAGESIZE);
int t;
for(int i=0;i<32000;i++){
t=abs((int)distribution(generator));
t=t%2;
bitview[i]=t;
}
}
void init()
{
cout << "请输入进程数量:" << endl;
cin >> psum;
createProcess(psum);
initBitView();
cout<<"已经随机初始化内存块的占用情况" <<endl;
// for(int i=0;i<100;i++){
// cout << bitview[i]<<" " <<ends;
// }
}
void createProcess(int psum)
{
// 从epoch(1970年1月1日00:00:00 UTC)开始经过的纳秒数,unsigned类型会截断这个值
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);
// 第一个参数为高斯分布的平均值,第二个参数为标准差
std::normal_distribution<double> distribution(0.0, 15.0 * PAGESIZE);
cout <<"进程号|"<<"需要的总内存|"<<" 计算后需要的块数|" <<endl;
for (int i = 0; i < psum; i++)
{
process p1;
p1.pid=i;
p1.needmemory = abs((int)distribution(generator));
p1.needpage = p1.needmemory / PAGESIZE ;
if(p1.needmemory%PAGESIZE)p1.needpage++;
cout <<i<<" : " << p1.needmemory <<" " <<p1.needpage<<endl;
p[i]=p1;
}
}
void memAlocation(){
int bitviewpoint=0;
for(int i=0;i<psum;i++){
cout << "\n进程"<<p[i].pid<< "已分配" <<p[i].needpage <<"页. 分配的页号为:"<<endl;
for(int j=0;j<p[i].needpage;j++){
while(bitview[bitviewpoint]==1)bitviewpoint++;
bitview[bitviewpoint]=1;
p[i].pagetable[j]=bitviewpoint;
cout <<bitviewpoint <<" " <<ends;
}
}
}
int addrTranslate(int plot,int addrInPage){
return plot+addrInPage;
}
void addrAccess(){
// 从epoch(1970年1月1日00:00:00 UTC)开始经过的纳秒数,unsigned类型会截断这个值
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);
// 第一个参数为高斯分布的平均值,第二个参数为标准差
std::normal_distribution<double> distribution(0.0, 15.0 * PAGESIZE);
int t=abs((int)distribution(generator));
for(int i=0;i<t%25;i++){
int pRandom=abs((int)distribution(generator));
pRandom=pRandom%psum;
int randn=abs((int)distribution(generator));
randn=randn%4000;
cout <<"进程"<<p[pRandom].pid<<"访问了"<<p[pRandom].pagetable[1]<<"页的地址,地址为:"<<
addrTranslate((p[pRandom].pagetable[1]) *4000, randn)<< endl;
}
}
void memRecover (){//内存回收
for(int i=0;i<psum;i++){
for(int j=0;j<p[i].needpage;j++){
bitview[p[i].pagetable[j]]=0;
}
cout <<"进程" << p[i].pid <<"共释放了" <<p[i].needpage <<"页. "<<endl;
}
}
int main()
{
init();
memAlocation();
addrAccess();
memRecover();
return 0;
}
五、运行结果
多次测试的结果:
六、结果分析
- 由结果可以直观看出,进程创建正确,随机产生需要的内存大小,并计算需要的页数; 然后进行块分配,写入页表. 然后进程按需访问内存, 最后使用完成释放.