思考题:
-
kswapd内核线程何时会被唤醒?
答: 在伙伴系统分配内存时,发现zone的水位低于WMARK_LOW的时候,kswapd内核线程将被唤醒。
-
LRU链表如何知道page的活跃频繁度?
答:LRU按照先进先出的逻辑,页面首先进入LRU链表头,然后慢慢移动到链表尾,这有一个老化过程。另外,page有PG_referenced/PG_active标志位和页表的PTE_YOUNG位来实现第二次机会法。
-
kswapd按照什么原则来换出页面?
答:页面在活跃LRU链表,需要从链表头到链表尾的一个老化过程才能迁移到不活跃LRU链表。在不活跃LRU链表中又经过一个老化过程后,首先剔除那些脏页面或者正在回写的页面,然后那些在不活跃LRU链表老化过程中没有被访问引用的页面是最佳的被换出的候选者,具体请看shrink_page_list()函数。
-
kswapd按照什么方向来扫描zone?
答:从低zone到高zone,和分配页面的方向相反。
-
kswapd以什么标准来退出扫描LRU?
答:判断当前内存节点是否处于"生态平衡",对于order为0的情况,所有的zone都是平衡的。对于order大于0的内存分配,需要统计从最低端zone到classzone_idx_zone中所有处于平衡状态zone的页面数量(balance_pages),当大于这个节点所有管理的页面managed_pages的25%,那么就认为内存节点处于平衡,详见pgdat_balanced()函数。理想情况下有LRU种活跃匿名页面和不活跃匿名页面比值为3:1,对于文件缓存,活跃的文件缓存应该比不活跃的文件缓存多才是理想情况。
-
手持设备例如安卓系统,没有swap分区或者swap文件,kswapd会扫描匿名页面LRU吗?
答:没有swap分区不会扫描匿名页面LRU链表,需要根据swappiness(互换性)来确定,当没有swap时,swappiness值为0,表示不会像swap写入页面。所以也就不获取扫描匿名页面。详见get_scan_count()函数。
-
swappiness的含义是什么?kswapd如何计算匿名页面和page cache之间的扫描比重?
答:swappiness用于设置向swap写入页面的活跃度。在get_scan_count()函数中计算匿名页面和page cache的扫描比重,计算方法为:首先确定swappiness的值,scan(扫描的总页面数量) = LRU上总页面 >> sc->priority(优先级)
ap = (swappiness*(recent_scanned[0] + 1)) // (recent_rotated[0] + 1),其中recent_scanned表示最近扫描页面的数量
fp = ((200-swappiness)*(recent_scanned[1]+1))/(recent_rotated[1]+1) ,其中recent_rotated反映真实活跃页面的数量
scan_anon = (scan * ap)/ (ap+fp+1)
scan_file = (scan * fp)/ (ap+fp+1)
-
当系统中充斥着大量只访问一次的文件访问(use-one streaming IO)时,kswapd如何来规避这种风暴?
答:根据二次机会法中使用的两个软件标志位来规避风暴,原理是第一次访问的文件,其中会设置PG_referenced为1,但是PG_active还是0,所以不会加入到活跃链表,只有到再次访问时,PG_active才会设置为1,才能加入到活跃链表。这样就有效的规避了只访问一次的文件缓存加入到活跃的LRU链表。
-
在回收page cache时,对于dirty的page cache,kswapd会马上回写吗?
答:不会。
-
内核有哪些页面被kswapd写回交换分区?
答:匿名页面,还有一些特殊情况,是利用shmem机制建立的文件映射,其实也是使用的匿名页面,在内存紧张时,这种页面也会被swap到交换分区。
在linux系统中,当内存有盈余时,内核会尽量多地使用内存作为文件缓存(page cache),从而提高系统的性能。文件缓存页面会加入到文件类型的LRU链表中,当系统内存紧张时,文件缓存页面会被丢弃,或者被修改的文件缓存会被回写到存储设备中,与块设备同步之后便可以释放出物理内存。现在的应用程序越来越转向内存密集型,无论系统中有多少物理内存都是不够用的,因此linux系统会使用存储设备当做交换分区,内核将很少使用的内存换出到交换分区,以便释放出物理内存,这个机制称为页交换(swapping),这些处理机制统称为页面回收(page reclaim).