Linux Swap 介绍
由于内存和磁盘的读写性能差异较大,Linux会在内存充裕时将空闲内存用于缓存磁盘数据,以提高I/O性能。相对的在内存紧张时Linux会将这些缓存回收,将脏页回写到磁盘中。而在进程的地址空间中,如heap,stack等匿名页,在磁盘上并没有对应的文件,但同样有回收到磁盘上以释放出空闲内存的需求。swap机制通过在磁盘上开辟专用的swap分区作为匿名页的backing storage,满足了这一需求。本文简要的对Linux中的swap机制进行了介绍。
一、swap分区
1. swap分区的创建
Linux中存在两种形式的swap分区:swap disk和swap file。前者是一个专用于做swap的块设备,作为裸设备提供给swap机制操作;后者则是存放在文件系统上的一个特定文件,其实现依赖于不同的文件系统,会有所区别。
图1 两种swap分区
通过mkswap命令可以将一个swap disk或swap file转换为swap分区的格式。随后可通过swapon和swapoff命令开启或关闭对应的swap分区。通过cat /proc/swaps或swapon -s可以查看使用中的swap分区的状态。
图2 swap分区的创建及使用
2. swap的数据结构
内核中使用swap_info_struct结构体来管理swap分区,其关键成员如下:
一个swap_info_struct对应一个swap分区。如下图所示,swap分区内部会以page大小为单位划分出多个swap slot,同时通过swap_map对每个slot的使用情况进行记录,为0代表空闲,大于0则代表该slot被map的进程数量。
图3 swap info
发生内存回收时,一个内存页会被回收到一个slot中,同时会修改pte内容为slot对应的swp_entry_t。swp_entry_t是一个64位的变量,其结构如下图所示,其中2-7位存放swap分区的type,8-57位存放slot在分区内的offset。内存换入时,通过pte的内容即可在磁盘上找到对应的slot。
图4 swp_entry_t
二、swap out
1. 回收流程
内核中的内存回收流程,最终都会走到shrink_page_list中,该函数对page_list链表中的内存依次处理,回收满足条件的内存。匿名页回收如下图所示,其回收需要经过两次shrink。
图5 swap out 流程
第一次shrink时,内存页会通过add_to_swap分配到对应的swap slot,设置为脏页并进行回写,最后将该page加入到swapcache中,但不进行回收。
第二次shrink时,若脏页已经回写完成,则将该page从swapcache中删除并回收。
2. swap slot cache
为了提高swap slot的分配速度,内核引入了swap slot cache机制。该机制定义了一个per_cpu的buffer,包含alloc和free两部分cache,分别用于分配和释放。
图6 swap slot cache
3. ssd查找算法
为了提高swap机制在ssd设备上的性能,内核引入了swap_cluster_info结构体。如下图所示,每SWAPFILE_CLUSTER个连续的slot会组合成一个cluster,内核在做内存换出时,会以cluster为单位查找空闲的slot,而不再遍历swap_map,从而降低了锁竞争,也保证了ssd设备上的磨损均衡。
图7 swap_cluster_info
三、swap in
1. 换入流程
当换出的内存产生缺页异常时,会通过do_swap_page查找到磁盘上的slot,并将数据读回,其流程如下图所示。
图8 swap in 流程
2. swapin_readahead
类似于IO预读机制,swap in的流程中也实现了预读。由于SSD的随机读写能力要强于HDD,在基于物理地址的预读机制之外,内核还引入了基于VMA的预读。两种预读方式可以通过/sys/kernel/mm/swap/vma_ra_enabled节点进行选择。
图9 swapin_readahead
四、总结
本文简要介绍了Linux中的swap流程及一些优化机制。随着SSD设备的快速发展以及新型存储设备的逐步应用,swap机制的性能得到了很大改善,并带来了一些新的优化方向。
参考材料
[1] https://www.kernel.org/doc/gorman/html/understand/understand014.html
[2] http://sopa.dis.ulpgc.es/ii-dso/leclinux/mm/swap/
[3] http://jake.dothome.co.kr/swap-1/
[4] https://lwn.net/Articles/704478/
[5] https://zhuanlan.zhihu.com/p/70964551
[6] https://blog.csdn.net/qkhhyga2016/article/details/88722458