页面回收的最重要的函数即:shrink_zone,其
主要工作就是shrink_active_list和shrink_inactive_list。
在shrink_zone中,如果该zone中需要扫描到的active和inactive的内存大于swap的阈值,即32个物理页面,则开始进行回收,否则不回收。
shrink_active_list:移动一部分active中的页面到inactive中
shrink_inactive_list:释放inactive的内存。
在shrink_active_list中:
1. lru_add_drain();目的是将per cpu中的页面放入到LRU链表中(默认放到对应zone的inactive_list中),per cpu的页面是基于pagevec,最多缓存14个。
2. isolate_lru_pages中lru中隔离出一定量的页面(在锁(&zone->lru_lock)内,然后批量处理,pagevec的思想)放到临时链表中,依次遍历该临时链表,如果其中的page有映射,并且referenced为1,则说明该页面刚被访问过,因此不能回收,还会被放入到临时的active链表中,其余的被放入到临时inactive中。
3. 然后批量处理临时的active和临时的inactive链表,回归中各自对应的zone的active_list和inactive_list中。
在shrink_inactive_list中:
1. 类似active的处理,将分离出的页面放到临时链表page_list中。
2. shrink_page_list将临时链表中的页面处理,依次按照页面的状态,逐一处理(如dirty,writeback,有需要还要释放bh)。
3. 将需要释放的页面放到临时向量表中,然后批量释放__pagevec_release_nonlru(&freed_pvec);其pagevec_free将页面返还给伙伴系统中。
4. 执行完前三步,还有页面没有被回收,则将其再放回LRU中,zone的active_list和inactive_list。
在shrink_zone中,如果该zone中需要扫描到的active和inactive的内存大于swap的阈值,即32个物理页面,则开始进行回收,否则不回收。
shrink_active_list:移动一部分active中的页面到inactive中
shrink_inactive_list:释放inactive的内存。
在shrink_active_list中:
1. lru_add_drain();目的是将per cpu中的页面放入到LRU链表中(默认放到对应zone的inactive_list中),per cpu的页面是基于pagevec,最多缓存14个。
2. isolate_lru_pages中lru中隔离出一定量的页面(在锁(&zone->lru_lock)内,然后批量处理,pagevec的思想)放到临时链表中,依次遍历该临时链表,如果其中的page有映射,并且referenced为1,则说明该页面刚被访问过,因此不能回收,还会被放入到临时的active链表中,其余的被放入到临时inactive中。
3. 然后批量处理临时的active和临时的inactive链表,回归中各自对应的zone的active_list和inactive_list中。
在shrink_inactive_list中:
1. 类似active的处理,将分离出的页面放到临时链表page_list中。
2. shrink_page_list将临时链表中的页面处理,依次按照页面的状态,逐一处理(如dirty,writeback,有需要还要释放bh)。
3. 将需要释放的页面放到临时向量表中,然后批量释放__pagevec_release_nonlru(&freed_pvec);其pagevec_free将页面返还给伙伴系统中。
4. 执行完前三步,还有页面没有被回收,则将其再放回LRU中,zone的active_list和inactive_list。