精华内容
下载资源
问答
  • 基本分页存储管理实验
    2022-03-04 22:24:07

    基本分页存储管理

    为了上述分页思想产生碎片的问题,提出了分页的思想:把主存空间划分为大小相等而且固定、容量较小的块,作为主存的基本存储单位,每个进程的信息也以块大小划分,在存入内存的时候进程以块为单位存入,一个进程装入一个或者多个块。在形式上看分也类似于固定分区,但是每个分区都很小,因此即便进程没有用满分区,留下来的内部碎片也很少。

    1.分页基本概念

    (1)页面和页面大小

    进程中的块又称之为页面或者,内存中的块称之为页框或者页帧。内存中的页框有页号,从低地址到高地址递增。页面的大小为整数幂,方便进行划分。为了管理分页,内存中会有页表以标记每个进程的页面对应的是内存中的哪个页框,同时页面大小设置应该适中,太小会使得页表过长,进程页数太多,换出换入次数增多;太大会导致碎片增多。在进程装入内存的时候,会向页表中写入,进程的每一个页面对应的是内存的哪个一页框,为后面寻址提供根据。

    (2)地址机构
    假设内存大小为2n比特,并且划分页面大小为2k比特,则需要划分2n-k个页,其内存地址表示需要n位,其中低k位表示的是页内地址,高n-k位表示的是在第几个页。因此,将进程中的逻辑地址转化为页内地址步骤如下:

    假设页大小为32B,页数为16页,需要访问的地址为0010 01010

    • 计算逻辑页号:然后取逻辑地址的高4位,可以知道这是第2个页。
    • 找到对应页框在内存中的位置:通过页表,查询进程的第二个页对应内存的位置
    • 算出逻辑地址对应的页内偏移量:取逻辑地址的低k位,知道是本页的第10个位置
    • 物理地址=页框开始物理地址+页内偏移量

    页号 = 逻辑地址/页面大小;页内偏移量=逻辑地址mod页面大小;

    2.基本地址变换机构

    在系统中会设置一个页表寄存器(PTR),用于存放页表在内存的起始地址F和页面长度M。进程未执行的时候,页表的起始地址和页表长度存放在本进程PCB中,当进程被调度的时候,才会将页表起始地址和页表长度装入页表寄存器中。主要地址变换过程如下:

    • 根据逻辑地址算出页号、页内偏移量
    • 页号是否合法,是否越界
    • 根据页表起始地址和页号找到对应页表项
    • 根据页表箱中记录的内存块号和页内偏移量得到最终物理地址
    • 访问物理内存的对应单元

    为了方彬啊找到页表项,页表一般放在连续的内存块中。

    3.具有快表的地址变换机构
    根据程序执行的空间局部性原理,上一条指令所在的页框很有可能也是下一条指令执行所在的页框,因此为了提高逻辑地址到物理地址转换的速度,地址比那换机构中增设了一个具有并行查找能力的高速缓冲存储器——快表,又称相连存储器(TLB),与之相对的在内存中的页表则是慢表
    在快表出现之后,地址变换如下:

    • CPU给出逻辑地址后,硬件进行地址转换,将页号送入高速缓存寄存器,并且将页号和快表之中的页号进行对比
    • 如果命中,则直接从中取出该页对应的页框号和页内偏移量组成物理地址
    • 如果不命中,则访问主存之中的页表,并且将读出的页框数据存入快表中,以便后续可能的再次访问

    该做法类似于高速缓存,一般命中率在90%以上。

    4.两级页表

    单级页表在使用上也会存在一定的问题:首先是搜又页表箱需要在内存中连续存放,页表要是很大时需要很大的连续空间;其次,一段时间内并非所有页面都用得到,让整个页表常驻内存有一定浪费。
    因此提出了两级页表的概念,逻辑地址被划分为了如下模型:

    一级页号二级页号页内偏移量

    (待补充

    更多相关内容
  • 这是操作系统实验报告,实现的是操作系统,里面含有源代码,能够对内存进行初始化,内存分配和回收等功能,决定原创。希望对各位有帮助
  • 操作系统 实验4【基本分页存储管理
    1. 操作系统 实验1【短作业优先调度算法(C++实现——FCFS\SJF\HRRN)】
    2. 操作系统 实验2【动态高优先权优先调度算法 C++实现】
    3. 操作系统 实验3【动态分区存储管理 Python实现】
    4. 操作系统 实验4【基本分页存储管理 C++实现】

    目录

    一、实验目的(目的与任务)

    二、实验内容(内容、要求与安排方式)

    三、实验代码

    ①创建表示作业的结构体

    ②编写建立作业的函数

    ③编写回收作业、释放内存的函数

    ④编写显示所有作业占用物理块的函数

    ⑤编写查看作业情况的函数

    ⑥编写显示内存块使用情况的函数

    实验代码

    四、实验结果

    五、实验总结


    一、实验目的(目的与任务)

    熟悉并掌握基本分页存储管理的思想。

    熟悉并掌握基本分页存储管理的分配和回收方式,并能够模拟实现。

    二、实验内容(内容、要求与安排方式)

    用高级语言模拟实现基本分页存储管理,要求:

    1. 内存空间的初始化——可以由用户输入初始内存空间各个物理块情况。(用二维矩阵的方式按物理块号,逐行给出每个物理块的状态,1——表示已分配,0——表示未分配,并能够将行标、列标转换为对应的物理块号,以查看或修改每一个块的状态,要求:初始时部分物理块已分配)
    2. 基本分页的分配过程:由用户输入作业号和作业的大小(这里的大小是逻辑页面数),实现分配过程:空间充足,分配,修改状态矩阵的相应位置的值(值由0转变为1),并用专门的数据记录下该作业占用的物理块的块号,以备删除作业时回收空间。
    3. 作业空间的的回收:用户输入作业号,实现分区回收。(通过相应的数据结构找到该作业占有的物理块号,将块号转变成对应的行标、列标,将对应位置的值由1转变成0就完成了回收)
    4. 分区的显示:任何时刻,可以查看当前内存的情况。(显示记录内存情况的矩阵的值)
    5. 要求考虑:(1)内存空间不足的情况,要有相应的显示;

          (2)作业不能同名,但是删除后可以再用这个名字;

          (3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有相应的提示。

    三、实验代码

    ①创建表示作业的结构体

    typedef struct Ln

    {

        int f;        //作业号

        int n;        //作业页数

        int len;      //作业大小

        char name[8]; //作业名

        int y[100];   //页表,下标表示页号,内容表示作业各页所在物理块

        struct Ln *next;

    Ln, *List;

    ②编写建立作业的函数

    //建立新作业

    void Create_Pagi(List &L)

    {

        int iflag;

        int mk;

        List p;

        List n_node;

        n_node = (List)malloc(sizeof(Ln));

        p = L;

        printf(亲,请输入作业号 :");

        scanf("%d", &n_node->f);      //输入作业号

        flag = 0;                     //三次输入错误返回上一层

        while (p != NULL && flag < 3// 查找作业号是否重复

        {

            if (p->f != n_node->f)

                p = p->next;

            else

            {

                printf("\n 亲,该作业已存在您忘记了吗 , 请重新输入 :");

                scanf("%d", &n_node->f);

                p = L; //p 重新指向头结点

                flag++;

            }

        }

        if (flag < 3)

        {

            printf(输入作业名称 :");

            scanf("%s"n_node->name);

            printf(输入作业的大小 (单位为K):");

            scanf("%d", &n_node->len); //例如1025,作业页数为1,但K不为0,所以+1=2

            n_node->n = n_node->len / 1024;

            k = n_node->len % 1024;

            if (k != 0)

                n_node->n = n_node->n + 1;

            printf(所需要的页数为 :");

            printf("%d\n"n_node->n);

            printf(偏移量为%d"k);

            if (n_node->n > num//放不进去,失败

            {

                printf("\n 对不起亲,内存物理块不足,新建作业失败 \n\n");

            }

            else

            {

                num -= n_node->n//更新剩余物理块

                m = 0;

                for (i = 0i <= maxi++)

                    if (S[i] == 0 && m < n_node->n//

                    {

                        S[i] = n_node->f//作业号

                        n_node->y[m] = i//页表,下标表示页号,内容表示作业各页所在物理块

                        m++;

                    }

                printf("\n");

                printf(页号\t\t块号\n");

                for (int i = 0i < mi++)

                    printf(" %d\t\t%d\n"in_node->y[i]);

                int ab;

                while (1)

                {

                    printf(请输入页号\n");

                    scanf("%d", &a);

                    printf(请输入页内偏移\n");

                    scanf("%d", &b);

                    if (a < m)

                    {

                        printf(物理地址:%d\n"n_node->y[a] * 1024 + b);

                        break;

                    }

                    else

                    {

                        printf(越界\n");

                        continue;

                    }

                }

                if (L == NULL)

                    L = n_node;

                else

                {

                    p = L; // 查找最后一个节点

                    while (p->next != NULL)

                    {

                        p = p->next;

                    }

                    p->next = n_node;

                }

                n_node->next = NULL;

            }

        }

        else

        {

            printf("\n 亲操作错误次数过多 , 已为您返回主菜单 :");

        }

    }

    ③编写回收作业、释放内存的函数

    //回收作业、释放内存

    void Revoke_Pagi(List &L)

    {

        List pq;

        int x;

        printf(请输入要删除的作业号 :");

        scanf("%d", &x);

        p = L; //查找作业;用 p 记录

        q = p;

        while (p != NULL)

        {

            if (p->f == x//作业号

            {

                printf(亲,该作业已为您删除^o^ ");

                break;

            }

            else

            {

                q = p;

                p = p->next;

            }

        }

        if (p == NULL//p为空说明不存在此作业

        {

            printf("\n 亲,该作业不存在呢^o^\n");

        }

        else //对该作业进行删除

        {

            for (int i = 0i < p->ni++)

                S[p->y[i]] = 0//内存物理块

            num += p->n;

            if (p->f == q->f//要删除的是头结点

            {

                L = p->next;

            }

            else

            {

                q->next = p->next;

            }

        }

    }

    ④编写显示所有作业占用物理块的函数

    //显示所有作业占用的物理块

    void Printf_Pagi(List L)

    {

        //int i = 0;

        printf("\n 内存物理块分配情况 :\n");

        List p = L;

        printf(该作业信息 :\n");

        printf(作业号 \t 作业名称 \t 作业页数 \t 所用物理块 \n");

        while (p != NULL)

        {

            printf(" %d\t\t"p->f);

            printf(" %s\t\t"p->name);

            printf(" %d\t\t"p->n);

            int i;

            for (i = 0i < p->ni++)

                printf(" %d"p->y[i]);

            printf("\n");

            p = p->next;

        }

    }

    ⑤编写查看作业情况的函数

    //查看作业

    void Look_Pagi(List L)

    {

        int z;

        printf(亲,请输入要查询的作业号: ");

        scanf("%d", &z); //输入查看的作业号

        List p = L;

        while (p != NULL)

        {

            if (p->f == z//相同直接输出

            {

                printf(作业号 \t 作业名称 \t 作业页数 \t 所用物理块 \n");

                printf(" %d\t\t"p->f);

                printf(" %s\t\t"p->name);

                printf(" %d\t\t"p->n);

                int i;

                for (i = 0i < p->ni++)

                    printf(" #%d"p->y[i]);

                printf("\n");

                break;

            }

            else

                p = p->next;

        }

        if (p == NULL)

            printf(要查询的作业不存在 \n");

    }

    ⑥编写显示内存块使用情况的函数

    //显示内存块使用情况

    void Show_Pagi()

    {

        printf(内存物理块分配情况 \n");

        for (int i = 0i <= maxi++)

        {

            printf(" %d\t"S[i]);

            if (i % 10 == 9)

                printf("\n");

        }

    }

    实验代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    #include <bits/stdc++.h>
    
    typedef struct Ln
    {
        int f;        //作业号
        int n;        //作业页数
        int len;      //作业大小
        char name[8]; //作业名
        int y[100];   //页表,下标表示页号,内容表示作业各页所在物理块
        struct Ln *next;
    } Ln, *List;
    
    int S[100];    //内存物理块,0:未使用,非0:已使用
    int max = 99;  //记录内存的物理块数,值为A[100]最大下标
    int num = 100; //记录内存未使用物理块数
    
    void Create_Pagi(); //建立分页作业
    void Revoke_Pagi(); //回收作业
    void Look_Pagi();   //显示所有作业占用的物理块
    void Show_Pagi();   // 查看作业
    void Pagi();        //分页界面
    
    void Create_Segm(); //创建分段作业
    void Show_Segm();   //显示作业信息
    void Suggest();     //建议模块
    void Dispatch();    //调用模块
    void Segme();       //分段界面
    void main_s();      //主界面
    
    //建立新作业
    void Create_Pagi(List &L)
    {
        int i, flag;
        int m, k;
        List p;
        List n_node;
        n_node = (List)malloc(sizeof(Ln));
        p = L;
        printf(" 亲,请输入作业号 :");
        scanf("%d", &n_node->f);      //输入作业号
        flag = 0;                     //三次输入错误返回上一层
        while (p != NULL && flag < 3) // 查找作业号是否重复
        {
            if (p->f != n_node->f)
                p = p->next;
            else
            {
                printf("\n 亲,该作业已存在您忘记了吗 , 请重新输入 :");
                scanf("%d", &n_node->f);
                p = L; //p 重新指向头结点
                flag++;
            }
        }
        if (flag < 3)
        {
            printf(" 输入作业名称 :");
            scanf("%s", n_node->name);
            printf(" 输入作业的大小 (单位为K):");
            scanf("%d", &n_node->len); //例如1025,作业页数为1,但K不为0,所以+1=2;
            n_node->n = n_node->len / 1024;
            k = n_node->len % 1024;
            if (k != 0)
                n_node->n = n_node->n + 1;
            printf(" 所需要的页数为 :");
            printf("%d\n", n_node->n);
            printf(" 偏移量为%d", k);
            if (n_node->n > num) //放不进去,失败
            {
                printf("\n 对不起亲,内存物理块不足,新建作业失败 \n\n");
            }
            else
            {
                num -= n_node->n; //更新剩余物理块
                m = 0;
                for (i = 0; i <= max; i++)
                    if (S[i] == 0 && m < n_node->n) //
                    {
                        S[i] = n_node->f; //作业号
                        n_node->y[m] = i; //页表,下标表示页号,内容表示作业各页所在物理块
                        m++;
                    }
                printf("\n");
                printf(" 页号\t\t块号\n");
                for (int i = 0; i < m; i++)
                    printf(" %d\t\t%d\n", i, n_node->y[i]);
                int a, b;
                while (1)
                {
                    printf(" 请输入页号\n");
                    scanf("%d", &a);
                    printf(" 请输入页内偏移\n");
                    scanf("%d", &b);
                    if (a < m)
                    {
                        printf(" 物理地址:%d\n", n_node->y[a] * 1024 + b);
                        break;
                    }
                    else
                    {
                        printf(" 越界\n");
                        continue;
                    }
                }
                if (L == NULL)
                    L = n_node;
                else
                {
                    p = L; // 查找最后一个节点
                    while (p->next != NULL)
                    {
                        p = p->next;
                    }
                    p->next = n_node;
                }
                n_node->next = NULL;
            }
        }
        else
        {
            printf("\n 亲操作错误次数过多 , 已为您返回主菜单 :");
        }
    }
    
    //回收作业、释放内存
    void Revoke_Pagi(List &L)
    {
        List p, q;
        int x;
        printf(" 请输入要删除的作业号 :");
        scanf("%d", &x);
        p = L; //查找作业;用 p 记录
        q = p;
        while (p != NULL)
        {
            if (p->f == x) //作业号
            {
                printf(" 亲,该作业已为您删除^o^ ");
                break;
            }
            else
            {
                q = p;
                p = p->next;
            }
        }
        if (p == NULL) //p为空说明不存在此作业
        {
            printf("\n 亲,该作业不存在呢^o^\n");
        }
        else //对该作业进行删除
        {
            for (int i = 0; i < p->n; i++)
                S[p->y[i]] = 0; //内存物理块
            num += p->n;
            if (p->f == q->f) //要删除的是头结点
            {
                L = p->next;
            }
            else
            {
                q->next = p->next;
            }
        }
    }
    
    // 显示所有作业占用的物理块
    void Printf_Pagi(List L)
    {
        //int i = 0;
        printf("\n 内存物理块分配情况 :\n");
        List p = L;
        printf(" 该作业信息 :\n");
        printf(" 作业号 \t 作业名称 \t 作业页数 \t 所用物理块 \n");
        while (p != NULL)
        {
            printf(" %d\t\t", p->f);
            printf(" %s\t\t", p->name);
            printf(" %d\t\t", p->n);
            int i;
            for (i = 0; i < p->n; i++)
                printf(" %d", p->y[i]);
            printf("\n");
            p = p->next;
        }
    }
    
    // 查看作业
    void Look_Pagi(List L)
    {
        int z;
        printf(" 亲,请输入要查询的作业号: ");
        scanf("%d", &z); //输入查看的作业号
        List p = L;
        while (p != NULL)
        {
            if (p->f == z) //相同直接输出
            {
                printf(" 作业号 \t 作业名称 \t 作业页数 \t 所用物理块 \n");
                printf(" %d\t\t", p->f);
                printf(" %s\t\t", p->name);
                printf(" %d\t\t", p->n);
                int i;
                for (i = 0; i < p->n; i++)
                    printf(" #%d", p->y[i]);
                printf("\n");
                break;
            }
            else
                p = p->next;
        }
        if (p == NULL)
            printf(" 要查询的作业不存在 \n");
    }
    
    // 显示内存块使用情况,不分作业
    void Show_Pagi()
    {
        printf(" 内存物理块分配情况 \n");
        for (int i = 0; i <= max; i++)
        {
            printf(" %d\t", S[i]);
            if (i % 10 == 9)
                printf("\n");
        }
    }
    
    //以上分页代码
    /*------------------------------------------------------------------*/
    //以下分段代码
    
    using namespace std;
    
    struct seg //定义结构体段seg
    {
        long cap; //该段的长度
        long phy; //物理地址
        long rea; //该段实际地址
    };
    
    struct Table //定义结构体段表Table
    {
        seg s[10];     //段表中每个段的属性
        char name[50]; //段表名
        int flag;      //标记是否被调度内存
        int num;       //作业中包含段数
        long total;    //作业所占用的存储空间
    };
    
    Table Ts[10];
    long mem = 0;
    int Tnum = 0;
    long k = 0;
    long base = 0;
    
    //创建分段作业
    void Create_Segm()
    {
        printf("\n");
        printf("请输入要创建的作业名:");
        cin >> Ts[Tnum + 1].name;
        printf("请输入该作业的段数:");
        cin >> Ts[Tnum + 1].num;
        int p = 0;
        for (int i = 1; i <= Ts[Tnum + 1].num; i++)
        {
            printf("请输入该作业第%d段的大小:", i);
            cin >> Ts[Tnum + 1].s[i].cap;  //该作业每段的大小
            Ts[Tnum + 1].s[i].phy = p;     //物理地址赋值给p
            p = p + Ts[Tnum + 1].s[i].cap; //每段的物理地址赋值给加和
        }
        printf("\n");
        Ts[Tnum + 1].flag = 0; //标记是否被调度
        Ts[Tnum + 1].total = p;
        Tnum++;
    }
    
    //显示作业信息
    void Show_Segm(int i)
    {
        printf("\n作业p%d:", i);
        cout << "名字:" << Ts[i].name << endl;
        cout << "该作业所占用的存储空间:" << Ts[i].total << endl;
        if (Ts[i].flag == 0)
            cout << "作业未调用" << endl;
        else
            cout << "作业已调用" << endl;
        cout << "段 号    物理始址    内存始址    长度" << endl;
        for (int j = 1; j <= Ts[i].num; j++)
        {
            cout << setw(3) << j << setw(11) << Ts[i].s[j].phy;
            if (Ts[i].flag == 0)
                cout << setw(11) << " ";
            else
                cout << setw(11) << Ts[i].s[j].rea;
            cout << setw(11) << Ts[i].s[j].cap << endl;
        }
    }
    
    //调用作业
    void Dispatch()
    {
        cout << endl;
        cout << "输入要调度的作业:p";
        int n;
        cin >> n;
        if (n <= 0 || n > Tnum) //排除非正常可能
        {
            cout << "请求的段表不存在!" << endl;
            cout << "请重新";
            Dispatch(); //重新调度
        }
        else if (Ts[n].flag == 1) //已经标记
            cout << "操作失败,该作业已经被调入到内存!" << endl;
        else if (Ts[n].total > mem - k) //存储不足
            cout << "内存空间不足,无法调度!" << endl;
        else
        {
            for (int j = 1; j <= Ts[n].num; j++)
            {
                Ts[n].s[j].rea = Ts[n].s[j].phy + k; //
            }
            k = k + Ts[n].total;
            Ts[n].flag = 1; //标记被访问
            cout << "调度后的结果是:" << endl;
            Show_Segm(n);
        }
    }
    
    //建议模块
    void Suggest()
    {
        printf(" 亲,请输入您宝贵的建议:");
        char s[10000];
        scanf("%s", s);
        printf(" *感谢您的宝贵建议,我们10分钟之内会受理您的建议* \n");
        printf(" *感谢您的本次使用,退出程序请输入【0】,返回主界面输入【1】: ");
        char m;
        cin >> m;
        do
            if (m - '0' == 0)
                exit(0);
            else if (m - '1' == 1)
                main_s();
            else
            {
                printf(" 对不起,输入有误,默认返回主界面呢\n\n");
                main_s();
            }
        while (m != 0);
    }
    
    //分页
    void Pagi()
    {
        memset(S, 0, sizeof(S)); //初始化A
        List L = NULL;
        int i = 0;
        do
        {
            printf("\t\t 欢迎使用基本分页存储管理系统 \n");
            printf("\t\t******************************\n");
            printf("\t\t* 1. 添加作业 *\n");
            printf("\t\t* 2. 回收作业 *\n");
            printf("\t\t* 3. 内存占用情况 *\n");
            printf("\t\t* 4. 查看作业 *\n");
            printf("\t\t* 5. 提出宝贵建议 *\n");
            printf("\t\t* 6. 返回主界面 *\n");
            printf("\t\t* 0. 退出程序 *\n");
            printf("\t\t******************************\n");
            printf(" 请输入您的选择 :");
            scanf("%d", &i);
            switch (i)
            {
            case 1:
                Create_Pagi(L);
                //Printf_Pagi(L);
                break;
            case 2:
                Revoke_Pagi(L);
                Printf_Pagi(L);
                break;
            case 3:
                Show_Pagi();
                break;
            case 4:
                Look_Pagi(L);
                break;
            case 5:
                Suggest();
                break;
            case 6:
                main_s();
                break;
            case 0:
                printf(" 感谢您的使用,祝您生活愉快!");
                exit(0);
            }
        } while (i != 0);
    }
    
    //分段
    void Segme()
    {
        int i;
        printf(" 请输入内存的大小:");
        int m;
        scanf("%d", &m);
        do
        {
            printf("\t\t 欢迎使用基本分段存储管理系统 \n");
            printf("\t\t******************************\n");
            printf("\t\t* 1. 创建作业 *\n");
            printf("\t\t* 2. 显示作业信息 *\n");
            printf("\t\t* 3. 调度作业   *\n");
            printf("\t\t* 4. 提出宝贵建议 *\n");
            printf("\t\t* 5. 返回主界面 *\n");
            printf("\t\t* 0. 退出程序 *\n");
            printf("\t\t******************************\n");
            printf(" 请输入您的选择 :");
            scanf("%d", &i);
            switch (i)
            {
            case 1:
                Create_Segm();
                break;
            case 2:
                for (int j = 1; j < Tnum + 1; j++)
                    Show_Segm(j);
                break;
            case 3:
                if (i == 3) //如果输入是3则调度一个作业
                    Dispatch();
                else
                    cout << " 输入错误!请重新输入!" << endl;
                break;
            case 4:
                Suggest();
                break;
            case 5:
                main_s();
                break;
            case 0:
                printf(" 感谢您的使用,祝您生活愉快!");
                exit(0);
            }
        } while (i != 0);
    }
    
    //主界面
    void main_s()
    {
        printf("\t\t 欢迎来到内存管理系统 \n");
        printf("\t\t**********************\n");
        printf("\t\t* 1.进入分页管理系统 *\n");
        printf("\t\t* 2.进入分段管理系统 *\n");
        printf("\t\t* 3.我要提出宝贵建议 *\n");
        printf("\t\t* 0.退出程序  *\n");
        int m;
        printf(" 亲,请输入您的选择 :");
        scanf("%d", &m);
        do
            if (m >= 0 && m <= 3)
            {
                switch (m)
                {
                case 1:
                    Pagi(); //分页
                    break;
                case 2:
                    Segme(); //分段
                    break;
                case 3:
                    Suggest();
                    break;
                case 0:
                    exit(0);
                }
            }
            else
            {
                printf(" 输入有误!请重新输入:");
                scanf("%d", &m);
            }
        while (m != 0);
    }
    
    int main()
    {
        system("color 3f"); //颜色
        main_s();
        return 0;
    }

    四、实验结果

     

    五、实验总结

    此次试验,收获甚多,使用代码实现了基本分页存储管理。基本分页存储管理的思想是把进程分页,各个页面可离散地放到各个的内存块中。实验中涉及到了连续分配与非连续分配的概念,连续分配:为用户进程分配的必须是一个连续的内存空间;非连续分配:为用户进程分配的可以是一些分散的内存空间。

    将内存空间分为一个个大小相等的分区,每个分区就是一个“页框”(页框=页帧=内存块=物理块=物理页面)。每个页框有一个编号,即“页框号”(页框号=页帧号=内存块号=物理块号=物理页号),页框号从0开始。将进程的逻辑地址空间也分为与页框大小相等的一个个部分, 每个部分称为一个“页”或“页面” 。每个页面也有一个编号, 即“页号”,页号也是从0开始。

    操作系统以页框为单位为各个进程分配内存空间。进程的每个页面分别放入一个页框中。也就是说,进程的页面与内存的页框有一一对应的关系。各个页面不必连续存放,可以放到不相邻的各个页框中。进程的最后一个页面可能没有一个页框那么大。即,分页存储有可能产生内部碎片,因此页框不能太大,否则可能产生过大的内部碎片造成浪费。

    实验中,还有很多不熟练的地方,课下我会好好努力,多加练习。

    展开全文
  • 实验通过程序模拟操作系统的基本分页存储管理方式,进一步理解这一内存分配方式的原理和特点,加深对理论知识的掌握。
  • 存储器管理 1实验内容模拟请求页式存储管理中硬件的地址转换和缺页中断并用先进先出调度算法FIFO处理缺页中断 2要求 指令序列的设定可以执行拟定格式如表3 在完成了FIFO换页策略后可以选做LRU的换页策略并进行比较 ...
  • 基本分页存储管理一、实验内容及要求二、实验环境三、设计思想四、数据结构五、实验代码六、运行结果 一、实验内容及要求 模拟分页存储管理方式; 模拟分页存储管理方式,定义地址变换机构函数; 程序要添加适当的...

    注:其他实验见:点击查看

    一、实验内容及要求

    1. 模拟分页存储管理方式;
    2. 模拟分页存储管理方式,定义地址变换机构函数;
    3. 程序要添加适当的注释,程序的书写要采用缩进格式;
    4. 程序要具在一定的健壮性,即当输入数据非法时,程序也能适当地做出反应;
    5. 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

    二、实验环境

    windows 10,Visual Studio 2019

    三、设计思想

    1. 设内存大小为2GB,页面大小为4KB。
    2. 建立进程:由用户输入进程ID与大小,随机数分配各个页面对应的物理块号;
    3. 地址变换(十进制):
      [1] 由用户输入一个十进制的逻辑地址A;
      [2] 则页号为P=INT[A/L],页内地址为d=[A] MOD L,L为页面大小(4096);
      [3] 查询页表,找到页号对应的物理块号B,计算物理地址B×L+d。
    4. 地址变换(二进制):
      [1] 由用户输入一个二进制的逻辑地址A;
      [2] 设页内地址的位数为x,则页号为A>>x,页内地址为A的低x位;
      [3] 查询页表,找到页号对应的物理块号,计算物理地址将物理块号与页内地址拼接即可。

    四、数据结构

    1. 定义一个pcb类,表示每一个进程,含有进程的编号、大小、页表等信息:
    class PCB {
    public:
    	PCB(int a, int b) :id(a), size(b) {};
    private:
    	int id;                   //进程编号
    	int size;                 //进程大小
    	int length;               //页表长度
    	vector<int> page_table;   //页表
    public:
    	void init(vector<int> &s);       //给每页分配相应的物理块号
    	void disp();                     //显示页表信息
    	int comp(int a,int b);           //越界检查
    	int comp(bitset<31> a, int b);   //越界检查
    	int trans(int a);                //查询页表
    	int trans(bitset<31> a);         //查询页表
    };
    
    1. 对于二进制的处理,使用bitset<31>结构来进行相关的逻辑移位、按位与或运算、转换成十进制等。

    五、实验代码

    #include<vector>
    #include<bitset>
    #include<ctime>
    #include<random>
    #include<cmath>
    #include<iostream>
    #include<string>
    
    using namespace std;
    
    class PCB {
    public:
    	PCB(int a, int b) :id(a), size(b) {};
    private:
    	int id;                   //进程编号
    	int size;                 //进程大小
    	int length;               //页表长度
    	vector<int> page_table;   //页表
    public:
    	void init(vector<int> &s);       //给每页分配相应的物理块号
    	void disp();                     //显示页表信息
    	int comp(int a,int b);           //越界检查
    	int comp(bitset<31> a, int b);   //越界检查
    	int trans(int a);                //查询页表
    	int trans(bitset<31> a);         //查询页表
    };
    
    //给每页分配相应的物理块号
    void PCB::init(vector<int> &s) {
    	int num,a,flag=1;
    	num = size / 4;
    	if (size % 4 != 0) {
    		num++;
    	}
    	static uniform_int_distribution<int> u(0, int(pow(2,19)));
    	static default_random_engine e(time(0));
    	while(page_table.size()!=num) {
    		a = u(e);
    		for (auto j = s.begin(); j != s.end(); j++) {    //检查物理块是否被占用
    			if (*j == a) {
    				flag = 0;
    				break;
    			}
    		}
    		if (flag) {
    			page_table.push_back(a);
    			s.push_back(a);
    		}
    	}
    	length = page_table.size();
    }
    
    //显示页表信息
    void PCB::disp() {
    	int no=0;
    	auto i = page_table.begin();
    	while (i != page_table.end()) {
    		cout << no << "\t" << *i << endl;
    		no++;
    		i++;
    	} 
    }
    
    //越界检查
    int PCB::comp(int a,int b) {
    	if (id!=b)
    		return 1;
    	else if (a > length|| a < 0)
    		return 2;
    	else
    		return 0;
    }
    
    //越界检查
    int PCB::comp(bitset<31> a, int b) {
    	if (id != b)
    		return 1;
    	else if (a.to_ulong() > length - 1 || a.to_ulong() < 0)
    		return 2;
    	else
    		return 0;
    }
    
    //查询页表
    int PCB::trans(int a) {
    	auto p = page_table.begin();
    	for (int i = 0; i < a; i++) {
    		p++;
    	}
    	return *p;
    }
    
    //查询页表
    int PCB::trans(bitset<31> a) {
    	auto p = page_table.begin();
    	for (int i = 0; i < int(a.to_ulong()); i++) {
    		p++;
    	}
    	return *p;
    }
    
    //内存大小2GB,页面大小4KB
    //创建进程
    bool create(vector<PCB>& pcbs, vector<int>& s) {
    	unsigned pid,psize;
    	cout << "请输入进程编号与大小(KB):";
    	cin >> pid >> psize;
    	if (psize > (524288 - s.size()) * 4) {
    		return 1;
    	}
    	pcbs.push_back(PCB(pid, psize));
    	auto p = pcbs.end();
    	p--;
    	p->init(s);
    	return 0;
    }
    
    //显示页表
    void display(vector<PCB> pcbs) {
    	int num=1;
    	for (auto i = pcbs.begin(); i != pcbs.end(); i++) {
    		cout << "第" << num << "个进程:" << endl;
    		cout << "页号\t" << "块号" << endl;
    		i->disp();
    		num++;
    	}
    }
    
    //地址转换机构1
    bool addr_trans(vector<PCB> pcbs) {
    	int no,addr;
    	int chunk_no,offset;
    	auto p = pcbs.begin();
    	cout << "输入转换的进程编号:";
    	cin >> no;
    	cout << "输入十进制地址:";
    	cin >> addr;
    	chunk_no = addr / 4096;
    	//找到进程并进行越界检查
    	while (p!=pcbs.end()&&p->comp(chunk_no, no)) {
    		if (p->comp(chunk_no, no) == 1)
    			p++;
    		else if (p->comp(chunk_no, no) == 2) {
    			cout << "地址越界,重新输入十进制地址:";
    			cin >> addr;
    			chunk_no = addr / 4096;
    		}	
    	}
    	if (p == pcbs.end()) {
    		cout << "未找到该进程!";
    		return 1;
    	}
    	offset = addr % 4096;
    	cout << "对应的物理地址为:" << p->trans(chunk_no)*int(pow(2,12.0)) + offset << endl;
    	return 0;
    }
    
    //地址变换机构2
    bool addr_trans2(vector<PCB> pcbs) {
    	bitset<31> addr,chunk_no, offset, s(string("0000000000000000000111111111111"));
    	bitset<31> p_addr;
    	int no;
    	auto p = pcbs.begin();
    	cout << "输入转换的进程编号:";
    	cin >> no;
    	cout << "输入二进制地址:";
    	cin >> addr;
    	chunk_no = addr >> 12;
    	//找到进程并进行越界检查
    	while (p != pcbs.end()&&p->comp(chunk_no, no)) {
    		if (p->comp(chunk_no, no) == 1)
    			p++;
    		else if (p->comp(chunk_no, no) == 2) {
    			cout << "地址越界,重新输入十进制地址:";
    			cin >> addr;
    			chunk_no = addr >> 12;
    		}
    	}
    	if (p == pcbs.end()) {
    		cout << "未找到该进程!";
    		return 1;
    	}
    	offset = addr & s;
    	p_addr = p->trans(chunk_no);
    	p_addr = p_addr << 12;
    	p_addr = p_addr | offset;
    	cout << "对应的二进制物理地址为:" << p_addr 
    		<< "\n转化为十进制为:" << p_addr.to_ulong()
    		<< endl;
    	return 0;
    }
    
    int main() {
    	int choose = 0;
    	vector<PCB> pcbs;
    	vector<int> s;   //记录占用的物理块号
    	cout << "1.创建进程\n"
    		<< "2.显示进程页表\n"
    		<< "3.逻辑地址转换(十进制)\n"
    		<< "4.逻辑地址转换(二进制)\n"
    		<< "5.退出" << endl;
    	while (choose != 5) {
    		cout << "\n请选择:" ;
    		cin >> choose;
    		switch (choose) {
    		case 1:
    			if (create(pcbs,s))
    				cout << "创建失败!" << endl;
    			else
    				cout << "创建成功!" << endl;
    			break;
    		case 2:
    			display(pcbs);
    			break;
    		case 3:
    			if (addr_trans(pcbs)) {
    				cout << "转换失败!" << endl;
    			};
    			break;
    		case 4:
    			if (addr_trans2(pcbs)) {
    				cout << "转换失败!" << endl;
    			};
    			break;
    		default:
    			break;
    		}
    	}
    	return 0;
    }
    
    

    六、运行结果

    运行结果

    展开全文
  • 操作系统实验基本分页存储管理

    千次阅读 2020-05-21 19:06:57
    目的:熟悉并掌握基本分页存储管理的思想及其实现方法,熟悉并掌握基本分页存储管理的分配和回收方式。 任务:模拟实现基本分页存储管理方式下内存空间的分配和回收。 二、内容、要求与安排 1、实验内容 内存空间的...

    不要抄!好好写!
    在这里插入图片描述
    一、目的与任务
    目的:熟悉并掌握基本分页存储管理的思想及其实现方法,熟悉并掌握基本分页存储管理的分配和回收方式。
    任务:模拟实现基本分页存储管理方式下内存空间的分配和回收。

    二、内容、要求与安排
    1、实验内容
    内存空间的初始化——可以由用户输入初始内存空间各个物理块情况。(用二维矩阵的方式按物理块号,逐行给出每个物理块的状态,1——表示已分配,0——表示未分配,并能够将行标、列标转换为对应的物理块号,以查看或修改每一个块的状态,要求:初始时部分物理块已分配)
    基本分页的分配过程:由用户输入作业号和作业的大小(这里的大小是逻辑页面数),实现分配过程:空间充足,分配,修改状态矩阵的相应位置的值(值由0转变为1),并用专门的数据记录下该作业占用的物理块的块号,以备删除作业时回收空间。
    作业空间的回收:用户输入作业号,实现分区回收(通过相应的数据结构找到该作业占有的物理块号,将块号转变成对应的行标、列标,将对应位置的值由1转变成0就完成了回收)。
    分区的显示:任何时刻,可以查看当前内存的情况(显示记录内存情况的矩阵的值)。
    2、实验要求
    (1)内存空间不足的情况,要有相应的显示;
    (2)作业不能同名,但是删除后可以再用这个名字;
    (3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有相应的提示。

    三、实验代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int Row = 10;//行
    const int Column = 20;//列
    int Remain = Row * Column;//剩余物理块数
    int Blocks[Row][Column];//物理块
    map<int, queue<int> > biao;//key是作业号,value是队列用来存这个作业存放在那个物理块,模拟了一个页表
    
    void in_it();
    void m_malloc();
    void m_free();
    void show();
    void solve();
    int menu();
    
    int main()
    {
        in_it();
        solve();
    }
    
    void in_it()
    {
        memset(Blocks, 0, sizeof(Blocks));
        int flag;
        printf("手动选择物理块占用输入1,程序随机选择输入2:");
        scanf("%d", &flag);
        if(flag == 1)
        {
            for(int i=0; i<Row; i++)
                for(int j=0; j<Column; j++)
                    scanf("%d", &Blocks[i][j]);
        }
        else
        {
            srand(time(NULL));
            for(int i=0; i<Row; i++)
                for(int j=0; j<Column; j++)
                    rand() % 2 == 1 ? Blocks[i][j]=1,Remain-- : Blocks[i][j]=0;
            for(int i=0; i<Row; i++)
                for(int j=0; j<Column; j++)
                    printf("%d%c", Blocks[i][j], j == Column-1 ? '\n' : ' ');
        }
    }
    void m_malloc()
    {
        int id, si;
        printf("输入作业ID和大小:");
        while(scanf("%d%d", &id, &si), biao.find(id) != biao.end())
            printf("!!!ID重复,请重新输入作业ID和大小:");
        if(Remain < si)
            printf("!!!内存已满\n");
        else
        {
            for(int i=0; i<Row&&si!=0; i++)//从头遍历,放满si个就退出
            {
                for(int j=0; j<Column&&si!=0; j++)
                {
                    if(!Blocks[i][j])
                    {
                        si--;
                        Blocks[i][j] = 1;
                        biao[id].push(i * Column + j);
                        Remain--;
                    }
                }
            }
            printf("分配成功\n");
        }
    }
    void m_free()
    {
        int id;
        printf("输入作业ID:");
        while(scanf("%d", &id), biao.find(id) == biao.end())
            printf("!!!ID缺失,请重新输入作业ID:");
        while(!biao[id].empty())
        {
            int top = biao[id].front();
            Blocks[top/Column][top%Column] = 0;
            biao[id].pop();
            Remain++;
        }
        biao.erase(id);
        printf("释放成功\n");
    }
    void show()
    {
        printf("内存块使用情况\n");
        for(int i=0; i<Row; i++)
            for(int j=0; j<Column; j++)
                printf("%d%c", Blocks[i][j], j == Column-1 ? '\n' : ' ');
    }
    void solve()
    {
        int flag;
        while( (flag = menu()) )
        {
            switch(flag)
            {
            case 1:
                m_malloc();
                break;
            case 2:
                m_free();
                break;
            case 3:
                show();
                break;
            case -1:
                printf("!!!数据非法,重新输入:");
                break;
            }
        }
    }
    
    int menu()
    {
        printf("--------------------\n");
        printf("Create:1\n");
        printf("Free:2\n");
        printf("View Info:3\n");
        printf("Over Input:0\n");
        printf("Plase Input A Num:");
        int m;
        scanf("%d",&m);
        switch(m)
        {
        case 0:
        case 1:
        case 2:
        case 3:
            return m;
            break;
        default:
            return -1;
        }
    
        return m;
    }
    
    展开全文
  • 生产过程管理程序 版本 修订 变更内容 制订 审核 核准 日期 次数 页次 章节 A 第一次发行
  • 计操实验 分页存储管理 C语言 需求: 假定页面大小为4K,物理内存128M,设计并实现一个内存分配和回收的程序,使用C语言或Python语言编写程序实现这个程序并进行测试。 (1)至少5个进程; (2)要求有空块管理; ...
  • 操作系统实验——分页存储管理

    千次阅读 2021-10-11 18:33:37
    掌握请求式分页存储管理基本原理,并在试验过程中体会内存与置换空间的分配与回收、地址转换以及缺页处理过程。 2.2内容 2.3数据结构 2.4算法设计及流程图 2.5 运行截图 2.6 小结 ...
  • 三、实验内容 (1) 通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成: 1. 50%的指令是顺序执行的; 2. 25%的指令是均匀分布在前地址部分; 3. 25%的指令是均匀分布在后地址部分; 具体的实施...
  • 通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法。通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。
  • 题目:1。存储管理 描述请求分页存储管理。 一. 产生一个作业及作业页面序列P(pi),例如:P(0,2,3,4,1,5,2,3,0,4,1,5)。 二.分配物理内存块数M。 三.采用FIFO,LRU置换算法。
  • 分页存储管理实验报告,实验报告,包含源码,结果,很详细的,不错
  • 基本分页存储管理.docx
  • 实验六请求分页存储管理.docx实验六请求分页存储管理.docx实验六请求分页存储管理.docx实验六请求分页存储管理.docx实验六请求分页存储管理.docx实验六请求分页存储管理.docx实验六请求分页存储管理.docx实验六请求...
  • 实验目的:熟悉并掌握基本分页存储管理的思想。 熟悉并掌握基本分页存储管理的分配和回收方式,并能够模拟实现。 实验内容:用高级语言模拟实现基本分页存储管理,要求: 1、 内存空间的初始化——可以由用户输入...
  • 操作系统 存储管理实验报告

    万次阅读 多人点赞 2020-06-19 10:05:40
    实验的目的是通过请求页式管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。 二、实验内容 (1) 通过计算不同算法的命中率比较算法的优劣。同时也考虑了用户内存容量对...
  • 实验六请求分页存储管理 (2).pdf实验六请求分页存储管理 (2).pdf实验六请求分页存储管理 (2).pdf实验六请求分页存储管理 (2).pdf实验六请求分页存储管理 (2).pdf实验六请求分页存储管理 (2).pdf实验六请求分页存储...
  • 分页存储管理模拟

    2021-12-29 18:56:26
    操作系统实验 文章目录任务测试数据代码结构体1分配内存2回收作业3显示内存4内存访问完整代码 任务 • 初始化内存大小为100000字节 • 每个页框占1000个字节 • 则一共有100个页框(假设默认页框号为0-99号)。 • ...
  • 实验存储管理 一、目的和要求 1. 实验目的 (1)掌握时间片轮换的进程调度算法; (2)掌握带优先级的进程调度算法; (3)选用面向对象的编程方法。 2、实验学时:2学时 3、实验要求 (1)自定义PCB的...
  • 真正的模拟操作系统中 内存的分配 (分页存储管理)(操作系统模拟多进程内存分配) 连续的分配方式会形成许多碎片,虽然通过紧凑的方法将血多碎片拼接成可用的大块空间 但须付出很大的开销。如果允许将一个进程...
  • 通过实现一个操作系统的内存管理的模拟系统,观察内存空闲分区管理、内存分配和回收过程,了解内存管理技术等特点,掌握内存管理中的分配、回收和置换算法,加深对请求调页系统的原理和实现过程的理解。
  • 实验存储管理

    2018-07-03 20:05:59
    掌握分页存储管理基本原理及分页存储管理中的地址变换过程,编制一个模拟地址变换过程的程序并能采用先进先出页面置换算法实现页面置换。 二、实验内容 1、复习分页想念管理的基本概念、基本原理、及地址变换过程...
  • 真正的模拟操作系统中 内存的分配 (分页存储管理)(操作系统模拟多进程内存分配) 连续的分配方式会形成许多碎片,虽然通过紧凑的方法将血多碎片拼接成可用的大块空间 但须付出很大的开销。如果允许将一个进程...
  • 分页存储管理方式,将程序划分为若干个大小固定的区域(页),也把物理内存划分为大小和页相等的块,通过页表完成页到块的映射。 分页存储管理之C语言模拟: #include #include #include #define PAGE 20 int ...
  • 分页存储管理

    2011-12-14 14:11:43
    操作系统分页存储管理实验,C++程序源代码
  • c语言,运行成功,比较基础,模拟存储管理(页面调度),页面淘汰算法采用先进先出(FIFO)
  • 根据进程的要求按照段式存储管理方式模拟内存空间的分配与回收,并能够根据进程的空间分配情况完成地址映射。简单界面显示内存情况!供参考。
  • 基本分页存储管理6.1把“固定分区分配“改造为”非连续分配版本“6.2分页存储管理的基本管理6.3如何实现地址的转换?6.4逻辑地址结构6.5页表6.6总结 操作系统-3.3-内存 本文内容讲解动态分区分配算法和非连续分配...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,855
精华内容 2,742
关键字:

基本分页存储管理实验