重读页面的回收处理笔记1

来源:互联网 发布:微信点赞截图制作软件 编辑:程序博客网 时间:2024/06/05 03:09

除了slab分配器,系统中所有正在使用的页面都存放在页面高速缓存中,并且通过page结构体的lru链表在一起,

所以很容易去扫描并替换他们。slab页面没有放在page cache中。

对于每一个zone:都有下面几个参数

    struct list_head    active_list;
    struct list_head    inactive_list;
    unsigned long        nr_scan_active;
    unsigned long        nr_scan_inactive;

 


static inline void
add_page_to_active_list(struct zone *zone, struct page *page)
{
    list_add(&page->lru, &zone->active_list);
    __inc_zone_state(zone, NR_ACTIVE);
}

static inline void
add_page_to_inactive_list(struct zone *zone, struct page *page)
{
    list_add(&page->lru, &zone->inactive_list);
    __inc_zone_state(zone, NR_INACTIVE);
}

这两个函数非常关键,先列在上面。

内存分配有下面的三种方式:

1:kmalloc/kfree   会从cache_sizes这个通用的cache上申请具体的slab对象或者会调用__kmem_cache_free(),将当前内存归还到缓存cache_sizes相应slab上

 

2:alloc_page()和alloc_pages()最终调用__alloc_pages(),使用Buddy伙伴算法,
  zone->free_area[order]或者拆分order+1之上的连续内存,申请若干页连续的物理内存

free_pages()->__free_pages_ok()将内存归还到Buddy伙伴算法管理的
zone->free_area[order]

 

上面的函数,都应该是真正的分配了物理内存。

3:vmalloc和vfree分配的进程空间连续的虚拟空间,但是“他们对应的物理内存还是要经过缺页中断来分配”,我认为这句话是有问题的,在代码中已经通过alloc-page来分配了物理内存,建立了页表。分配的物理地址的页争也是不连续的。

也就是说确保页在虚拟地址空间内是连续的。它通过分配非连续的物理内存块,再“修正”页表。但是为什么这里还说需要缺页中断呢?因为一个进程启动的时候,他把父进程的用户空间的pgd拷贝了,但是在执行的时候,访问内核数据或者代码,会发生vmalloc地址错误,然后把init进程的pgd拷贝到该进程,这也保证了共响内核的pgd,然后你这个时候这个地址才可以访问,但是在vmalloc的时候,物理内存已经有了。

代码如下:

static inline int alloc_area_pte (pte_t * pte, unsigned long address,
                        unsigned long size, int gfp_mask, pgprot_t prot)
{
        unsigned long end;

        address &= ~PMD_MASK;
        end = address + size;
        if (end > PMD_SIZE)
                end = PMD_SIZE;
        do {
                struct page * page;
                spin_unlock(&init_mm.page_table_lock);
                page = alloc_page(gfp_mask);
                spin_lock(&init_mm.page_table_lock);
                if (!pte_none(*pte))
                        printk(KERN_ERR "alloc_area_pte: page already exists/n");
                if (!page)
                        return -ENOMEM;
                set_pte(pte, mk_pte(page, prot));
                address += PAGE_SIZE;
                pte++;
        } while (address < end);
        return 0;
}

从上面很清晰的看到,会call alloc_page这个分配函数,建立页表给init的pgd



原创粉丝点击