一般用戶空間關聯(lián)的物理頁面是按需通過缺頁異常的方式分配和調(diào)頁,當系統(tǒng)物理內(nèi)存不足時頁面回收算法會回收一些最近很少使用的頁面,但是有時候我們需要鎖住一些物理頁面防止其被回收(如時間有嚴格要求的應用),Linux中提供了mlock相關的系統(tǒng)調(diào)用供用戶空間使用來鎖住部分或全部的地址空間關聯(lián)的物理頁面。 本文的分析基于arm64處理器架構,內(nèi)核版本為Linux-5.10.27,我們會結合重點內(nèi)核源代碼來解析mlock是如何做到鎖住進程地址空間關聯(lián)的物理內(nèi)存的,又是如何防止相關的物理頁面被交換出去的。
一、主動缺頁
mlock的主要代碼處理流程如下,這里我們主要關注主動缺頁部分:

mlock處理路徑中,會將VM_LOCKED標志加入到vma->vm_flags中(由于設置的地址區(qū)域有可能跨越多個vma,所以代碼中會涉及到分裂和合并的操作,實質(zhì)上都會設置相關的vma->vm_flags的VM_LOCKED標志),然后會調(diào)用__mm_populate來填充虛擬頁對應的物理頁,最終在faultin_page函數(shù)中試圖查找vma中的每個虛擬頁對應的物理頁面(對應于follow_page_mask函數(shù)),如果沒有找到會調(diào)用handle_mm_fault主動觸發(fā)缺頁處理。 handle_mm_fault函數(shù)是內(nèi)核通用的缺頁異常處理例程,如vma是匿名映射的則分配物理頁面然后建立頁表映射關系,vma是文件映射則會從磁盤讀取對應的文件頁(如果page cache沒有對應頁面時)到內(nèi)存的page cache,然后建立虛擬頁面建立頁表映射關系。
二、內(nèi)存回收處理
1. 掃描活躍的lru鏈表
內(nèi)存回收掃描活躍的lru鏈表時,對于設定了VM_LOCKED的vma處理鏈路如下:

可以看到:當掃描活躍的lru鏈表的時候,會通過反向映射機制查找到映射這個物理頁面的每個vma, 對于設置了vma->vm_flags 的VM_LOCKED標志的vma來說直接退出反向映射處理即可,不需要進行訪問計數(shù)的統(tǒng)計工作,本身這樣的物理頁面就需要常駐內(nèi)存不要進行回收。
2.掃描不活躍的lru鏈表
內(nèi)存回收掃描不活躍的lru鏈表時,對于設定了VM_LOCKED的vma處理鏈路如下:

可以看到:調(diào)用鏈中也會調(diào)用page_referenced 函數(shù)通過反向映射機制查找到映射這個物理頁面的每個vma, 對于設置了vma->vm_flags 的VM_LOCKED標志的vma來說直接退出反向映射處理即可,返回到page_check_references函數(shù)時,判斷如果有vma設置了VM_LOCKED標志就會返回PAGEREF_RECLAIM到shrink_page_list函數(shù)接著處理。 shrink_page_list函數(shù)在處理完page_check_references之后,就進行回收處理,對于頁表映射頁會調(diào)用try_to_unmap來解除頁表映射。
3.反向映射處理
shrink_page_list在回收物理頁面之前會調(diào)用try_to_unmap來解除映射到這個頁面所有頁表項,相關處理如下:

對于映射到這個物理頁的每個vma來說,如果vma->vm_flags設置了VM_LOCKED標志,則會調(diào)用mlock_vma_page來做mlock處理,然后返回false,結束反向映射處理。 下面我們來看mlock_vma_page做了什么事情:

可以看到:mlock_vma_page首先設置頁描述符的PG_mlocked標志,然后會zone的NR_MLOCK頁面記賬,然后會將頁面從原來的lru鏈表中隔離出來,最后會將頁面加入不可回收的lru中(這個代碼大家自行閱讀,實際上是判斷頁描述符的PG_mlocked標志)。
mlock_vma_page處理的重點就是將頁面加入到不可回收的lru鏈表,這樣內(nèi)存回收的時候就不會在掃描到這樣的頁面了。
mlock的整個過程如下圖所示:

三、munlock處理
munlock會解除原來鎖住的頁面,處理路徑如下:

當然代碼中也會有對應的vma的分裂處理,主要處理為:清除vma的VM_LOCKED標志,清除頁描述符的PG_mlocked標志,最后就會將原來在不可回收的lru中的頁面重新加入對應的lru鏈表中。 這里還有一個細節(jié),那就是有可能這個頁面對多個vma共享,所以會通過try_to_munlock來處理,處理路徑如下:

會通過反向映射機制,遍歷這樣頁對應的所有vma,如果傳遞的ttu_flags為TTU_MUNLOCK且vma->vm_flags沒有設置VM_LOCKED標志,則直接返回,檢查下一個vma;如果有一個vma設置了VM_LOCKED標志,說明這個頁面還不能被回收,就會通過mlock_vma_page函數(shù)重新將頁面加入到不可回收的lru鏈表。 munlock的整個處理過程如下圖:

四、總結
對于一些對時間有嚴格要求的應用場景,訪問時按需分配和調(diào)頁機制的時延可能是未知的,內(nèi)核中提供了mlock相關的系統(tǒng)調(diào)用,用于將虛擬內(nèi)存區(qū)域?qū)奈锢眄撁妗版i在”內(nèi)存中。內(nèi)核對應mlock鎖住的頁面實際上它主要做了兩步比較重要的操作:1,調(diào)用mlock的時候就將所需要的物理頁面準備好;2,內(nèi)存回收時當掃描到相關的物理頁面時,將其放入不可回收的lru鏈表。第一步保證訪問的虛擬地址對應的物理頁面在內(nèi)存中,第二步保證了鎖住的頁面不會被回收。
-
ARM
+關注
關注
135文章
9538瀏覽量
390337 -
內(nèi)存
+關注
關注
9文章
3185瀏覽量
76242
原文標題:mlock鎖原理剖析
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
keil中c語言的動態(tài)分配內(nèi)存
【「Linux 設備驅(qū)動開發(fā)(第 2 版)」閱讀體驗】+讀深入理解Linux內(nèi)核內(nèi)存分配
進程概念和特征
進程通信
進程的控制
CW32F030片上FLASH閃存存儲器物理區(qū)域的劃分
解析Linux的進程、線程和協(xié)程
rk基于linux/android內(nèi)存管理
mlock如何鎖住進程地址空間關聯(lián)的物理內(nèi)存
評論