写在最前面:本文代码转载自https://blog.csdn.net/weixin_52760656/article/details/127715747?spm=1001.2014.3001.5502
在写本次文章前,先允许我啰嗦两句。这次的文章是我在写操作系统实验时,从另一个博主那里学习然后写的代码,在完成他的代码的时候,我发现了几点问题,于是打算自己写一篇笔记,把我发现的问题和我自己在写代码中出现的问题当作经验和大家分享。本篇笔记为我的第一篇笔记,如有错误请在评论区指出,我可以和大家一起探讨。
本实验代码在文末。
实验环境:vscode。
设置一个表:
页号 | 状态 | 物理块号 |
0 | 1 | 9 |
1 | 1 | 5 |
2 | 1 | 4 |
3 | 0 | |
4 | 0 | |
5 | 0 | |
6 | 0 |
状态1表示该页在内存,状态0表示该页不在内存;
假设一个物理块大小为1K,即为1024B;
使用先进先出页面置换算法。
定义页面数PN,页面大小PAGESIZE;
#define PN 7//页面数
#define PAGESIZE 1024//页面大小:1K
定义结构体;
typedef struct
{
int P;//存在标志
int M;//修改标志
int pno;//页号
int bno;//物理块号
int place;//位移
}PAGETAB;
主函数里定义结构体数组存储页表PAGETAB s[];
void main(){
PAGETAB s[PN];
int i,sel;
int flag=1;
for(i=0;i<PN;i++){
s[i].pno=i;
if(i<3){
s[i].P=1;
}
else{
s[i].bno=0;
s[i].P=0;
}
}
s[0].bno=9;
s[1].bno=5;
s[2].bno=4;
}
先进先出页面置换算法;
void change(PAGETAB s[]){
int flag=1;
int a,p;//a为逻辑地址,p为页号
int x=0,i=0;
int weiyi,place;//位移量,物理地址
int found=0;
char st;//缺页状态
while(flag==1){
st='N';
printf("请输入逻辑地址:");
scanf("%d",&a);
p=a/PAGESIZE;
weiyi=a%PAGESIZE;
if(p>=PN){
printf("逻辑地址非法!\n");
}
else{
for(i=0;i<PN;i++){
if(s[i].pno==p){//利用页号p找到对应页
break;
}
}
if(s[i].P==0){//状态为0
st='Y';//说明缺页
for(x;x<PN;x++){//s页
if(s[x].P==1){
found=1;
break;
}
}//说明在s页中有状态为1的表,跳过下面的if
if(found=0){//说明s页中没有状态为1的表,执行此if
for(x=0;x<PN;x++){
if(s[x].P==1){
break;
}
}
}
found=0;
s[x].P=0;//s页状态修改为0
s[i].bno=s[x].bno;//p页物理块号记为s页所在的物理块号
s[x].bno=0;//s页块号修改为0
s[i].P=1;//p页状态修改为1
}
place=s[i].bno*PAGESIZE+weiyi;//物理地址=物理块号*页面大小+页内位移
printf("逻辑地址:%d\n页号:%d\n页内位移:%d\n是否缺页:%c\n物理块:%d\n物理地址:%d\n",a,p,weiyi,st,s[i].bno,place);
}
printf("是否继续?(1:是 0:否):");
scanf("%d",&flag);
}
}
显示当前页表;
void show(PAGETAB s[]){
int i;
for(i=0;i<PN;i++){
printf("页号:%d\n状态:%d\n物理块号:%d\n",s[i].pno,s[i].P,s[i].bno);
}
}
实验运行结果截图:
很明显,当输入的逻辑地址为2546时,页号为2,此时在页表中,页号为2的页状态为1,在change函数中,跳过if(s[i].P==0),直接输出;
当输入的逻辑地址为5456时,页号为5,此时在页表中,页号为5的页状态为0,进入if(s[i].P==0)中;
if(s[i].P==0){//此时页号i为5,状态为0
st='Y';//缺页状态设置为'Y'
for(x;x<PN;x++){
if(s[x].P==1){//找到第一个状态为1的页
found=1;
break; //跳出for循环
}
}//此时found为1,跳过下面的if
if(found=0){
for(x=0;x<PN;x++){
if(s[x].P==1){
break;
}
}
}
found=0;//设置found为0
s[x].P=0;//将找到的该页状态修改为0
s[i].bno=s[x].bno;//第i页(即第5页)物理块号记为找到的该页所在的物理块号
s[x].bno=0;//该页块号修改为0
s[i].P=1;//i页状态修改为1
}
因为输入逻辑地址为5456,所以,将页号为0的页淘汰,转移到页号为5的页面;
当输入的逻辑地址为9867的时候,页号为9,超出页表长度,输出错误。
if(p>=PN){
printf("逻辑地址非法!\n");
}
本次实验遇到的问题:
1:在转载原博主写的代码时,他有一处错误:
place = s[i].bno*PAGESIZE+place;
此处应该写为:
place=s[i].bno*PAGESIZE+weiyi;
place为物理地址,物理地址=物理块号*页面大小+页内位移
2:本人写的实验代码与原博主不同的还有:缺页状态。原博主使用的是int st=0代表缺页,st=1代表不缺页。事实上,st=0为不缺页,st=1为缺页状态。而我使用的是char st='N'代表不缺页,'Y'代表缺页。关于char还有一点要说的是,在printf中,使用%c输出,我开始使用的是%s,发现程序崩溃,后来一找发现是%c,此处为本人对C语言的不熟悉;还有一点,char st='N'时,N一定用单引号,如果是双引号会有警告提示,将指针变量赋值给char类型,这个是我打代码时打错了发现的问题,以上两点如果对你有帮助最好,没有帮助就看个乐呵。
3:借鉴原博主代码时发现在结构体里定义了一个int M,但是在后面的代码中并未出现M,所以我认为此M可删除,我懒就没删。
4:原博主主函数中有一段:
else{
s[i].bno = NULL;
s[i].P = 0;
}
此时s[i].bno的类型为int,而NULL类型为void *指针类型,此时也是将指针赋值给int, 也会报错,所以将NULL改为0,就不会报错了。
5:本人的代码注释中有一些错误,有看不懂的可以在评论区说,我会尽我所能去解释。
本实验完整代码:
#include<stdio.h>
#define PN 7//页面数
#define PAGESIZE 1024//页面大小:1K
typedef struct
{
int P;//存在标志
int M;//修改标志
int pno;//页号
int bno;//物理块号
int place;//位移
}PAGETAB;
void change(PAGETAB s[]){
int flag=1;
int a,p;//a为逻辑地址,p为页号
int x=0,i=0;
int weiyi,place;//位移量,物理地址
int found=0;
char st;//缺页状态
while(flag==1){
st='N';
printf("请输入逻辑地址:");
scanf("%d",&a);
p=a/PAGESIZE;
weiyi=a%PAGESIZE;
if(p>=PN){
printf("逻辑地址非法!\n");
}
else{
for(i=0;i<PN;i++){
if(s[i].pno==p){//利用页号p找到对应页
break;
}
}
if(s[i].P==0){//状态为0
st='Y';//说明缺页
for(x;x<PN;x++){//s页
if(s[x].P==1){
found=1;
break;
}
}//说明在s页中有状态为1的表,跳过下面的if
if(found=0){//说明s页中没有状态为1的表,执行此if
for(x=0;x<PN;x++){
if(s[x].P==1){
break;
}
}
}
found=0;
s[x].P=0;//s页状态修改为0
s[i].bno=s[x].bno;//p页物理块号记为s页所在的物理块号
s[x].bno=0;//s页块号修改为0
s[i].P=1;//p页状态修改为1
}
place=s[i].bno*PAGESIZE+weiyi;//物理地址=物理块号*页面大小+页内位移
printf("逻辑地址:%d\n页号:%d\n页内位移:%d\n是否缺页:%c\n物理块:%d\n物理地址:%d\n",a,p,weiyi,st,s[i].bno,place);
}
printf("是否继续?(1:是 0:否):");
scanf("%d",&flag);
}
}
void show(PAGETAB s[]){
int i;
for(i=0;i<PN;i++){
printf("页号:%d\n状态:%d\n物理块号:%d\n",s[i].pno,s[i].P,s[i].bno);
}
}
void main(){
PAGETAB s[PN];
int i,sel;
int flag=1;
for(i=0;i<PN;i++){
s[i].pno=i;
if(i<3){
s[i].P=1;
}
else{
s[i].bno=0;
s[i].P=0;
}
}
s[0].bno=9;
s[1].bno=5;
s[2].bno=4;
while(flag==1){
printf("************系统菜单************\n");
printf("***********1: change***********\n");
printf("***********2: show ***********\n");
printf("***********0: exit ***********\n");
printf("*******************************\n");
printf("输入你的选择(0-2):");
scanf("%d",&sel);
switch (sel)
{
case 1:change(s);break;
case 2:show(s);break;
case 0:flag=0;break;
default:printf("输入错误!");break;
}
}
}
感谢您的观看,请多提宝贵意见,谢谢!