提交 0ebba54c 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

鸿蒙内核源码分析系列篇 https://blog.csdn.net/kuangyufei

上级 213c8c47
...@@ -171,10 +171,10 @@ typedef struct VmSpace { ...@@ -171,10 +171,10 @@ typedef struct VmSpace {
#define VM_MAP_REGION_FLAG_FLAG_MASK (3<<7) //掩码用途 #define VM_MAP_REGION_FLAG_FLAG_MASK (3<<7) //掩码用途
#define VM_MAP_REGION_FLAG_STACK (1<<9) //栈区 #define VM_MAP_REGION_FLAG_STACK (1<<9) //栈区
#define VM_MAP_REGION_FLAG_HEAP (1<<10) //堆区 #define VM_MAP_REGION_FLAG_HEAP (1<<10) //堆区
#define VM_MAP_REGION_FLAG_DATA (1<<11) //数据区 #define VM_MAP_REGION_FLAG_DATA (1<<11) //data数据区 编译在ELF中
#define VM_MAP_REGION_FLAG_TEXT (1<<12) //代码区 #define VM_MAP_REGION_FLAG_TEXT (1<<12) //代码区
#define VM_MAP_REGION_FLAG_BSS (1<<13) //bbs数据区 #define VM_MAP_REGION_FLAG_BSS (1<<13) //bbs数据区 由运行时动态分配
#define VM_MAP_REGION_FLAG_VDSO (1<<14) //映射区 #define VM_MAP_REGION_FLAG_VDSO (1<<14) //虚拟动态链接对象(Virtual Dynamically Shared Object、vDSO
#define VM_MAP_REGION_FLAG_MMAP (1<<15) //映射区 #define VM_MAP_REGION_FLAG_MMAP (1<<15) //映射区
#define VM_MAP_REGION_FLAG_SHM (1<<16) //共享内存区 #define VM_MAP_REGION_FLAG_SHM (1<<16) //共享内存区
#define VM_MAP_REGION_FLAG_INVALID (1<<17) /* indicates that flags are not specified */ #define VM_MAP_REGION_FLAG_INVALID (1<<17) /* indicates that flags are not specified */
...@@ -224,7 +224,7 @@ STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly(LosVmMapRegion* region) ...@@ -224,7 +224,7 @@ STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly(LosVmMapRegion* region)
return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) == return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) ==
(VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ)); (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ));
} }
//私有线性区 //是否为私有线性区
STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly(LosVmMapRegion* region) STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly(LosVmMapRegion* region)
{ {
return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE); return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE);
...@@ -234,33 +234,33 @@ STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion* region) ...@@ -234,33 +234,33 @@ STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion* region)
{ {
region->regionType = VM_MAP_REGION_TYPE_FILE; region->regionType = VM_MAP_REGION_TYPE_FILE;
} }
//是否为设备映射线性区
STATIC INLINE BOOL LOS_IsRegionTypeDev(LosVmMapRegion* region) STATIC INLINE BOOL LOS_IsRegionTypeDev(LosVmMapRegion* region)
{ {
return region->regionType == VM_MAP_REGION_TYPE_DEV; return region->regionType == VM_MAP_REGION_TYPE_DEV;
} }
//设为设备映射线性区
STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion* region) STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion* region)
{ {
region->regionType = VM_MAP_REGION_TYPE_DEV; region->regionType = VM_MAP_REGION_TYPE_DEV;
} }
//是否为匿名swap映射线性区
STATIC INLINE BOOL LOS_IsRegionTypeAnon(LosVmMapRegion* region) STATIC INLINE BOOL LOS_IsRegionTypeAnon(LosVmMapRegion* region)
{ {
return region->regionType == VM_MAP_REGION_TYPE_ANON; return region->regionType == VM_MAP_REGION_TYPE_ANON;
} }
//设为匿名swap映射线性区
STATIC INLINE VOID LOS_SetRegionTypeAnon(LosVmMapRegion* region) STATIC INLINE VOID LOS_SetRegionTypeAnon(LosVmMapRegion* region)
{ {
region->regionType = VM_MAP_REGION_TYPE_ANON; region->regionType = VM_MAP_REGION_TYPE_ANON;
} }
//虚拟地址是否在用户空间
STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr) STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
{ {
return ((vaddr >= USER_ASPACE_BASE) && return ((vaddr >= USER_ASPACE_BASE) &&
(vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1)))); (vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1))));
} }
//从vaddr 到 vaddr + len 这段虚拟地址是否在用户空间
STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len) STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len)
{ {
return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1)); return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1));
......
...@@ -54,8 +54,8 @@ typedef struct VmPage { ...@@ -54,8 +54,8 @@ typedef struct VmPage {
UINT16 nPages; /**< the vm page is used for kernel heap */ UINT16 nPages; /**< the vm page is used for kernel heap */
} LosVmPage; } LosVmPage;
extern LosVmPage *g_vmPageArray;//物理内存所有页记录数组 extern LosVmPage *g_vmPageArray;//物理内存所有页框(page frame)记录数组
extern size_t g_vmPageArraySize;//物理内存总页数 extern size_t g_vmPageArraySize;//物理内存总页框(page frame)
LosVmPage *LOS_VmPageGet(PADDR_T paddr); LosVmPage *LOS_VmPageGet(PADDR_T paddr);
VOID OsVmPageStartup(VOID); VOID OsVmPageStartup(VOID);
......
...@@ -52,12 +52,12 @@ extern "C" { ...@@ -52,12 +52,12 @@ extern "C" {
#define VM_PAGE_TO_PHYS(page) (page->physAddr)//获取页面物理地址 #define VM_PAGE_TO_PHYS(page) (page->physAddr)//获取页面物理地址
#define VM_ORDER_TO_PAGES(order) (1 << (order))//伙伴算法由order 定位到该块组的页面单位,例如:order=2时,page[4] #define VM_ORDER_TO_PAGES(order) (1 << (order))//伙伴算法由order 定位到该块组的页面单位,例如:order=2时,page[4]
#define VM_ORDER_TO_PHYS(order) (1 << (PAGE_SHIFT + (order)))//通过order找物理地址 #define VM_ORDER_TO_PHYS(order) (1 << (PAGE_SHIFT + (order)))//跳块例如 order=2 就是跳4页
#define VM_PHYS_TO_ORDER(phys) (min(LOS_LowBitGet((phys) >> PAGE_SHIFT), VM_LIST_ORDER_MAX - 1))//通过物理地址定位到order #define VM_PHYS_TO_ORDER(phys) (min(LOS_LowBitGet((phys) >> PAGE_SHIFT), VM_LIST_ORDER_MAX - 1))//通过物理地址定位到order
struct VmFreeList { struct VmFreeList {
LOS_DL_LIST node; LOS_DL_LIST node; //双循环链表
UINT32 listCnt; UINT32 listCnt; //双循环链表节点总数
}; };
//针对匿名页和文件页各拆分成一个活跃,一个不活跃的链表。 //针对匿名页和文件页各拆分成一个活跃,一个不活跃的链表。
enum OsLruList { enum OsLruList {
......
...@@ -1561,7 +1561,7 @@ STATIC INLINE INT32 OsMemPoolExpand(VOID *pool, UINT32 size, UINT32 intSave) ...@@ -1561,7 +1561,7 @@ STATIC INLINE INT32 OsMemPoolExpand(VOID *pool, UINT32 size, UINT32 intSave)
endNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, poolInfo->poolSize); endNode = (LosMemDynNode *)OS_MEM_END_NODE(pool, poolInfo->poolSize);
RETRY: RETRY:
newNode = (LosMemDynNode *)LOS_PhysPagesAllocContiguous(size >> PAGE_SHIFT); newNode = (LosMemDynNode *)LOS_PhysPagesAllocContiguous(size >> PAGE_SHIFT);//分配连续的物理内存
if (newNode == NULL) { if (newNode == NULL) {
if (tryCount > 0) { if (tryCount > 0) {
tryCount--; tryCount--;
......
...@@ -44,9 +44,9 @@ extern "C" { ...@@ -44,9 +44,9 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* __cplusplus */ #endif /* __cplusplus */
UINTPTR g_vmBootMemBase = (UINTPTR)&__bss_end;//内核空间 UINTPTR g_vmBootMemBase = (UINTPTR)&__bss_end;//内核空间可用于分配的区域
BOOL g_kHeapInited = FALSE;//内核堆区初始化变量 BOOL g_kHeapInited = FALSE;//内核堆区初始化变量
//虚拟内存区间检查, 需理解 los_vm_zone.h 中画出的鸿蒙虚拟内存全景图
UINT32 OsVmAddrCheck(size_t tempAddr, size_t length) UINT32 OsVmAddrCheck(size_t tempAddr, size_t length)
{ {
if ((tempAddr >= KERNEL_VMM_BASE) && ((tempAddr + length) <= (PERIPH_UNCACHED_BASE + PERIPH_UNCACHED_SIZE))) { if ((tempAddr >= KERNEL_VMM_BASE) && ((tempAddr + length) <= (PERIPH_UNCACHED_BASE + PERIPH_UNCACHED_SIZE))) {
...@@ -60,7 +60,7 @@ VOID *OsVmBootMemAlloc(size_t len) ...@@ -60,7 +60,7 @@ VOID *OsVmBootMemAlloc(size_t len)
{ {
UINTPTR ptr; UINTPTR ptr;
if (g_kHeapInited) {//g_kHeapInited 在什么时候会变成 true?没找到代码 if (g_kHeapInited) {// ??? g_kHeapInited 在什么时候会变成 true,没找到代码
VM_ERR("kernel heap has been inited, should not to use boot mem alloc!"); VM_ERR("kernel heap has been inited, should not to use boot mem alloc!");
return NULL; return NULL;
} }
......
...@@ -94,8 +94,8 @@ LosVmPage *LOS_VmPageGet(PADDR_T paddr) ...@@ -94,8 +94,8 @@ LosVmPage *LOS_VmPageGet(PADDR_T paddr)
INT32 segID; INT32 segID;
LosVmPage *page = NULL; LosVmPage *page = NULL;
for (segID = 0; segID < g_vmPhysSegNum; segID++) { for (segID = 0; segID < g_vmPhysSegNum; segID++) {//物理内存采用段页管理
page = OsVmPhysToPage(paddr, segID); page = OsVmPhysToPage(paddr, segID);//通过物理地址和段ID找出物理页框
if (page != NULL) { if (page != NULL) {
break; break;
} }
......
...@@ -45,35 +45,35 @@ extern "C" { ...@@ -45,35 +45,35 @@ extern "C" {
#define ONE_PAGE 1 #define ONE_PAGE 1
/* Physical memory area array */ /* Physical memory area array */
STATIC struct VmPhysArea g_physArea[] = { STATIC struct VmPhysArea g_physArea[] = {//这里只整了一个区域,即只生成一个段,鸿蒙物理内存采用段页式管理
{ {
.start = SYS_MEM_BASE, //整个物理内存基地址 .start = SYS_MEM_BASE, //整个物理内存基地址
.size = SYS_MEM_SIZE_DEFAULT,//整个物理内存总大小 .size = SYS_MEM_SIZE_DEFAULT,//整个物理内存总大小
}, },
}; };
struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX];//32段 struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX];//最大32段
INT32 g_vmPhysSegNum = 0; INT32 g_vmPhysSegNum = 0; //段数
//获取段数组,全局变量,变量放在 .bbs 区
LosVmPhysSeg *OsGVmPhysSegGet() LosVmPhysSeg *OsGVmPhysSegGet()
{ {
return g_vmPhysSeg; return g_vmPhysSeg;
} }
//初始化Lru置换 LRU list 在 VmPhysSeg中管理
STATIC VOID OsVmPhysLruInit(struct VmPhysSeg *seg) STATIC VOID OsVmPhysLruInit(struct VmPhysSeg *seg)
{ {
INT32 i; INT32 i;
UINT32 intSave; UINT32 intSave;
LOS_SpinInit(&seg->lruLock); LOS_SpinInit(&seg->lruLock);//自旋锁,自旋锁用户CPU多核同步
LOS_SpinLockSave(&seg->lruLock, &intSave); LOS_SpinLockSave(&seg->lruLock, &intSave);
for (i = 0; i < VM_NR_LRU_LISTS; i++) { for (i = 0; i < VM_NR_LRU_LISTS; i++) { //五个双循环链表
seg->lruSize[i] = 0; seg->lruSize[i] = 0; //记录链表节点数
LOS_ListInit(&seg->lruList[i]); LOS_ListInit(&seg->lruList[i]);//初始化LRU链表
} }
LOS_SpinUnlockRestore(&seg->lruLock, intSave); LOS_SpinUnlockRestore(&seg->lruLock, intSave);
} }
//创建物理段
STATIC INT32 OsVmPhysSegCreate(paddr_t start, size_t size) STATIC INT32 OsVmPhysSegCreate(paddr_t start, size_t size)
{ {
struct VmPhysSeg *seg = NULL; struct VmPhysSeg *seg = NULL;
...@@ -98,14 +98,14 @@ VOID OsVmPhysSegAdd(VOID) ...@@ -98,14 +98,14 @@ VOID OsVmPhysSegAdd(VOID)
LOS_ASSERT(g_vmPhysSegNum <= VM_PHYS_SEG_MAX); LOS_ASSERT(g_vmPhysSegNum <= VM_PHYS_SEG_MAX);
for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) { for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) {//将g_physArea转化成段
ret = OsVmPhysSegCreate(g_physArea[i].start, g_physArea[i].size);//一个区对应一个段 ret = OsVmPhysSegCreate(g_physArea[i].start, g_physArea[i].size);//一个区对应一个段
if (ret != 0) { if (ret != 0) {
VM_ERR("create phys seg failed"); VM_ERR("create phys seg failed");
} }
} }
} }
//段区域大小调整
VOID OsVmPhysAreaSizeAdjust(size_t size) VOID OsVmPhysAreaSizeAdjust(size_t size)
{ {
INT32 i; INT32 i;
...@@ -127,24 +127,24 @@ UINT32 OsVmPhysPageNumGet(VOID) ...@@ -127,24 +127,24 @@ UINT32 OsVmPhysPageNumGet(VOID)
return nPages; return nPages;
} }
//初始化空闲链表,分配页框使用伙伴算法
STATIC INLINE VOID OsVmPhysFreeListInit(struct VmPhysSeg *seg) STATIC INLINE VOID OsVmPhysFreeListInit(struct VmPhysSeg *seg)
{ {
int i; int i;
UINT32 intSave; UINT32 intSave;
struct VmFreeList *list = NULL; struct VmFreeList *list = NULL;
LOS_SpinInit(&seg->freeListLock); LOS_SpinInit(&seg->freeListLock);//自旋锁
LOS_SpinLockSave(&seg->freeListLock, &intSave); LOS_SpinLockSave(&seg->freeListLock, &intSave);
for (i = 0; i < VM_LIST_ORDER_MAX; i++) { for (i = 0; i < VM_LIST_ORDER_MAX; i++) {
list = &seg->freeList[i]; list = &seg->freeList[i];
LOS_ListInit(&list->node); LOS_ListInit(&list->node);//初始化9个链表 2|0,2|1,2|2 分配页框 |代表次方的意思
list->listCnt = 0; list->listCnt = 0;
} }
LOS_SpinUnlockRestore(&seg->freeListLock, intSave); LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
} }
//段初始化
VOID OsVmPhysInit(VOID) VOID OsVmPhysInit(VOID)
{ {
struct VmPhysSeg *seg = NULL; struct VmPhysSeg *seg = NULL;
...@@ -153,13 +153,13 @@ VOID OsVmPhysInit(VOID) ...@@ -153,13 +153,13 @@ VOID OsVmPhysInit(VOID)
for (i = 0; i < g_vmPhysSegNum; i++) { for (i = 0; i < g_vmPhysSegNum; i++) {
seg = &g_vmPhysSeg[i]; seg = &g_vmPhysSeg[i];
seg->pageBase = &g_vmPageArray[nPages]; seg->pageBase = &g_vmPageArray[nPages];//
nPages += seg->size >> PAGE_SHIFT; nPages += seg->size >> PAGE_SHIFT;//偏移12位,因以页管理,本段总页数
OsVmPhysFreeListInit(seg); OsVmPhysFreeListInit(seg); //初始化空闲链表,分配页框使用伙伴算法
OsVmPhysLruInit(seg); OsVmPhysLruInit(seg); //初始化LRU置换链表
} }
} }
//将页框挂入空闲链表,供分配
STATIC VOID OsVmPhysFreeListAdd(LosVmPage *page, UINT8 order) STATIC VOID OsVmPhysFreeListAdd(LosVmPage *page, UINT8 order)
{ {
struct VmPhysSeg *seg = NULL; struct VmPhysSeg *seg = NULL;
...@@ -169,12 +169,12 @@ STATIC VOID OsVmPhysFreeListAdd(LosVmPage *page, UINT8 order) ...@@ -169,12 +169,12 @@ STATIC VOID OsVmPhysFreeListAdd(LosVmPage *page, UINT8 order)
LOS_Panic("The page segment id(%d) is invalid\n", page->segID); LOS_Panic("The page segment id(%d) is invalid\n", page->segID);
} }
page->order = order; page->order = order;// page记录 块组号
seg = &g_vmPhysSeg[page->segID]; seg = &g_vmPhysSeg[page->segID];//先找到所属段
list = &seg->freeList[order]; list = &seg->freeList[order];//找到对应List
LOS_ListTailInsert(&list->node, &page->node); LOS_ListTailInsert(&list->node, &page->node);//将page节点挂入链表
list->listCnt++; list->listCnt++;//链表内的节点总数++
} }
STATIC VOID OsVmPhysFreeListAddUnsafe(LosVmPage *page, UINT8 order) STATIC VOID OsVmPhysFreeListAddUnsafe(LosVmPage *page, UINT8 order)
...@@ -264,23 +264,23 @@ VOID *OsVmPageToVaddr(LosVmPage *page)// ...@@ -264,23 +264,23 @@ VOID *OsVmPageToVaddr(LosVmPage *page)//
//内核空间的vmPage是不会被置换的,所以是常驻内存,内核空间初始化mmu时就映射好了L1表 //内核空间的vmPage是不会被置换的,所以是常驻内存,内核空间初始化mmu时就映射好了L1表
return (VOID *)(UINTPTR)vaddr; return (VOID *)(UINTPTR)vaddr;
} }
//通过虚拟地址找映射的物理页框
LosVmPage *OsVmVaddrToPage(VOID *ptr) LosVmPage *OsVmVaddrToPage(VOID *ptr)
{ {
struct VmPhysSeg *seg = NULL; struct VmPhysSeg *seg = NULL;
PADDR_T pa = LOS_PaddrQuery(ptr); PADDR_T pa = LOS_PaddrQuery(ptr);//通过虚拟地址查询物理地址
UINT32 segID; UINT32 segID;
for (segID = 0; segID < g_vmPhysSegNum; segID++) { for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID]; seg = &g_vmPhysSeg[segID];
if ((pa >= seg->start) && (pa < (seg->start + seg->size))) { if ((pa >= seg->start) && (pa < (seg->start + seg->size))) {
return seg->pageBase + ((pa - seg->start) >> PAGE_SHIFT); return seg->pageBase + ((pa - seg->start) >> PAGE_SHIFT);//段基地址+页偏移索引 得到虚拟地址经映射所在物理页框
} }
} }
return NULL; return NULL;
} }
//从段中分配指定页框数
LosVmPage *OsVmPhysPagesAlloc(struct VmPhysSeg *seg, size_t nPages) LosVmPage *OsVmPhysPagesAlloc(struct VmPhysSeg *seg, size_t nPages)
{ {
struct VmFreeList *list = NULL; struct VmFreeList *list = NULL;
...@@ -293,7 +293,7 @@ LosVmPage *OsVmPhysPagesAlloc(struct VmPhysSeg *seg, size_t nPages) ...@@ -293,7 +293,7 @@ LosVmPage *OsVmPhysPagesAlloc(struct VmPhysSeg *seg, size_t nPages)
} }
order = OsVmPagesToOrder(nPages);//根据页数计算出用哪个块组 order = OsVmPagesToOrder(nPages);//根据页数计算出用哪个块组
if (order < VM_LIST_ORDER_MAX) { if (order < VM_LIST_ORDER_MAX) {//order不能大于9 即:256*4K = 1M 可理解为向内核堆申请内存一次不能超过1M
for (newOrder = order; newOrder < VM_LIST_ORDER_MAX; newOrder++) {//没有就找更大块 for (newOrder = order; newOrder < VM_LIST_ORDER_MAX; newOrder++) {//没有就找更大块
list = &seg->freeList[newOrder];//从最合适的块处开始找 list = &seg->freeList[newOrder];//从最合适的块处开始找
if (LOS_ListEmpty(&list->node)) {//没找到 if (LOS_ListEmpty(&list->node)) {//没找到
...@@ -309,7 +309,7 @@ DONE: ...@@ -309,7 +309,7 @@ DONE:
OsVmPhysPagesSpiltUnsafe(page, order, newOrder); OsVmPhysPagesSpiltUnsafe(page, order, newOrder);
return page; return page;
} }
//释放物理页,所谓释放物理页就是把页挂到空闲链表中
VOID OsVmPhysPagesFree(LosVmPage *page, UINT8 order) VOID OsVmPhysPagesFree(LosVmPage *page, UINT8 order)
{ {
paddr_t pa; paddr_t pa;
...@@ -320,14 +320,14 @@ VOID OsVmPhysPagesFree(LosVmPage *page, UINT8 order) ...@@ -320,14 +320,14 @@ VOID OsVmPhysPagesFree(LosVmPage *page, UINT8 order)
} }
if (order < VM_LIST_ORDER_MAX - 1) {//order[0,7] if (order < VM_LIST_ORDER_MAX - 1) {//order[0,7]
pa = VM_PAGE_TO_PHYS(page); pa = VM_PAGE_TO_PHYS(page);//获取物理地址
do { do {
pa ^= VM_ORDER_TO_PHYS(order); pa ^= VM_ORDER_TO_PHYS(order);//注意这里是高位和低位的^=,也就是说跳到 order块组 物理地址处,此处处理甚妙!
buddyPage = OsVmPhysToPage(pa, page->segID); buddyPage = OsVmPhysToPage(pa, page->segID);//如此就能拿到以2的order次方跳的buddyPage
if ((buddyPage == NULL) || (buddyPage->order != order)) { if ((buddyPage == NULL) || (buddyPage->order != order)) {
break; break;
} }
OsVmPhysFreeListDel(buddyPage); OsVmPhysFreeListDel(buddyPage);//注意buddypage是连续的物理页框 例如order=2时,连续的4页就是一个块组 |_|_|_|_|
order++; order++;
pa &= ~(VM_ORDER_TO_PHYS(order) - 1); pa &= ~(VM_ORDER_TO_PHYS(order) - 1);
page = OsVmPhysToPage(pa, page->segID); page = OsVmPhysToPage(pa, page->segID);
...@@ -363,7 +363,7 @@ VOID OsVmPhysPagesFreeContiguous(LosVmPage *page, size_t nPages) ...@@ -363,7 +363,7 @@ VOID OsVmPhysPagesFreeContiguous(LosVmPage *page, size_t nPages)
page += n; page += n;
} }
} }
//获取一定数量的页框
STATIC LosVmPage *OsVmPhysPagesGet(size_t nPages) STATIC LosVmPage *OsVmPhysPagesGet(size_t nPages)
{ {
UINT32 intSave; UINT32 intSave;
...@@ -378,11 +378,11 @@ STATIC LosVmPage *OsVmPhysPagesGet(size_t nPages) ...@@ -378,11 +378,11 @@ STATIC LosVmPage *OsVmPhysPagesGet(size_t nPages)
for (segID = 0; segID < g_vmPhysSegNum; segID++) { for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID]; seg = &g_vmPhysSeg[segID];
LOS_SpinLockSave(&seg->freeListLock, &intSave); LOS_SpinLockSave(&seg->freeListLock, &intSave);
page = OsVmPhysPagesAlloc(seg, nPages); page = OsVmPhysPagesAlloc(seg, nPages);//分配指定页数的物理页, 可分析出 nPages 不能大于 256个
if (page != NULL) { if (page != NULL) {
/* */ /* */
LOS_AtomicSet(&page->refCounts, 0);//设置引用次数为0 LOS_AtomicSet(&page->refCounts, 0);//设置引用次数为0
page->nPages = nPages; page->nPages = nPages;//页数
LOS_SpinUnlockRestore(&seg->freeListLock, intSave); LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
return page; return page;
} }
...@@ -398,7 +398,7 @@ VOID *LOS_PhysPagesAllocContiguous(size_t nPages) ...@@ -398,7 +398,7 @@ VOID *LOS_PhysPagesAllocContiguous(size_t nPages)
if (nPages == 0) { if (nPages == 0) {
return NULL; return NULL;
} }
//鸿蒙 nPages 不能大于 2的8 次方,即256个页,1M内存,仅限于内核态,用户态不限制分配大小.
page = OsVmPhysPagesGet(nPages);//通过伙伴算法获取物理上连续的页 page = OsVmPhysPagesGet(nPages);//通过伙伴算法获取物理上连续的页
if (page == NULL) { if (page == NULL) {
return NULL; return NULL;
...@@ -542,7 +542,7 @@ struct VmPhysSeg *OsVmPhysSegGet(LosVmPage *page) ...@@ -542,7 +542,7 @@ struct VmPhysSeg *OsVmPhysSegGet(LosVmPage *page)
return (OsGVmPhysSegGet() + page->segID); return (OsGVmPhysSegGet() + page->segID);
} }
//通过总页数 ,获取块组 ,例如需要分配 8个页,返回就是 3 ,例如 1023个 返回就是 10
UINT32 OsVmPagesToOrder(size_t nPages) UINT32 OsVmPagesToOrder(size_t nPages)
{ {
UINT32 order; UINT32 order;
......
...@@ -5,6 +5,8 @@ typedef unsigned long PTE_T; ...@@ -5,6 +5,8 @@ typedef unsigned long PTE_T;
typedef unsigned long VADDR_T; typedef unsigned long VADDR_T;
#define IS_ALIGNED(a, b) (!(((UINTPTR)(a)) & (((UINTPTR)(b)) - 1))) #define IS_ALIGNED(a, b) (!(((UINTPTR)(a)) & (((UINTPTR)(b)) - 1)))
//鸿蒙内核源码分析系列篇 https://blog.csdn.net/kuangyufei
void b(){ void b(){
UINT8 w[3]={0}; UINT8 w[3]={0};
PTE_T pte1BasePtr = 0x11100000; PTE_T pte1BasePtr = 0x11100000;
......
git add -A
git commit -m "鸿蒙内核源码分析系列篇 https://blog.csdn.net/kuangyufei"
git push
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册