您的位置:首页 > 其它

【存储管理】页面的定期换出do_try_to_free_pages()

2014-05-03 11:36 369 查看
如果进过page_launder()后,如果可分配的物理页面数量仍然不足,那就要进一步设法回收页面,不过不是单纯的从各个进程的用户空间映射的页面中回收,而是其它方面回收,一个是文件关闭后并没立即释放的inode,dentry,作为LRU的后备,以防以后又要用到,用shrink_dcache_memory()和shrink_icache_memory()适当回收;一个是经由slab机制管理的动态分配的数据结构,它倾向于分配和保持过多的空闲物理页面,而不是热衷于换出,因此需要用kmem_cache_reap()来回收。

(1)在do_try_to_free_pages()中的refill_inactive()中,首先是通过kmem_cache_reap()回收由slab机制管理的空闲物理页面,相对而言该动作是很小的;然后从低优先级的开始来回收,判断task_struct中的need_resched是1的话,说明某一个中断服务程序需要调度,要求schedule()让内核再进行一次调度,但要把此进程设置成TASK_RUNNING,主要是因为内核线程永远不会返回用户空间(每当CPU结束一次系统调用和中断服务或从系统空间返回到用户空间时都会检查该标志),为了防止,占住CPU不放,自己调度离开;

(2)在循环中,用refill_inactive_scan()扫描活跃页面队列,试图找到可以转入到不活跃状态的页面;用swap_out()找出一个进程,然后扫描其映射表,从中可以找到不活跃状态的页面,此外,还要尝试dentry和inode结构的页面;在refill_inactive_scan()中,根据优先级来扫描活跃页面队列(优先级为0时是整个活跃页面队列),来设置和移动相应的page结构; 

(3)swap_out()实际只是为把一些页面交换到交换设备上做准备,并不是物理意义上的换出;其中每一个进程中虚存页面对应在内存的集合,称为RSS;从init_task进程开始扫描一圈,找到最大的mm->swap_cnt反映的是该进程在一轮换出页面的努力中尚未受到考察的页面数量;如果一轮下来,没有找到这样的一个best对象,则设置assign再扫描一遍,跳到指定的标号select;而因最近因因异常换入(恢复映射)的页面,将会等到下一次扫描;

(4)swap_out_mm()执行具体的换出,mm->swap_address为考察的页面地址,首先根据该地址找到虚存区域vma,然后调用swap_out_vma()来试图换出一个页面,包括执行,其中执行包括以下几个部分,swap_out_pgd(),swap_out_pmd(),try_to_swap_out();

(5)在try_to_swap_out()中,首先通过pte_present()来测试所指的物理页面是否在内存中,不在即失败,直接跳到标号out_failed;try_to_swap_out()返回失败时,上一层的程序就会跳过这个页面,而试着换出同一个页面表映射的下一个页面,如果该页面表已经穷尽,就试着再往上层试下一个页面表;物理页面是在内存中时,通过pte_page将页面表项的内容换算成指向物理页面的page指针;判断跳过一些在外部设备上的物理页面和不允许换出的保留页面;接着具体考察一个页面,一个物理页面是否应该换出,取决于这个歌页面是否受到了访问,通过pte_test_and_clear_young()来测试_PAGE_BIT_ACCESSED位,如果是1的话说明上一次对同一个页面表项仍在使用,说明页面还很年轻,不易换出,此函数清_PAGE_BIT_ACCESSED位,把它会写到页面表项,为下一次再测试这个标志做准备,还要使用SetPageRerenced将page数据结构中的PG_reference标志置1,即将页面表项中受到过访问的信息转移至页面的数据结构中,并通过age_page_up()来增加页面可以留下来观察的时间;

(6)如果页面不再年轻,linux内核还是给他机会的,查看多久也就要看page->age,当它为0时,我们就可以换出对象了,首先查看该物理页面是否被锁住,锁住的话,直接返回到标号out_failed,加锁成功后,根据页面不同情况做换出的准备了;若page已在swapper_space页面换入换出队列(脏和干净两个)中,说明页面已在交换设备中;使用swap_duplicate()来对swap_entry_t做一些检验和递增相应盘上页面的共享计数;使用set_pte()把那个盘上页面的索引项置入相应的页面表项,原先对内存页面的映射变成了对盘上页面的映射,这样RSS页面也就少了一个页面;使用deactivate()有条件的将page设置成不活跃状态,要考虑三种情况(分配时,用户空间映射,内存模拟磁盘),将页面转入相应的不活跃脏/干净队列;

(7)对于页面page不在swapper_space页面换入换出队列(脏和干净两个)中时,说明尚未为页面在交换设备上建立起映像,或页面来自的是一个文件(若提供vm_operations中的nopage操作,说明页面来自文件不是交换设备,此时可根据虚存地址计算出文件中的页面位置,否则就是普通页面,但尚未建立盘上页面);最后页面如果很久没有访问到,不在swapper_space队列时,也不是文件映射,也是个脏页面,就为它分配一个盘上页面,然后将该盘上页面放入到swapper_space队列中以及活跃的页面队列中,再通过set_page_dirty将页面转到不活跃脏队列中,再使用

page_launder()来洗净;

(8)kreclaimd与kswapd类似,task_struct中的flags字段PF_MEMALLOC都被设置成1,表示它们都是页面管理机制的维护者,kreclaimd中通过reclaim_page()扫描各个页面管理区的不活跃干净页面队列,从中回收页面加以释放。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: