由於內存和磁盤的讀寫性能差異較大,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

“內核工匠”微信公眾號
Linux 內核黑科技 | 技術文章 | 精選教程