Linux 操作系統原理 — 內存 — KSM 內存頁共享的性能問題
目錄
文章目錄
目錄
linux 的共享內存
KSM 共享內存頁
性能問題
Shm 接口
linux 的共享內存
進程訪問物理內存空間的原理:在 Linux 的虛擬存儲器中,用戶進程的頁表項和物理地址是多對一的關系,即多個頁表項可以對應一個物理頁面,這就是實現共享內存的底層支撐(幾個進程同時共享物理內存)。
多進程間使用共享內存進行通信:在 Linux 操作系統中使用文件或管道的方式來進行多進程之間的通信會有很多局限性,比如效率的問題,并且進程間通信使用文件描述符不如內存地址訪問來得方便,于是多進程間以共享內存的方式進行通信就成了一個不錯的選擇。
Linux 在編程上提供了多種使用共享內存的方案,兩個運行中的進程共享數據,是進程間通信的高效方法,可有效減少數據拷貝的次數:
mmap 內存共享映射。
XSI 共享內存。
POSIX 共享內存。
KSM 共享內存頁
KSM(Kernel Shared Memory)是 Linux Kernel 的一種內存共享機制,在 2.6.36 版本引入。簡而言之,KSM 用于合并具有相同內容的物理主存頁面以減少頁面冗余。在 Kernel 中有一個 KSM 守護進程 ksmd,它會定期掃描用戶向它注冊的內存區域,尋找到相同的頁面就會將其合并,并用一個添加了寫保護的頁面來代替。當有進程嘗試寫入該頁面時,Kernel 會自動為其分配一個新的頁面,然后將新數據寫入到這個新頁面,這就是典型的 COW 機制。類似的,存儲技術中有一個稱為去耦合(de-duplication)的技術,通過刪除冗余數據(基于數據塊,或者基于更大的數據片段,比如文件)來減少已存儲的數據。公共數據片段被合并(以一種 COW 方式),釋放空間供其他用途。使用這種方法,存儲成本更低,最終需要的存儲器也更少。
KSM 最初被應用到 KVM 上,因為事實證明,如果虛擬化了許多相同的操作系統和應用程序組,那么宿主機上許多內存頁面都是相同的。假如操作系統和應用程序代碼以及常量數據在 VMs 之間相同,那么這個特點就很有用。當頁面惟一時,它們可以被合并,從而釋放內存,供其他應用程序使用。將多個 VMs 具有的相同內存頁合并(共享),可以騰出更多的可用物理內存。
實際上,KSM 可以應用于任何應用。KSM 僅僅會合并匿名頁面,不會對文件映射的頁面做處理,經過 KSM 合并的頁面最初是被鎖定的內存中的,但是現在已經可以像其他頁面一樣被換出到交換區了。但是共享頁一經換出,其共享的特性就被打破,再次換入的時候,ksmd 必須重新對其處理。
前面提到,KSM 僅僅會掃描那些向其注冊的區域,就是向 KSM 模塊注冊了如果條件允許可以被合并的區域,通過 madvise 系統調用可以做到這點 int madvise(addr, length, MADV_MERGEABLE)。同時,應用也可以通過調用 int madvise(addr, length, MADV_UNMERGEABLE) 來取消這個注冊,從而讓頁面恢復私有特性。但是該調用可能會造成內存超額,造成 unmerge 失敗,很大程度上會造成喚醒 Out-Of-Memory killer,殺死當前進程。如果 KSM 沒有在當前運行的 Kernel 啟用,那么前面提到的 madvise 調用就會失敗,如果內核配置了 CONFIG_KSM=y,調用一般是會成功的。
KSM 的管理和監控通過 sysfs(位于根 /sys/kernel/mm/ksm)執行。
pages_to_scan:定義一次給定掃描中可以掃描的頁面數。
sleep_millisecs:定義執行另一次頁面掃描前 ksmd 休眠的毫秒數。
max_kernel_pages:定義 ksmd 可以使用的最大頁面數(默認值是可用內存的 25%,但可以寫入一個 0 來指定為無限)。
merge_across_nodes:控制不同 NUMA 節點內存的合并,如果被設置成 0,則只合并當前 NUMA 節點的內存。
run:控制 ksmd 的運行
0 表示停止 ksmd,但是保持合并的頁面;
1 表示運行 ksmd;
2 表示停止 ksmd 并請求取消合并所有合并頁面。
KSM 合并效果會實時顯示在下面文件:
pages_shared:KSM 正在使用的不可交換的內核頁面的數量。
pages_sharing:一個內存存儲指示。
pages_unshared :為合并而重復檢查的惟一頁面的數量。
pages_volatile:頻繁改變的頁面的數量。
full_scans:表明已經執行的全區域掃描的次數。
性能問題
需要注意的是,應用 KSM 的時候要慎重考慮,因為 KSM 掃描相同的頁面的過程會消耗較多的 CPU 資源,在對虛擬機性能要求苛刻的環境中一般都會禁用 KSM。關閉 KSM,可以讓作為 Hypervisor 的 Linux Kernel(KVM)在負載增加時候,保證虛擬機的響應速度。這里再次印證了一句名言:計算機藝術永遠是時間與空間的較量。
Shm 接口
shmget 創建共享內存。
shmat 啟動對該共享內存的訪問,并把共享內存連接到當前進程的地址空間。
shmdt 將共享內存從當前進程中分離。
Linux 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。