2017-04-26
KSM是內核中的一種內存共享機制,在2.6.36版本的內核中開始引入,簡單來說就是其會 合並某些相同的頁面以減少頁面冗余。在內核中有一個KSM守護進程 ksmd,它定期掃描用戶向它注冊的內存區,尋找相同的頁面,從而用一個添加寫保護的頁面來代替, 當有進程嘗試寫入的時候,會自動分配一個新頁面,這點就是典型的COW機制。
KSM最初應用到KVM上,主要作為內存共享,從而騰出更多的可用物理內存,但是事實上,它可以應用於任何應用。KSM僅僅合並匿名頁面,不會對文件映射的頁面做處理,經過KSM合並的頁面最初是被鎖定的內存中的,但是現在已經可以像其他頁面一樣被換出到交換區,但是一經換出,共享的特性就被打破,再次換入的時候,ksmd必須重新對其處理。前面提到,KSM僅僅會掃描那些請求合並的區域,說請求不太合適,就是向KSM模塊注冊了如果條件允許可以被合並的區域,通過madvise系統調用可以做到這點int madvise(addr, length, MADV_MERGEABLE),同時,應用也可以通過調用int madvise(addr, length, MADV_UNMERGEABLE)取消這個建議從而恢復頁面的私有特性,但是該調用可能會突然請求很多內存,超過當前可用的內存額度,造成unmerge失敗,很大程度上會造成喚醒Out-Of-Memory killer,殺死當前進程。
如果KSM沒被配置進當前運行的內核,前面提到的madvise調用會失敗,如果內核配置了 CONFIG_KSM=y,調用一般會成功,即使KSM守護進程沒有運行,不過在進程運行的時候,調用設置的區間范圍會被注冊進去。
像其他的madvise調用,它們是應用於用戶空間的mmap區域,如果區間包含unmap區域,那么他們就會返回ENOMEM。
應用在使用KSM的時候要慎重考慮,因為KSM掃描相同的頁面會消耗較多的CPU資源,所以一些安裝會禁用KSM。KSM守護進程通過sysfs文件系統控制,在/sys/kernel/mm/ksm/下包含有幾個文件,所有用戶可讀但是只有root用戶可寫
pages_to_scan 在ksmd睡眠之前,需要掃描多少頁面 ,通過echo 100 > /sys/kernel/mm/ksm/pages_to_scan可以修改
sleep_millisecs ksmd的睡眠時間,以毫秒為單位。
merge_across_nodes 控制不同NUMA節點內存的合並,如果被設置成0,則只合並當前NUMA節點的內存。
run 控制ksmd的運行。0停止ksmd,但是保持合並的頁面。1 運行ksmd。2 停止ksmd並unmerge所有合並的頁面。
KSM合並效果實時顯示在下面文件:
pages_shared - how many shared pages are being used
pages_sharing - how many more sites are sharing them i.e. how much saved
pages_unshared - how many pages unique but repeatedly checked for merging
pages_volatile - how many pages changing too fast to be placed in a tree
full_scans - how many times all mergeable areas have been scanned
上面字段意義如下A high ratio of pages_sharing to pages_shared indicates good sharing, but a high ratio of pages_unshared to pages_sharing indicates wasted effort.pages_volatile embraces several different kinds of activity, but a high proportion there would also indicate poor use of madvise MADV_MERGEABLE.
原文內容見內核文檔ksm.txt