实验五 操作系统之存储管理
一、实验目的
连续内存分配方式会形成许多“碎片”,虽然可以通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无需再进行“紧凑”。基于这一思想而产生了离散分配方式。
如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。
在分页存储管理方式中,如果不具备页面兑换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具备支持虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。
本实验通过程序模拟操作系统的基本分页存储管理方式,进一步理解这一内存分配方式的原理和特点,加深对理论知识的掌握。
二、实验要求
1、用C语言或Java语言编写程序模拟操作系统对内存的基本分页存储管理方式
2、程序要能正确对“内存”进行“分配”和“回收”,能接受用户的输入,显示内存的分配情况,并有一定的容错能力。
3、每个人独立按时完成实验内容。
三、实验内容
本实验假定内存空间已经按块划分,目标程序无需关心内存块大小等底层细节,只需按算法对内存块进行分配即可。程序应该实现以下功能:
1、内存初始化。假定内存块共有N个,初始化后的内存空间应该有一部分已经被使用,这可以用随机数或程序内部的其他算法完成。
2、程序应该能接受用户输入的进程信息,并为之分配内存,返回分配结果(成功或失败),注意,此处应该考虑到不合法的输入并进行相应处理。
3、程序能回收用户指定的进程所占用的内存空间,因此,程序可能需要为每个进程分配一个唯一的进程号并给出详细的提示信息。
4、能直观合理地显示内存分配情况。
5、程序界面友好,便于操作和查看运行结果。
四、程序员代码
#include<stdio.h> #define N 200 static int shengyu;//剩余空间 struct nei{ int id;//内存首地址 int zyid;//作业名 int free;//是否空闲 int size;//大小 }a[N]; struct zuoye{ int name;//作业名 int changdu;//作业长度 int shoudizhi;//存入后首地址 int free;//数组是否被占用 }zy[N]; void cun() { int i,j,x,n,m; for(i=0;i<N;i++) { if(zy[i].free==0) break; } if(i==N) { printf("找不到所需的大小! "); return ; } printf(" 输入你的作业名:"); scanf("%d",&zy[i].name); if(zy[i].name<=0) { printf("错误:id<=0! 退出! "); return; } for(m=0;m<N;m++) if(zy[i].name==zy[m].name) { if(i==m); else { printf("错误:同名! 退出! "); return; } } printf(" 输入你的作业长度:"); scanf("%d",&zy[i].changdu); printf(" "); for(j=0;j<N;j++) { if(a[j].free==0&&a[j].size>=zy[i].changdu) break; } if(j==N) { printf("找不到所需的大小! "); return; } a[j].zyid=zy[i].name; zy[i].free=1; zy[i].shoudizhi=a[j].id; a[j].free=1; a[j].size=zy[i].changdu; shengyu-=zy[i].changdu; x=a[j].id+zy[i].changdu; for(n=x;n<N;n++) if(a[n].free==1) break; a[x].size=n-x; } void qu() { int name,i,j,x,y,z; printf("输入你要取的作业名(若不知道作业名按0退出):"); scanf("%d",&name); printf(" "); if(name==0) return; for(i=0;i<N;i++) { if(zy[i].name==name) break; } if(i==N) { printf("无此作业!退出! "); return; } for(j=0;j<N;j++) { if(a[j].id==zy[i].shoudizhi) break; } zy[i].free=0; zy[i].name=0; a[j].free=0; x=j+a[j].size; if(a[x].free==0) { a[j].size+=a[x].size; a[x].size=0; } y=a[j].id-1; for(z=y;z>=0;z--) { if(a[z].free==1) break; } if(z<0) return; for(y=a[j].id-1;y>z;y--) { if(a[y].size>0&&a[y].free==0) break; } if(y==z) return; a[y].size+=a[j].size; a[j].size=0; } void xianshi() { int i=0,m; printf("1:查看剩余空间! "); printf("2:查看所有作业! "); printf(" 请选择:"); scanf("%d",&m); switch(m) { case 1: { if(shengyu==0) { printf("剩余空间不足! "); return; } for(i=0;i<N;i++) { if(a[i].free==0&&a[i].size>0) printf("存储长度=%d,剩余空间=%d ",a[i].id),a[i].size; } break; } case 2: { if(shengyu==N) { printf(" "); return; } for(i=0;i<N;i++) { if(a[i].free==1) printf("作业名=%d,长度=%d,首地址=%d ",a[i].zyid,a[i].size,a[i].id); } } } } void main() { shengyu=N; int m; int i; for(i=0;i<N;i++) { a[i].id=i; a[i].free=0; a[i].size=0; zy[i].free=0; a[i].zyid=0; zy[i].name=0; } a[0].size=N; while(true) { char c1,c; printf(" "); printf(" 1、存入"); printf(" 2、取出"); printf(" 3、查看"); printf(" 4、退出"); while(true) { printf(" 请选择菜单项:"); scanf("%d",&m); if(m==1||m==2||m==3||m==4) break; printf(" "); } if(m==4) break; switch(m) { case 1: { while(true) { char c; cun(); printf("是否继续存入(Y/N):"); scanf("%c",&c); scanf("%c",&c); printf(" "); if(c=='y'||c=='Y'); else if(c=='n'||c=='N') break; else{ printf(" 输入错误! "); break; } } break; } case 2: { while(true) { char c; qu(); printf("是否继续取出(Y/N):"); scanf("%c",&c); scanf("%c",&c); printf(" "); if(c=='y'||c=='Y'); else if(c=='n'||c=='N') break; else{ printf(" 输入错误! "); break; } } printf(" "); break; } case 3: { xianshi(); printf(" "); break; } } scanf("%c",&c1); loop:printf("是否继续其他操作(Y/N):"); scanf("%c",&c1); scanf("%c",&c); printf(" "); if(c1=='y'||c1=='Y'); else if(c1=='n'||c1=='N') break; else{ printf(" 输入错误! "); goto loop; } } }
五、运行结果
进入主界面:
存入界面:
查看剩余空间和作业名:
取出作业后再次查看:
总结:经过测试结果完全正常。经过编写代码和学习让我对操作系统方面的知识更深一步地得到了理解和巩固。