摘要:本文介紹了OpenHarmony鴻蒙輕內核LiteOS-A的虛擬地址空間編號知識,詳細分析進程空間編號的申請與釋放操作。
本文分享自華為雲社區《鴻蒙輕內核A核源碼分析系列四 (1) 虛擬內存進程空間編號》,作者: zhushy 。
在熟悉下OpenHarmony鴻蒙輕內核提供的虛擬內存(Virtual memory)管理模塊之前,作為預備基礎知識,我們先了解下虛擬內存進程空間編號,進程空間編號功能相對獨立,源代碼文件單獨維護。涉及的頭文件和C源代碼文件分別為arch/arm/arm/include/los_asid.h和arch/arm/arm/src/los_asid.c。本文先介紹OpenHarmony鴻蒙輕內核LiteOS-A的虛擬地址空間編號知識,然后詳細分析進程空間編號的申請與釋放操作。
1. 地址空間編號數組
虛擬內存地址空間編號取值范圍為[0,255],256個編號對應8位數值。為了記錄256個進程地址空間編號的使用狀態需要256個比特位來維護。下述代碼中位圖字數BITMAP_NUM_WORDS(1UL << MMU_ARM_ASID_BITS)等於8,即地址空間編號數組的大小為8,每個位圖字32位,正好對應256個比特位。
#define MMU_ARM_ASID_BITS 8 ...... STATIC UINTPTR g_asidPool[BITMAP_NUM_WORDS(1UL << MMU_ARM_ASID_BITS)];
2. 函數OsAllocAsid()
函數OsAllocAsid()用於分配一個地址空間編號,輸出參數UINT32 *asid記錄獲取的地址空間編號,獲取失敗時返回值為-1;獲取地址空間編號成功時返回LOS_OK。⑴處語句獲取g_asidPool數組元素中二進制位數值從左到右第一處為0的位數。⑵處如果獲取的位數大於等於0,小於256,沒有越界,說明獲取地址空間編號成功。執行⑶把該bit位設置為1,標記為已使用。⑷處設置獲取的地址空間編號。
status_t OsAllocAsid(UINT32 *asid) { UINT32 flags; LOS_SpinLockSave(&g_cpuAsidLock, &flags); ⑴ UINT32 firstZeroBit = LOS_BitmapFfz(g_asidPool, 1UL << MMU_ARM_ASID_BITS); ⑵ if (firstZeroBit >= 0 && firstZeroBit < (1UL << MMU_ARM_ASID_BITS)) { ⑶ LOS_BitmapSetNBits(g_asidPool, firstZeroBit, 1); ⑷ *asid = firstZeroBit; LOS_SpinUnlockRestore(&g_cpuAsidLock, flags); return LOS_OK; } LOS_SpinUnlockRestore(&g_cpuAsidLock, flags); return firstZeroBit; }
3. 函數OsFreeAsid
函數OsFreeAsid釋放地址空間編號,代碼比較簡單調用LOS_BitmapClrNBits()把地址編號所在的bit位清0即可。
VOID OsFreeAsid(UINT32 asid) { UINT32 flags; LOS_SpinLockSave(&g_cpuAsidLock, &flags); LOS_BitmapClrNBits(g_asidPool, asid, 1); LOS_SpinUnlockRestore(&g_cpuAsidLock, flags); }
總結
本文首先介紹了OpenHarmony鴻蒙輕內核LiteOS-A的虛擬地址空間編號知識,然后詳細分析進程空間編號的申請與釋放操作。