一、内存页面回收
参考:http://www.wowotech.net/memory_management/233.html
内核会回收很少使用的内存页面来保证系统持续有内存使用。页面的回收方式有三种
- 页回写:如果一个很少使用的页的后备存储器是一个块设备(例如文件映射),则可以将内存直接同步到块设备,腾出的页面可以被重用。
- 页交换:如果页面没有后备存储器,则可以交换到特定swap分区,再次被访问时再交换回内存。
- 页丢弃:如果页面的后备存储器是一个文件,但文件内容在内存不能被修改(例如可执行文件),那么在当前不需要的情况下可直接丢弃。
触发页面回收的时机如下图所示:

当触发页面回收时,内核对下列分配的内存页进行回收处理:
- LRU列表中的页框
- slab缓存:所有注册到shrinker_list的shrinker都会被触发回收内存。
参考mm/vmscan.c
内核中定义了一个列表shrinker_list,外部通过register_shrinker、unregister_shrinker向该列表添加和移除shrinker。
shrinker的定义如下:
1 /* 2 * A callback you can register to apply pressure to ageable caches. 3 * 4 * @count_objects should return the number of freeable items in the cache. If 5 * there are no objects to free or the number of freeable items cannot be 6 * determined, it should return 0. No deadlock checks should be done during the 7 * count callback - the shrinker relies on aggregating scan counts that couldn't 8 * be executed due to potential deadlocks to be run at a later call when the 9 * deadlock condition is no longer pending. 10 * 11 * @scan_objects will only be called if @count_objects returned a non-zero 12 * value for the number of freeable objects. The callout should scan the cache 13 * and attempt to free items from the cache. It should then return the number 14 * of objects freed during the scan, or SHRINK_STOP if progress cannot be made 15 * due to potential deadlocks. If SHRINK_STOP is returned, then no further 16 * attempts to call the @scan_objects will be made from the current reclaim 17 * context. 18 * 19 * @flags determine the shrinker abilities, like numa awareness 20 */ 21 struct shrinker { 22 unsigned long (*count_objects)(struct shrinker *, 23 struct shrink_control *sc); 24 unsigned long (*scan_objects)(struct shrinker *, 25 struct shrink_control *sc); 26 27 int seeks; /* seeks to recreate an obj */ 28 long batch; /* reclaim batch size, 0 = default */ 29 unsigned long flags; 30 31 /* These are for internal use */ 32 struct list_head list; 33 /* objs pending delete, per node */ 34 atomic_long_t *nr_deferred; 35 };
lowmemorykiller就是通过向shrinker_list中注册shrinker。
当内存不足时kswapd线程会遍历shrinker_list链表,并回调已注册的shrinker函数来回收内存page,kswapd还会周期性唤醒来执行内存操作。每个zone维护active_list和inactive_list链表,内核根据页面活动状态将page在这两个链表之间移动,最终通过shrink_slab和shrink_zone来回收内存页
浙公网安备 33010602011771号