操作系统实验四:模拟请求分页管理中地址转换和缺页中断处理

写在最前面:本文代码转载自https://blog.csdn.net/weixin_52760656/article/details/127715747?spm=1001.2014.3001.5502

在写本次文章前,先允许我啰嗦两句。这次的文章是我在写操作系统实验时,从另一个博主那里学习然后写的代码,在完成他的代码的时候,我发现了几点问题,于是打算自己写一篇笔记,把我发现的问题和我自己在写代码中出现的问题当作经验和大家分享。本篇笔记为我的第一篇笔记,如有错误请在评论区指出,我可以和大家一起探讨。 

本实验代码在文末。

实验目的: 了解内存请求分页管理中地址转换过程与先进先出置换算法和缺页中断处理过程。

实验环境:vscode。

设置一个表:

页号状态物理块号
019
115
214
30
40
50
60

状态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;
        }
    }
}

感谢您的观看,请多提宝贵意见,谢谢!

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 分页管理地址转换是指将逻辑地址转换为物理地址的过程。在分页管理,逻辑地址由页号和页内偏移量组成,而物理地址由页框号和页内偏移量组成。地址转换的过程需要使用页表来实现,通过查找页表对应的页号,可以得到该页所在的页框号,然后将页内偏移量加上页框号得到物理地址。 缺页中断处理是指当程序访问的页面不在内存时,操作系统需要将该页面从磁盘读入内存,然后再进行地址转换。这个过程需要使用缺页中断机制来实现,当程序访问的页面不在内存时,CPU会产生一个缺页中断,操作系统会根据页表的信息将该页面从磁盘读入内存,并更新页表的信息,然后再重新执行访问该页面的指令。 ### 回答2: 请求分页管理是一种虚拟内存管理技术,将物理内存分成若干等大小的区域(页面),并将进程的逻辑空间也划分成等大小的区域(页)。将进程的页调入物理内存,使进程访问逻辑地址时自动转换为物理地址,从而实现了虚拟内存的抽象。 地址转换请求分页管理的核心操作之一,它主要是将进程的虚拟地址映射到物理地址上。地址转换部分通常位于处理器(CPU)的硬件,其操作链路如下:当CPU访问虚拟地址时,处理器会将该地址发送给地址转换机构。地址转换机构先通过地址转换表得到与该虚拟地址对应的物理页框号,然后再加上虚拟地址的页内偏移量,最终得到物理地址。这个过程是透明的,对进程来说,它看到的仍然是逻辑地址。 缺页中断处理请求分页管理的另一个重要操作,在内存不足时,操作系统会将进程暂时挂起,将进程未能获取的页面调入内存,然后再让进程继续运行。这个过程,当进程访问一个还未被调入内存的页面时,请求分页管理会发出缺页中断信号,从而通知操作系统重新为该进程映射虚拟地址到物理地址的过程,并确定该页面的位置,将其调入内存。 总之,地址转换缺页中断处理请求分页管理的核心操作,这些操作必须快速有效、可靠性强,从而确保操作系统能够高效地管理虚拟内存,满足进程的空间需求。 ### 回答3: 分页管理是操作系统一种重要的内存管理技术,它采用虚拟内存和物理内存分离的方式,使得进程可以在逻辑上拥有比实际物理内存更大的内存空间。地址转换缺页中断处理是分页管理的两个关键技术,以下分别进行详细说明: 地址转换:当进程访问一个虚拟地址时,操作系统需要将该地址转换为实际物理地址,以访问对应的物理存储空间。地址转换过程主要包括两个步骤:页表查找和页内偏移计算。操作系统维护了每个进程的页表,该表记录了虚拟地址和实际物理地址之间的映射关系,当进程访问一个虚拟地址时,首先通过页表进行查找,获取到对应的物理页框号。然后,结合物理页框大小和地址在所在页内的偏移量,计算出实际物理地址。这样,进程就可以通过实际物理地址直接访问物理内存,完成内存读写操作。 缺页中断处理:当进程访问一个虚拟地址,但其对应的物理页框不存在于内存时,就会发生缺页中断,操作系统需要进行一系列的处理操作,以将缺失的物理页框从存储器读取到内存,使得进程可以正常访问。缺页中断处理主要包括以下几个步骤:首先,操作系统需要通过页表获取到缺失的虚拟地址所在页的页号,然后查找硬盘或其他外部存储介质,将页面读取到内存的空闲物理页框,并修改页表的映射关系。最后,重新执行导致缺页中断的指令,从而完成进程对缺失的物理页框的访问。如果内存没有足够的物理页框,操作系统需要通过页面置换算法,将一些暂时不会被使用的页替换掉,以腾出足够的物理内存空间。 以上是关于分页管理地址转换缺页中断处理的详细说明,这两个技术是确保分页管理正常运行的关键所在,也是操作系统内存管理不可或缺的组成部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值