LRUVEC && pagevec
1、背景
每个node维护一个lruvec数组,数组包含LRU_INACTIVE_ANON、LRU_ACTIVE_ANON、LRU_INACTIVE_FILE、LRU_ACTIVE_FILE、LRU_UNEVICTABLE五个链表;
每个cpu维护五个pagevec,每个pagevec最多可以缓存15个page,正常一个page分出去后是先加入到cpu的pagevec的,然后批量写到node的lruvec链表里;
五个pagevec分别为:lru_add_pvec、lru_rotate_pvecs、lru_deactivate_file_pvecs、lru_lazyfree_pvecs、activate_page_pvecs。
2、pagevec
2.1、lru_add_pvec
page分配成功后,最终通过__lru_cache_add加入到cpu的lru_add_pvec pagevec里;当pagevec里的page个数到达15后,paevec_add就会返回0,因此进入__pagevec_lru_add,将pagevec的page刷新到node的lruvec里;
2.2.1、Page cache
add_to_page_cache_lru
lru_cache_add
__lru_cache_add
pagevec_add
2.2.2、Anon page
do_anonymous_page
lru_cache_add_active_or_unevictable
lru_cache_add
__lru_cache_add
pagevec_add
2.2、lru_rotate_pvecs
1)、对于已经完成writeback的dirty page,如果page是可回收的,则将page移除到inactive的末尾,便于优先回收;
end_page_writeback
rotate_reclaimable_page
pagevec_add(将page加到cpu的lru_rotate_pvecs里)
pagevec_move_tail(如果lru_rotate_pvecs的page个数超过15个)
pagevec_move_tail_fn
del_page_from_lru_list(page, lruvec, page_lru(page));(从当前的lru链表移除)
ClearPageActive(page); (清除active标志)
add_page_to_lru_list_tail(page, lruvec, page_lru(page)); (加入inactive链表的末尾)

2.3、lru_deactivate_file_pvecs
1)、将一个page cache移到inactive lru里(比如手工触发drop cache释放pagecache);
invalidate_mapping_pages deactivate_file_page pagevec_add(将添加到cpu的lru_deactivate_file_pvecs) lru_deactivate_file_fn(lru_deactivate_file_pvecs的个超过15个) del_page_from_lru_list(page, lruvec, lru + active); (从原来的lru里删除) ClearPageActive(page); (清除active标记) ClearPageReferenced(page); (清除reference标记) add_page_to_lru_list(page, lruvec, lru); (添加到inactive 链表)
2.4、lru_lazyfree_pvecs
1)、对madvise free的page标记lazyfree
2.5、activate_page_pvecs
将page从inactive迁移到active里;
1)、do_swap_page(swap page的swap in流程)
2)、mark_page_accessed(主要针对pagecache的第二次访问)
3、LRU
3.1、LRU_INACTIVE_ANON
1)、shrink_active_list的时候,将page从active_list里移除到inactive_list;
2)、分配anon page的是,vma是lock的,但vma不属于VM_SEPCIAL类型;
3.2、LRU_ACTIVE_ANON
1)、一般情况下,在anon的pape fault流程里,分配完anon page后会直接设置active page,然后将page加入到LRU_ACTIVE_ANON链表里;
do_anonymous_page
lru_cache_add_active_or_unevictable

2)、通过active_page_pvecs,将page从inactive链表移除到active链表;
3.3、LRU_INACTIVE_FILE
1)、page cache第一次分配的时候,没有设置active page,先加到INCATIVE链表里;

3.4、LRU_ACTIVE_FILE
1)、page cache第二次访问的时候,从INACTIVE list迁移到ACTIVE list;
4、总结:
1)、每个cpu管理5个pagevec,每个node管理5个lru链表;
2)、分配page的时候,先加入到cpu的lru_add_pvec,等满15个后才一次性加入node的lru链表里;
3)、对于anon page,一般情况是第一次分配的时候就会设置ACTIVE PAGE标记,最终加入到node 的ACTIVE LRU链表;
4)、对于page cache,第一次分配的时候page是inactive的,第二次访问的时候,才会设置page的active标记,将page从inactive lru链表迁移到active lru链表;
浙公网安备 33010602011771号