• ucore lab2 物理内存管理 学习笔记


    总的来讲把的LAB1代码逻辑理顺后再往后学就轻松了一大截.LAB2过遍课程视频,再多翻翻实验指导书基本上就没遇到啥大坎儿.对这节学得东西做个总结就是一张图:

    练习0:填写已有实验

    本实验依赖实验1。请把你做的实验1的代码填入本实验中代码中有“LAB1”的注释相应部分。
    提示:可采用diff和patch工具进行半自动的合并(merge),也可用一些图形化的比较/merge
    工具来手动合并,比如meld,eclipse中的diff/merge工具,understand中的diff/merge工具
    等。

    我是用meld手动合并的.也就那几个填空的函数合一下

    文件结构分析

    bootasm.S:
    将内存分布状态存储到0x8000

    kernel.ld:
    把kernel入口函数设为了kern_entry

    entry.S:
    初始化页表
    建立物理内存0~4M到虚拟内存KERNBASE+0 ~ KERNBASE+4M的映射
    使能页机制
    长跳指令进入高内存地址
    设置内核栈
    调用init.c的kern_init

    init.c:
    无修改

    memlayout.h:
    增加KERNBASE等相关常量
    增加E820MAP结构体描述内存分布
    增加Pages结构体及相关的setter和getter宏

    mmu.h:
    增加线性地址相关的宏

    pmm.c&.h:
    增加了pmm_manager抽象类(运用结构体和函数指针实现)
    增加了
    增加物理地址与虚拟地址换算的宏
    pmm_init:
    设置CR3寄存器
    初始化pmm_manager
    初始化page
    检测分配的page
    检测PD
    把pgdir插入到pgdir自身中
    将物理地址映射到虚拟地址中
    LA: KERNBASE~KERNBASE+KMEMSIZE -> PA: 0 ~ KMEMSIZE
    初始化GDT

    init_pmm_manager:
    将default_pmm_manager设为当前PMM,并初始化

    init_page:
    根据E820MAP求出最大物理内存,总页数
    将page数组放到KERNEL末尾之后的内存区域
    (0----KERNEL----PAGE数组----自由内存区域---最大内存)
    将所有page设为保留状态
    对E820MAP里的所有内存块进行初始化内存映射(init_memmap)

    init_memmap
    调用PMM的init_memmap

    练习1:实现 first-fit 连续物理内存分配算法(需要编程)

    在实现first fit 内存分配算法的回收函数时,要考虑地址连续的空闲块之间的合并操作。提示:
    在建立空闲页块链表时,需要按照空闲页块起始地址来排序,形成一个有序的链表。可能会
    修改default_pmm.c中的default_init,default_init_memmap,default_alloc_pages,
    default_free_pages等相关函数。请仔细查看和理解default_pmm.c中的注释。

    就硬照着给的参考代码撸就行.撸完再改改BUG.

    default_pmm.c&.h:
    实现了一个默认的pmm_manager

    default_init:
    空闲块链表置空
    空闲块计数器归零

    default_init_memmap:
    将给定的page区域初始化,设置页状态(空闲头页,非保留)并放入空闲块链表

    default_alloc_pages:
    实现最先匹配法分配页,更新页状态(保留,非空闲头页),更新空闲块链表状态

    default_free_pages:
    释放页,并把相邻的空闲块合并,更新空闲块链表

    练习2:实现寻找虚拟地址对应的页表项(需要编程)

    通过设置页表和对应的页表项,可建立虚拟内存地址和物理内存地址的对应关系。其中的
    get_pte函数是设置页表项环节中的一个重要步骤。此函数找到一个虚地址对应的二级页表项
    的内核虚地址,如果此二级页表项不存在,则分配一个包含此项的二级页表。本练习需要补
    全get_pte函数 in kern/mm/pmm.c,实现其功能。请仔细查看和理解get_pte函数中的注释。

    牵扯到指向指针的指针,物理地址与线性地址选择.做的时候就很晕.引用BALDR SKY DRIVE里的一幕:

    //PDE,PTE本身存储的是物理地址和标志位
    //各类指针变量用的是线性地址
    pde_t *pdep=pgdir+PDX(la); //指针指向要访问的PDE
    if((*pdep)&PTE_P){ //当PDE存在,对应的二级页表也存在
    return ((pte_t*)KADDR((PDE_ADDR(*pdep))))+PTX(la);
    //返回PDE对应的PTE的指针
    //1.清空PDE末尾标志位,使其变成物理地址
    //2.物理地址转为线性地址
    //3.转化为指向pt头部的指针
    //4.指向目标pte
    }
    else{   
    if(!create){//页表不存在又不创建新页表,返回空
        return NULL;
    }
    struct Page *page=alloc_pages(1);//每个页表1024项,每项4B,刚好占一页
    if(page==NULL){//分配不成功
        return NULL;
    }
    page->ref=1;//引用一次
    uintptr_t pa=page2pa(page);//求出page的物理地址
    memset(KADDR(pa),0,PGSIZE);//把新建页表的内存区域清零
    (*pdep)=pa|PTE_P|PTE_W|PTE_U;//更新PDE的信息(物理内存和标志位)
    return ((pte_t*)KADDR((PDE_ADDR(*pdep))))+PTX(la);
    //返回PDE对应的PTE的指针
    }
    

    请描述页目录项(Page Directory Entry)和页表项(Page Table Entry)中每个组成部分的含义以及对ucore而言的潜在用处:
    这俩玩意都占32B,高24位为物理地址,低12位为标志位.具体含义直接看源码

    练习3:释放某虚地址所在的页并取消对应二级页表项的映射(需要编程)

    当释放一个包含某虚地址的物理内存页时,需要让对应此物理内存页的管理数据结构Page做
    相关的清除处理,使得此物理内存页成为空闲;另外还需把表示虚地址与物理地址对应关系
    的二级页表项清除。请仔细查看和理解page_remove_pte函数中的注释。为此,需要补全在
    kern/mm/pmm.c中的page_remove_pte函数。

    注释给的太全了,直接出代码就行

    数据结构Page的全局变量(其实是一个数组)的每一项与页表中的页目录项和页表项有
    无对应关系?如果有,其对应关系是啥?

    页目录项存着对应页表项的物理地址,页表项存着对应Page的物理地址

    疑问解答

    如何理解lab2的内存布局?

    /* *
     * Virtual memory map:                                          Permissions
     *                                                              kernel/user
     *
     *     4G ------------------> +---------------------------------+
     *                            |                                 |
     *                            |         Empty Memory (*)        |
     *                            |                                 |
     *                            +---------------------------------+ 0xFB000000
     *                            |   Cur. Page Table (Kern, RW)    | RW/-- PTSIZE
     *     VPT -----------------> +---------------------------------+ 0xFAC00000
     *                            |        Invalid Memory (*)       | --/--
     *     KERNTOP -------------> +---------------------------------+ 0xF8000000
     *                            |                                 |
     *                            |    Remapped Physical Memory     | RW/-- KMEMSIZE
     *                            |                                 |
     *     KERNBASE ------------> +---------------------------------+ 0xC0000000
     *                            |                                 |
     *                            |                                 |
     *                            |                                 |
     *                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * (*) Note: The kernel ensures that "Invalid Memory" is *never* mapped.
     *     "Empty Memory" is normally unmapped, but user programs may map pages
     *     there if desired.
     *
     * */
    

    初看不理解,读完代码再看就指导了.KERNBASE,KMEMSIZE等等这些数都是代码里规定好的常量,是人为规定的分布.

  • 相关阅读:
    mybatis 绑定 statement 失败
    JDBC链接Mysql失败
    Mysql 链接数据库时区错误
    mybatis 延迟加载
    C++ 虚函数表解析
    运行错误:error while loading shared libraries: xxx.so.0:cannot open shared object file: No such file or
    QComboBox的activated与currentIndexChanged的区别
    QT 文件对话框(QFileDialog)
    VS2010 ERROR:c1xx fatal error c1083
    django 在字符串[str(list)]中精确查找
  • 原文地址:https://www.cnblogs.com/kangyupl/p/12752872.html
Copyright © 2020-2023  润新知