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 1887 Testing the CATCHER
    HDU 3374 String Problem
    HDU 2609 How many
    POJ 1509 Glass Beads
    POJ 1458 Common Subsequence
    POJ 1159 Palindrome
    POJ 1056 IMMEDIATE DECODABILITY
    POJ 3080 Blue Jeans
    POJ 1200 Crazy Search
    软件体系结构的艺术阅读笔记1
  • 原文地址:https://www.cnblogs.com/kangyupl/p/12752885.html
Copyright © 2011-2022 走看看