zoukankan      html  css  js  c++  java
  • ucore lab3 虚拟内存管理 学习笔记

    做个总结,这节说是讲虚拟内存管理,大部分的时间都在搞SWAP机制和服务于此机制的一些个算法.难度又降了一截.
    不过现在我的电脑都16G内存了,能用完一半的情景都极少见了,可能到用到退休都不见得用的上SWAP机制了.在这种情况下SWAP分区也就象征性的分个几百兆了.

    vmm.c&.h

    vma:描述了一块连续的虚拟内存空间,保证start<=end

    struct vma_struct {
        struct mm_struct *vm_mm; // the set of vma using the same PDT 
        uintptr_t vm_start;      // start addr of vma      
        uintptr_t vm_end;        // end addr of vma, not include the vm_end itself
        uint32_t vm_flags;       // flags of vma
        list_entry_t list_link;  // linear list link which sorted by start addr of vma
    };
    

    mm:管理使用同一PDT的vma集合的结构体

    struct mm_struct {
        list_entry_t mmap_list;        // linear list link which sorted by start addr of vma,
        								//一直指向头部
        struct vma_struct *mmap_cache; // current accessed vma, used for speed purpose,
       								 //一直指向最后访问项
        pde_t *pgdir;                  // the PDT of these vma
        int map_count;                 // the count of these vma
        void *sm_priv;                   // the private data for swap manager
    };
    

    mm实现类似于物理内存管理里的free_area,是一个管理虚拟内存的链表,mm为指向头元素的指针,每一项都是vma

    mm_create: 分配一个mm并初始化
    如果此时已初始化SM,则调用SM的init_mm

    mm_destroy: 释放mm管理的内存和它自身

    vma_create: 创建一个vma并初始化

    insert_vma_struct: 把指定vma插入到指定mm里.
    以为要保证插入后起始地址从小到达排,所以遍历mm->mmap_list,找到地址刚好比vma地址大的一项,插到它前面.并检查vma的地址范围与前一项和后一项是否重叠

    find_vma: 在mm里查找包含指定addr的vma
    与插入不同,查找是按着mmap_cache遍历链表来缩短查找的期望时间,并在查找成功后更新mmap_cache为找到的vma

    pmm.c

    kmalloc: 分配n字节的内容,间接使用了alloc_pages

    kfree: 释放从ptr起n字节的内容,间接使用了free_pages

    page_insert(pgdir,page,la,perm):
    *get_pte(pgdia,la,1)=page2pa(page)|PTE_P|perm
    还有对page.ref,快表更新,pte的旧page的清理等细节

    pgdir_alloc_page:
    把(pgdir,la)对应的pte分配个page,并把page放到pra队列队尾,并更新page->pra->vaddr

    memlayout.h:
    Page结构里增加了俩成员
    list_entry_t pra_page_link 在PRA里作为链表项
    uintptr_t pra_vaddr 用于在被换出时记录当前线性地址

    swap_fifo.c&.h

    实现了基于FIFO的页置换算法

    fifo_init_mm: 用le变量pra_list_head作为队头,令mm->sm_priv=队头

    fifo_map_swappable: 把指定page添加到队尾

    fifo_swap_out_victim: victim在这里有被替换者的意思.把队头page出队列,并返回之

    swapfs.c&.h

    封装了对SWAP分区的读写操作

    swap.c&.h

    在物理内存管理中,当PTE的存在位为0时,表示物理页不在内存中.我们把此时的PTE转化为swap_entry_t(SET)来描述一个处于换出状态的物理页在外存中的偏移

    /* *
     * swap_entry_t
     * --------------------------------------------
     * |         offset        |   reserved   | 0 |
     * --------------------------------------------
     *           24 bits            7 bits    1 bit
     * */
    

    为实现SWAP机制,定义了swap_manager结构体,原理类似于类似于PMM

    struct swap_manager
    {
         const char *name;
         /* Global initialization for the swap manager */
         int (*init)            (void);
         /* Initialize the priv data inside mm_struct */
         int (*init_mm)         (struct mm_struct *mm);
         /* Called when tick interrupt occured */
         int (*tick_event)      (struct mm_struct *mm);
         /* Called when map a swappable page into the mm_struct */
         int (*map_swappable)   (struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in);
         /* When a page is marked as shared, this routine is called to
          * delete the addr entry from the swap manager */
         int (*set_unswappable) (struct mm_struct *mm, uintptr_t addr);
         /* Try to swap out a page, return then victim */
         int (*swap_out_victim) (struct mm_struct *mm, struct Page **ptr_page, int in_tick);
         /* check the page relpacement algorithm */
         int (*check_swap)(void);     
    };
    

    swap_init:
    计算SWAP分区的最大页数
    将默认sm设为swap_manager_fifo,并调用它的初始化函数
    检查初始化是否成功

    swap_out: 把mm的pra队列的前n个page出队并写入外存
    重复n次:
    (1)把mm的pra队列的头page出队列
    (2)获取page对应的pte
    (3)把page写入外存
    (4)更新pte,转化为set格式
    (5)更新快表

    swap_in:
    (1)分配一页内存result
    (2)获取指定addr对应的pte(当前为set格式)
    (3)把pte对应的扇取区域读入result
    (4)返回result地址

    swap_out的触发时机:
    在pmm.c的alloc_pages里
    当swap初始化标志为真,并且分配页失败时,会写入外存,腾出空间.

    swap_in的触发时机:
    pagefault异常处理函数:do_pgfault(mm, error_code, addr)
    大部分情况下会输出各种异常信息,只有在满足以下条件时会继续执行

    * IF (write an existed addr ) OR
    *    (write an non_existed addr && addr is writable) OR
    *    (read  an non_existed addr && addr is readable)
    

    此时意味着发生缺页了,
    (1)获取addr对应的vma
    (2)获取vma对应的权限
    (3)获取addr对应的pte
    (4)pte为0,pgdir_alloc_page
    (5)pte!=0,那就当成set进行swap_in,读进后更新pte,更新pra队列和page->ptr_vaddr

  • 相关阅读:
    POJ-2253 Frogger dijsktra查找间隔最小的路径
    LightOJ-1282 Leading and Trailing 模算数 快速幂 对数的用法
    LightOJ-1341 Aladdin and the Flying Carpet 分解质因数(注意对大素数的优化)
    UVA-10200 Prime Time 素数(注意除法精度)
    POJ-2142 The Balance 扩展欧几里德(+绝对值和最小化)
    ArchLinux 音乐播放客户端ncmpcpp和服务端mpd的配置
    [笔记-统计学习方法]感知机模型(perceptron) 原理与实现
    [Bug]Python3.x AttributeError: libtest.so: undefined symbol: fact
    [Bug]C++ XXX:undefined reference to "xxx"
    ip代理池的爬虫编写、验证和维护
  • 原文地址:https://www.cnblogs.com/kangyupl/p/12752885.html
Copyright © 2011-2022 走看看