看到這篇文章的時候,感覺只有兩個字:郁悶。還在Linux-2.6.29的時候,就看是看Linux kernel virtual machine,那時候就感覺多個VM肯定有很多的內存是共享的,完全可以合并,沒想到Linux的發展是這么的快,linux-2.6.32就正式的支持了ksm機制,實現了共享內存的合并,而且還是專門針對虛擬機的,真是讓我抓狂,都是可惡的項目,全是在浪費時間。下面轉載ksm相關的一篇文章,學習之余做個記錄,已備畢業設計只需。
簡介: 作為一個系統管理程序(hypervisor),Linux? 有幾個創新,2.6.32 內核中一個有趣的變化是 Kernel Shared Memory (KSM)。KSM 允許這個系統管理程序通過合并內存頁面來增加并發虛擬機的數量。本文探索 KSM 背后的理念(比如存儲去耦合)、KSM 的實現、以及如何管理 KSM。
虛擬化技術從上世紀 60 年代開始出現,經由 IBM? System/360? 大型機得以流行。50 年過后,虛擬化技術取得了跨越式發展,使得多個操作系統和應用程序共享一個服務器成為可能。這一特殊用途(稱為 服務器虛擬化 )正在演變為數據中心,因為單個物理機能夠用于托管 10 個(一般情況)或更多虛擬機(VM),如圖 1 所示。這種虛擬化使基礎設施更動態、更省電、(因而也)更經濟。
頁面都是相同的。假如操作系統和應用程序代碼以及常量數據在 VMs 之間相同,那么這個特點就很有用。當頁面惟一時,它們可以被合并,從而釋放內存,供其他應用程序使用。圖 2 演示了內存共享,并展示了在內容相同的 VMs 之間共享頁面時更多可用閑置內存的好處。
圖 2. 跨 VMs 的內存共享
您很快就會發現,盡管 Linux 中的內存共享在虛擬環境中有優勢(KSM 最初設計用于基于內核的虛擬機),但它在非虛擬環境中仍然有用。事實上,KSM 甚至在嵌入式 Linux 系統中也有用處,表明了這種方法的靈活性。下面,我們將探索這種 Linux 內存共享方法,以及如何使用該方法提高服務器的內存密度,從而增加其托管其他應用程序或 VMs 的能力。
存儲技術中的一個稱為 去耦合(de-duplication) 的最新進展是 Linux 和其他系統管理程序中的內存共享的先驅。去耦合這種技術通過刪除冗余數據(基于數據塊,或者基于更大的數據片段,比如文件)來減少已存儲的數據。公共數據片段被合并(以一種 copy-on-write [CoW] 方式),釋放空間供其他用途。使用這種方法,存儲成本更低,最終需要的存儲器也更少。鑒于當前的數據增長速度,這個功能顯得非常重要。
KSM 作為內核中的守護進程(稱為
ksmd
)存在,它定期執行頁面掃描,識別副本頁面并合并副本,釋放這些頁面以供它用。KSM 執行上述操作的過程對用戶透明。例如,副本頁面被合并(然后被標記為只讀),但是,如果這個頁面的其中一個用戶由于某種原因更改該頁面,該用戶將(以 CoW 方式)收到自己的副本。可以在內核源代碼 ./mm/ksm.c 中找到 KSM 內核模塊的完整實現。
KSM 依賴高級應用程序來提供指導,根據該指導確定合并的候選內存區域。盡管 KSM 可以只掃描系統中的匿名頁面,但這將浪費 CPU 和內存資源(考慮到管理頁面合并進程所需的空間)。因此,應用程序可以注冊可能包含副本頁面的虛擬區域。
KSM 應用程序編程接口(API)通過
madvise
系統調用(見清單 1)和一個新的建議參數(advice parameter)
MADV_MERGEABLE
(表明已定義的區域可以合并)來實現。可以通過
MADV_UNMERGEABLE
參數(立即從一個區域取消合并任何已合并頁面)從可合并狀態刪除一個區域。注意,通過
madvise
來刪除一個頁面區域可能會導致一個
EAGAIN
錯誤,因為該操作可能會在取消合并過程中耗盡內存,從而可能會導致更大的麻煩(內存不足情況)。
#include <sys/mman.h> int madvise ( void *start, size_t length, int advice ); |
一旦某個區域被定義為 “可合并”,KSM 將把該區域添加到它的工作內存列表。啟用 KSM 時,它將搜索相同的頁面,以寫保護的 CoW 方式保留一個頁面,釋放另一個頁面以供它用。
KSM 使用的方法與內存去耦合中使用的方法不同。在傳統的去耦合中,對象被散列化,然后使用散列值進行初始相似性檢查。當散列值一致時,下一步是進行一個實際對象比較(本例中是一個內存比較),以便正式確定這些對象是否一致。KSM 在它的第一個實現中采用這種方法,但后來開發了一種更直觀的方法來簡化它。
在當前的 KSM 中,頁面通過兩個 “紅-黑” 樹管理,其中一個 “紅-黑” 樹是臨時的。第一個樹稱為 不穩定樹 ,用于存儲還不能理解為穩定的新頁面。換句話說,作為合并候選對象的頁面(在一段時間內沒有變化)存儲在這個不穩定樹中。不穩定樹中的頁面不是寫保護的。第二個樹稱為 穩定樹 ,存儲那些已經發現是穩定的且通過 KSM 合并的頁面。為確定一個頁面是否是穩定頁面,KSM 使用了一個簡單的 32 位校驗和(checksum)。當一個頁面被掃描時,它的校驗和被計算且與該頁面存儲在一起。在一次后續掃描中,如果新計算的校驗和不等于此前計算的校驗和,則該頁面正在更改,因此不是一個合格的合并候選對象。
使用 KSM 進程處理一個單一的頁面時,第一步是檢查是否能夠在穩定樹中發現該頁面。搜索穩定樹的過程很有趣,因為每個頁面都被視為一個非常大的數字(頁面的內容)。一個
memcmp
(內存比較)操作將在該頁面和相關節點的頁面上執行。如果
memcmp
返回 0,則頁面相同,發現一個匹配值。反之,如果
memcmp
返回
-1
,則表示候選頁面小于當前節點的頁面;如果返回
1
,則表示候選頁面大于當前節點的頁面。盡管比較 4KB 的頁面似乎是相當重量級的比較,但是在多數情況下,一旦發現一個差異,
memcmp
將提前結束。請參見圖 3 查看這個過程的視覺呈現。
如果候選頁面位于穩定樹中,則該頁面被合并,候選頁面被釋放。有關代碼位于 ksm.c/
stable_tree_search()
(稱為 ksm.c/
cmp_and_merge_page()
)中。反之,如果沒有發現候選頁面,則應轉到不穩定樹(參見 ksm.c/
unstable_tree_search()
)。
在不穩定樹中搜索時,第一步是重新計算頁面上的校驗和。如果該值與原始校驗和不同,則本次掃描的后續搜索將拋棄這個頁面(因為它更改了,不值得跟蹤)。如果校驗和沒有更改,則會搜索不穩定樹以尋找候選頁面。不穩定樹的處理與穩定樹的處理有一些不同。第一,如果搜索代碼沒有在不穩定樹中發現頁面,則在不穩定樹中為該頁面添加一個新節點。但是如果在不穩定樹中發現了頁面,則合并該頁面,然后將該節點遷移到穩定樹中。
當掃描完成(通過 ksm.c/
ksm_do_scan()
執行)時,穩定樹被保存下來,但不穩定樹則被刪除并在下一次掃描時重新構建。這個過程大大簡化了工作,因為不穩定樹的組織方式可以根據頁面的變化而變化(還記得不穩定樹中的頁面不是寫保護的嗎?)。由于穩定樹中的所有頁面都是寫保護的,因此當一個頁面試圖被寫入時將生成一個頁面故障,從而允許 CoW 進程為寫入程序取消頁面合并(請參見 ksm.c/
break_cow()
)。穩定樹中的孤立頁面將在稍后被刪除(除非該頁面的兩個或更多用戶存在,表明該頁面還在被共享)。
如前所述,KSM 使用 “紅-黑” 樹來管理頁面,以支持快速查詢。實際上,Linux 包含了一些 “紅-黑” 樹作為一個可重用的數據結構,可以廣泛使用它們。“紅-黑” 樹還可以被 Completely Fair Scheduler (CFS) 使用,以便按時間順序存儲任務。您可以在 ./lib/rbtree.c 中找到 “紅-黑” 樹的這個實現。
KSM 的管理和監控通過 sysfs(位于根 /sys/kernel/mm/ksm)執行。在這個 sysfs 子目錄中,您將發現一些文件,有些用于控制,其他的用于監控。
第一個文件
run
用于啟用和禁用 KSM 的頁面合并。默認情況下,KSM 被禁用(
0
),但可以通過將一個
1
寫入這個文件來啟用 KSM 守護進程(例如,
echo 1 > sys/kernel/mm/ksm/run
)。通過寫入一個
0
,可以從運行狀態禁用這個守護進程(但是保留合并頁面的當前集合)。另外,通過寫入一個
2
,可以從運行狀態(
1
)停止 KSM 并請求取消合并所有合并頁面。
KSM 運行時,可以通過 3 個參數(sysfs 中的文件)來控制它。sleep_millisecs 文件定義執行另一次頁面掃描前
ksmd
休眠的毫秒數。max_kernel_pages 文件定義
ksmd
可以使用的最大頁面數(默認值是可用內存的 25%,但可以寫入一個
0
來指定為無限)。最后,pages_to_scan 文件定義一次給定掃描中可以掃描的頁面數。任何用戶都可以查看這些文件,但是用戶必須擁有根權限才能修改它們。
還有 5 個通過 sysfs 導出的可監控文件(均為只讀),它們表明
ksmd
的運行情況和效果。full_scans 文件表明已經執行的全區域掃描的次數。剩下的 4 個文件表明 KSM 的頁面級統計數據:
- pages_shared:KSM 正在使用的不可交換的內核頁面的數量。
- pages_sharing:一個內存存儲指示。
- pages_unshared:為合并而重復檢查的惟一頁面的數量。
- pages_volatile:頻繁改變的頁面的數量。
KSM 作者定義:較高的 pages_sharing/pages_shared 比率表明高效的頁面共享(反之則表明資源浪費)。
Linux 并不是使用頁面共享來改進內存效率的惟一系統管理程序,但是它的獨特之處在于將其實現為一個操作系統特性。VMware 的 ESX 服務器系統管理程序將這個特性命名為 Transparent Page Sharing (TPS),而 XEN 將其稱為 Memory CoW 。不管采用哪種名稱和實現,這個特性都提供了更好的內存利用率,從而允許操作系統(KVM 的系統管理程序)過量使用內存,支持更多的應用程序或 VM。 您可以在最新的 2.6.32 Linux 內核中發現 KSM — 以及其他很多有趣的特性。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
