inverse map 页框逆映射

inverse map页框逆映射



在页回收中,逆映射是一个有意思,并且很有技巧的一个功能.

逆映射:就是从给定的page来找到所有的引用者,特别的是PTE页表项.
有了逆映射就能安心释放指定page了.不然就会杯具了.

逆映射的场景:共享页框最常见的是共享库,C库基本上映射到所有的用户进程了.其次比如共享内存.

**kernel的演进:**
1. 2.4时代是遍历所有的进程要找到此page的引用者的PTE.简单粗暴.
效率上有点弱,功能上还是达到的.
2. 2.5时代改进了,牺牲了空间换效率,为每个页分配一个list来记录引用者.因为每个page都要增加了size空间,其实大部分页是不存在共享的.据说被抱怨.
3. 2.6又改进了,提出所谓的基于对象的方法.

**2种共享页,或者是2种对象**
1. anonymous 匿名页,这个名字其实真取得不好.MAP_PRIVATE, stack * or brk vma (with NULL file) 
2. file map 文件映射页.


**page/anon_vma/address_space**
struct page {
    
    union {
        atomic_t _mapcount;    /* Count of ptes mapped in mms,    
    };
    union {
        struct {
        struct address_space *mapping;    /* If low bit clear, points to
                         * inode address_space, or NULL.
                         * If page mapped as anonymous
                         * memory, low bit is set, and
                         * it points to anon_vma object:
                         * see PAGE_MAPPING_ANON below.
                         */
        };
 }

};

struct anon_vma {
    spinlock_t lock;    /* Serialize access to vma list */
    struct list_head head;    /* List of private "related" vmas */
};

struct vm_area_struct {
    struct mm_struct * vm_mm;    /* The address space we belong to. */
    
    /*
     * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
     * list, after a COW of one of the file pages.    A MAP_SHARED vma
     * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
     * or brk vma (with NULL file) can only be in an anon_vma list.
     */
    struct list_head anon_vma_node;    /* Serialized by anon_vma->lock */
    struct anon_vma *anon_vma;    /* Serialized by page_table_lock */

    
};


struct address_space {
    struct inode        *host;        /* owner: inode, block_device */    
    struct prio_tree_root    i_mmap;        /* tree of private and shared mappings */
    struct list_head    i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
    
} ;

**页逆映射**
page->mapping[0]来区分是何种对象.
如果是anonymous对象,则mapping指向anon_vma这个对象,这个对象list所有的vma_area_struct.
vma_area_struct->vm_mm->PGD就能找到PTE了.

如果是file对象,则mapping指向file address space对象.这个address_space.i_mmap记录有所进程的共享映射信息vma_area_struct.这个也就能找到所有进程的PTE信息了. 特别要说的是i_mmap是棵优先查找树. over.

**func**
int try_to_unmap(struct page *page, int migration)
{
    int ret;

    BUG_ON(!PageLocked(page));

    if (PageAnon(page))
        ret = try_to_unmap_anon(page, migration);
    else
        ret = try_to_unmap_file(page, migration);

    if (!page_mapped(page))
        ret = SWAP_SUCCESS;
    return ret;
}

try_to_unmap_one()释放一页
{


address = vma_address(page, vma);算出虚拟地址
    if (address == -EFAULT)
        goto out;

    pte = page_check_address(page, mm, address, &ptl);由虚拟地址算出pte
    if (!pte)
        goto out;

    ...后续的页表操作 , 略
}

猜你喜欢

转载自blog.csdn.net/pcj2007/article/details/81631820