更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_vm_phys.h 文件参考

浏览源代码.

结构体

struct  VmFreeList
 
struct  VmPhysSeg
 物理段描述符 更多...
 
struct  VmPhysArea
 物理区描述,仅用于方案商配置范围使用 更多...
 

类型定义

typedef struct VmPhysSeg LosVmPhysSeg
 物理段描述符 更多...
 

枚举

enum  OsLruList {
  VM_LRU_INACTIVE_ANON = 0 , VM_LRU_ACTIVE_ANON , VM_LRU_INACTIVE_FILE , VM_LRU_ACTIVE_FILE ,
  VM_LRU_UNEVICTABLE , VM_NR_LRU_LISTS
}
 Lru全称是Least Recently Used,即最近最久未使用的意思 针对匿名页和文件页各拆成对应链表。 更多...
 

函数

UINT32 OsVmPagesToOrder (size_t nPages)
 获取参数nPages对应的块组,例如 7 -> 2^3 返回 3 更多...
 
struct VmPhysSegOsVmPhysSegGet (LosVmPage *page)
 获取物理页框所在段 更多...
 
LosVmPhysSegOsGVmPhysSegGet (VOID)
 
VOID * OsVmPageToVaddr (LosVmPage *page)
 通过page获取内核空间的虚拟地址 参考OsArchMmuInit
#define SYS_MEM_BASE DDR_MEM_ADDR /* physical memory base 物理地址的起始地址 * /
本函数非常重要,通过一个物理地址找到内核虚拟地址
内核静态映射:提升虚实转化效率,段映射减少页表项 更多...
 
VOID OsVmPhysSegAdd (VOID)
 添加物理段 更多...
 
VOID OsVmPhysInit (VOID)
 物理段初始化 更多...
 
VOID OsVmPhysAreaSizeAdjust (size_t size)
 段区域大小调整 更多...
 
UINT32 OsVmPhysPageNumGet (VOID)
 获得物理内存的总页数 更多...
 
LosVmPageOsVmVaddrToPage (VOID *ptr)
 通过虚拟地址找映射的物理页框 更多...
 
VOID OsPhysSharePageCopy (PADDR_T oldPaddr, PADDR_T *newPaddr, LosVmPage *newPage)
 拷贝共享页面 更多...
 
VOID OsVmPhysPagesFreeContiguous (LosVmPage *page, size_t nPages)
 连续的释放物理页框, 如果8页连在一块是一起释放的 更多...
 
LosVmPageOsVmPhysToPage (paddr_t pa, UINT8 segID)
 通过物理地址获取所属参数段的物理页框 更多...
 
LosVmPageOsVmPaddrToPage (paddr_t paddr)
 
LosVmPageLOS_PhysPageAlloc (VOID)
 申请一个物理页 更多...
 
VOID LOS_PhysPageFree (LosVmPage *page)
 释放一个物理页框 更多...
 
size_t LOS_PhysPagesAlloc (size_t nPages, LOS_DL_LIST *list)
 LOS_PhysPagesAlloc 分配nPages页个物理页框,并将页框挂入list
返回已分配的页面大小,不负责一定能分配到nPages的页框
更多...
 
size_t LOS_PhysPagesFree (LOS_DL_LIST *list)
 释放双链表中的所有节点内存,本质是回归到伙伴orderlist中 更多...
 
VOID * LOS_PhysPagesAllocContiguous (size_t nPages)
 分配连续的物理页 更多...
 
VOID LOS_PhysPagesFreeContiguous (VOID *ptr, size_t nPages)
 释放指定页数地址连续的物理内存 更多...
 
VADDR_TLOS_PaddrToKVaddr (PADDR_T paddr)
 通过物理地址获取内核虚拟地址 更多...
 
PADDR_T OsKVaddrToPaddr (VADDR_T kvaddr)
 

变量

struct VmPhysSeg g_vmPhysSeg [VM_PHYS_SEG_MAX]
 物理内存采用段页式管理,先切段后伙伴算法页 更多...
 
INT32 g_vmPhysSegNum
 段总数 更多...
 

类型定义说明

◆ LosVmPhysSeg

typedef struct VmPhysSeg LosVmPhysSeg

物理段描述符

枚举类型说明

◆ OsLruList

enum OsLruList

Lru全称是Least Recently Used,即最近最久未使用的意思 针对匿名页和文件页各拆成对应链表。

枚举值
VM_LRU_INACTIVE_ANON 

非活动匿名页(swap)

VM_LRU_ACTIVE_ANON 

活动匿名页(swap)

VM_LRU_INACTIVE_FILE 

非活动文件页(磁盘)

VM_LRU_ACTIVE_FILE 

活动文件页(磁盘)

VM_LRU_UNEVICTABLE 

禁止换出的页

VM_NR_LRU_LISTS 

在文件 los_vm_phys.h74 行定义.

74 {// 页属性
75 VM_LRU_INACTIVE_ANON = 0, ///< 非活动匿名页(swap)
76 VM_LRU_ACTIVE_ANON, ///< 活动匿名页(swap)
77 VM_LRU_INACTIVE_FILE, ///< 非活动文件页(磁盘)
78 VM_LRU_ACTIVE_FILE, ///< 活动文件页(磁盘)
79 VM_LRU_UNEVICTABLE, ///< 禁止换出的页
81};
@ VM_LRU_UNEVICTABLE
禁止换出的页
Definition: los_vm_phys.h:79
@ VM_LRU_ACTIVE_ANON
活动匿名页(swap)
Definition: los_vm_phys.h:76
@ VM_NR_LRU_LISTS
Definition: los_vm_phys.h:80
@ VM_LRU_ACTIVE_FILE
活动文件页(磁盘)
Definition: los_vm_phys.h:78
@ VM_LRU_INACTIVE_FILE
非活动文件页(磁盘)
Definition: los_vm_phys.h:77
@ VM_LRU_INACTIVE_ANON
非活动匿名页(swap)
Definition: los_vm_phys.h:75

函数说明

◆ LOS_PaddrToKVaddr()

VADDR_T * LOS_PaddrToKVaddr ( PADDR_T  paddr)

通过物理地址获取内核虚拟地址

在文件 los_vm_phys.c688 行定义.

689{
690 if ((paddr < DDR_MEM_ADDR) || (paddr >= ((PADDR_T)DDR_MEM_ADDR + DDR_MEM_SIZE))) {
691 return NULL;
692 }
693
694 return (VADDR_T *)DMA_TO_VMM_ADDR(paddr);
695}
unsigned long PADDR_T
Definition: los_typedef.h:207
unsigned long VADDR_T
Definition: los_typedef.h:208
这是这个函数的调用关系图:

◆ LOS_PhysPageAlloc()

LosVmPage * LOS_PhysPageAlloc ( VOID  )

申请一个物理页

在文件 los_vm_phys.c566 行定义.

567{
568 return OsVmPhysPagesGet(ONE_PAGE);//分配一页物理页
569}
STATIC LosVmPage * OsVmPhysPagesGet(size_t nPages)
OsVmPhysPagesGet 获取一定数量的页框 LosVmPage实体是放在全局大数组中的, LosVmPage->nPages 标记了分配页数
Definition: los_vm_phys.c:455
函数调用图:
这是这个函数的调用关系图:

◆ LOS_PhysPageFree()

VOID LOS_PhysPageFree ( LosVmPage page)

释放一个物理页框

在文件 los_vm_phys.c546 行定义.

547{
548 UINT32 intSave;
549 struct VmPhysSeg *seg = NULL;
550
551 if (page == NULL) {
552 return;
553 }
554
555 if (LOS_AtomicDecRet(&page->refCounts) <= 0) {//减少引用数后不能小于0
556 seg = &g_vmPhysSeg[page->segID];
557 LOS_SpinLockSave(&seg->freeListLock, &intSave);
558
559 OsVmPhysPagesFreeContiguous(page, ONE_PAGE);//释放一页
560 LOS_AtomicSet(&page->refCounts, 0);//只要物理内存被释放了,引用数就必须得重置为 0
561
562 LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
563 }
564}
STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal)
Atomic setting.
Definition: los_atomic.h:147
STATIC INLINE INT32 LOS_AtomicDecRet(Atomic *v)
Atomic auto-decrement. | 对内存数据减1并返回运算结果
Definition: los_atomic.h:357
VOID LOS_SpinUnlockRestore(SPIN_LOCK_S *lock, UINT32 intSave)
Definition: los_spinlock.c:108
VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
Definition: los_spinlock.c:98
unsigned int UINT32
Definition: los_typedef.h:57
VOID OsVmPhysPagesFreeContiguous(LosVmPage *page, size_t nPages)
连续的释放物理页框, 如果8页连在一块是一起释放的
Definition: los_vm_phys.c:420
struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX]
最大32段
Definition: los_vm_phys.c:87
Atomic refCounts
Definition: los_vm_page.h:57
UINT8 segID
Definition: los_vm_page.h:60
物理段描述符
Definition: los_vm_phys.h:85
SPIN_LOCK_S freeListLock
Definition: los_vm_phys.h:89
函数调用图:
这是这个函数的调用关系图:

◆ LOS_PhysPagesAlloc()

size_t LOS_PhysPagesAlloc ( size_t  nPages,
LOS_DL_LIST list 
)

LOS_PhysPagesAlloc 分配nPages页个物理页框,并将页框挂入list
返回已分配的页面大小,不负责一定能分配到nPages的页框

参数
list
nPages
返回
参见

在文件 los_vm_phys.c581 行定义.

582{
583 LosVmPage *page = NULL;
584 size_t count = 0;
585
586 if ((list == NULL) || (nPages == 0)) {
587 return 0;
588 }
589
590 while (nPages--) {
591 page = OsVmPhysPagesGet(ONE_PAGE);//一页一页分配,由伙伴算法分配
592 if (page == NULL) {
593 break;
594 }
595 LOS_ListTailInsert(list, &page->node);//从参数链表list尾部挂入新页面结点
596 count++;
597 }
598
599 return count;
600}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the tail of a doubly linked list.
Definition: los_list.h:244
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
Definition: los_vm_page.h:53
LOS_DL_LIST node
Definition: los_vm_page.h:54
函数调用图:
这是这个函数的调用关系图:

◆ LOS_PhysPagesAllocContiguous()

VOID * LOS_PhysPagesAllocContiguous ( size_t  nPages)

分配连续的物理页

在文件 los_vm_phys.c478 行定义.

479{
480 LosVmPage *page = NULL;
481
482 if (nPages == 0) {
483 return NULL;
484 }
485 //鸿蒙 nPages 不能大于 2^8 次方,即256个页,1M内存,仅限于内核态,用户态不限制分配大小.
486 page = OsVmPhysPagesGet(nPages);//通过伙伴算法获取物理上连续的页
487 if (page == NULL) {
488 return NULL;
489 }
490
491 return OsVmPageToVaddr(page);//通过物理页找虚拟地址
492}
VOID * OsVmPageToVaddr(LosVmPage *page)
通过page获取内核空间的虚拟地址 参考OsArchMmuInit #define SYS_MEM_BASE DDR_MEM_ADDR /* physical memory base 物理地址的起始...
Definition: los_vm_phys.c:288
函数调用图:
这是这个函数的调用关系图:

◆ LOS_PhysPagesFree()

size_t LOS_PhysPagesFree ( LOS_DL_LIST list)

释放双链表中的所有节点内存,本质是回归到伙伴orderlist中

在文件 los_vm_phys.c661 行定义.

662{
663 UINT32 intSave;
664 LosVmPage *page = NULL;
665 LosVmPage *nPage = NULL;
666 LosVmPhysSeg *seg = NULL;
667 size_t count = 0;
668
669 if (list == NULL) {
670 return 0;
671 }
672
673 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(page, nPage, list, LosVmPage, node) {//宏循环
674 LOS_ListDelete(&page->node);//先把自己摘出去
675 if (LOS_AtomicDecRet(&page->refCounts) <= 0) {//无引用
676 seg = &g_vmPhysSeg[page->segID];//获取物理段
677 LOS_SpinLockSave(&seg->freeListLock, &intSave);//锁住freeList
678 OsVmPhysPagesFreeContiguous(page, ONE_PAGE);//连续释放,注意这里的ONE_PAGE其实有误导,让人以为是释放4K,其实是指连续的物理页框,如果3页连在一块是一起释放的.
679 LOS_AtomicSet(&page->refCounts, 0);//引用重置为0
680 LOS_SpinUnlockRestore(&seg->freeListLock, intSave);//恢复锁
681 }
682 count++;//继续取下一个node
683 }
684
685 return count;
686}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
函数调用图:
这是这个函数的调用关系图:

◆ LOS_PhysPagesFreeContiguous()

VOID LOS_PhysPagesFreeContiguous ( VOID *  ptr,
size_t  nPages 
)

释放指定页数地址连续的物理内存

在文件 los_vm_phys.c494 行定义.

495{
496 UINT32 intSave;
497 struct VmPhysSeg *seg = NULL;
498 LosVmPage *page = NULL;
499
500 if (ptr == NULL) {
501 return;
502 }
503
504 page = OsVmVaddrToPage(ptr);//通过虚拟地址找到页框
505 if (page == NULL) {
506 VM_ERR("vm page of ptr(%#x) is null", ptr);
507 return;
508 }
509 page->nPages = 0;//被分配的页数置为0,表示不被分配
510
511 seg = &g_vmPhysSeg[page->segID];
512 LOS_SpinLockSave(&seg->freeListLock, &intSave);
513
514 OsVmPhysPagesFreeContiguous(page, nPages);//具体释放实现
515
516 LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
517}
LosVmPage * OsVmVaddrToPage(VOID *ptr)
通过虚拟地址找映射的物理页框
Definition: los_vm_phys.c:295
UINT16 nPages
Definition: los_vm_page.h:61
函数调用图:
这是这个函数的调用关系图:

◆ OsGVmPhysSegGet()

LosVmPhysSeg * OsGVmPhysSegGet ( VOID  )

◆ OsKVaddrToPaddr()

PADDR_T OsKVaddrToPaddr ( VADDR_T  kvaddr)

在文件 los_vm_phys.c519 行定义.

520{
521 if (kvaddr == 0) {
522 return 0;
523 }
524 return (kvaddr - KERNEL_ASPACE_BASE + SYS_MEM_BASE);
525}
这是这个函数的调用关系图:

◆ OsPhysSharePageCopy()

VOID OsPhysSharePageCopy ( PADDR_T  oldPaddr,
PADDR_T newPaddr,
LosVmPage newPage 
)

拷贝共享页面

在文件 los_vm_phys.c602 行定义.

603{
604 UINT32 intSave;
605 LosVmPage *oldPage = NULL;
606 VOID *newMem = NULL;
607 VOID *oldMem = NULL;
608 LosVmPhysSeg *seg = NULL;
609
610 if ((newPage == NULL) || (newPaddr == NULL)) {
611 VM_ERR("new Page invalid");
612 return;
613 }
614
615 oldPage = LOS_VmPageGet(oldPaddr);//由物理地址得到页框
616 if (oldPage == NULL) {
617 VM_ERR("invalid oldPaddr %p", oldPaddr);
618 return;
619 }
620
621 seg = &g_vmPhysSeg[oldPage->segID];//拿到物理段
622 LOS_SpinLockSave(&seg->freeListLock, &intSave);
623 if (LOS_AtomicRead(&oldPage->refCounts) == 1) {//页面引用次数仅一次,说明只有一个进程在操作
624 *newPaddr = oldPaddr;//新老指向同一块物理地址
625 } else {//是个共享内存
626 newMem = LOS_PaddrToKVaddr(*newPaddr); //新页虚拟地址
627 oldMem = LOS_PaddrToKVaddr(oldPaddr); //老页虚拟地址
628 if ((newMem == NULL) || (oldMem == NULL)) {
629 LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
630 return;
631 }//请记住,在保护模式下,物理地址只能用于计算,操作(包括拷贝)需要虚拟地址!
632 if (memcpy_s(newMem, PAGE_SIZE, oldMem, PAGE_SIZE) != EOK) {//老页内容复制给新页,需操作虚拟地址,拷贝一页数据
633 VM_ERR("memcpy_s failed");
634 }
635
636 LOS_AtomicInc(&newPage->refCounts);//新页引用次数以原子方式自动减量
637 LOS_AtomicDec(&oldPage->refCounts);//老页引用次数以原子方式自动减量
638 }
639 LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
640 return;
641}
STATIC INLINE VOID LOS_AtomicInc(Atomic *v)
Atomic addSelf.
Definition: los_atomic.h:253
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
Definition: los_atomic.h:123
STATIC INLINE VOID LOS_AtomicDec(Atomic *v)
Atomic auto-decrement. | 对32bit原子数据做减1
Definition: los_atomic.h:323
LosVmPage * LOS_VmPageGet(PADDR_T paddr)
通过物理地址获取页框
Definition: los_vm_page.c:120
VADDR_T * LOS_PaddrToKVaddr(PADDR_T paddr)
通过物理地址获取内核虚拟地址
Definition: los_vm_phys.c:527
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPaddrToPage()

LosVmPage * OsVmPaddrToPage ( paddr_t  paddr)

在文件 los_vm_phys.c267 行定义.

268{
269 INT32 segID;
270 LosVmPage *vmPage = NULL;
271
272 for (segID = 0; segID < g_vmPhysSegNum; segID++) {
273 vmPage = OsVmPhysToPage(paddr, segID);
274 if (vmPage != NULL) {
275 return vmPage;
276 }
277 }
278 return NULL;
279}
signed int INT32
Definition: los_typedef.h:60
INT32 g_vmPhysSegNum
段总数
Definition: los_vm_phys.c:88
LosVmPage * OsVmPhysToPage(paddr_t pa, UINT8 segID)
通过物理地址获取所属参数段的物理页框
Definition: los_vm_phys.c:250
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPagesToOrder()

UINT32 OsVmPagesToOrder ( size_t  nPages)

获取参数nPages对应的块组,例如 7 -> 2^3 返回 3

在文件 los_vm_phys.c652 行定义.

653{
654 UINT32 order;
655
656 for (order = 0; VM_ORDER_TO_PAGES(order) < nPages; order++);
657
658 return order;
659}
这是这个函数的调用关系图:

◆ OsVmPageToVaddr()

VOID * OsVmPageToVaddr ( LosVmPage page)

通过page获取内核空间的虚拟地址 参考OsArchMmuInit
#define SYS_MEM_BASE DDR_MEM_ADDR /* physical memory base 物理地址的起始地址 * /
本函数非常重要,通过一个物理地址找到内核虚拟地址
内核静态映射:提升虚实转化效率,段映射减少页表项

参数
page
返回
VOID*

在文件 los_vm_phys.c288 行定义.

289{
290 VADDR_T vaddr;
291 vaddr = KERNEL_ASPACE_BASE + page->physAddr - SYS_MEM_BASE;//表示申请的物理地址在物理空间的偏移量等于映射的虚拟地址在内核空间的偏移量
292 return (VOID *)(UINTPTR)vaddr;//不需要存储映射关系,这简直就是神来之笔,拍案叫绝。@note_good 详见 鸿蒙内核源码分析(页表管理篇)
293}
unsigned long UINTPTR
Definition: los_typedef.h:68
PADDR_T physAddr
Definition: los_vm_page.h:56
这是这个函数的调用关系图:

◆ OsVmPhysAreaSizeAdjust()

VOID OsVmPhysAreaSizeAdjust ( size_t  size)

段区域大小调整

在文件 los_vm_phys.c141 行定义.

142{
143 /*
144 * The first physics memory segment is used for kernel image and kernel heap,
145 * so just need to adjust the first one here.
146 */
147 g_physArea[0].start += size;
148 g_physArea[0].size -= size;
149}
STATIC struct VmPhysArea g_physArea[]
Definition: los_vm_phys.c:80
size_t size
物理内存总大小
Definition: los_vm_phys.h:100
PADDR_T start
物理内存区基地址
Definition: los_vm_phys.h:99
这是这个函数的调用关系图:

◆ OsVmPhysInit()

VOID OsVmPhysInit ( VOID  )

物理段初始化

在文件 los_vm_phys.c181 行定义.

182{
183 struct VmPhysSeg *seg = NULL;
184 UINT32 nPages = 0;
185 int i;
186
187 for (i = 0; i < g_vmPhysSegNum; i++) {
188 seg = &g_vmPhysSeg[i];
189 seg->pageBase = &g_vmPageArray[nPages];//记录本段首页物理页框地址
190 nPages += seg->size >> PAGE_SHIFT;//偏移12位,按4K一页,算出本段总页数
191 OsVmPhysFreeListInit(seg); //初始化空闲链表,分配页框使用伙伴算法
192 OsVmPhysLruInit(seg); //初始化LRU置换链表
193 }
194}
LosVmPage * g_vmPageArray
物理页框(page frame)池,在g_vmPageArray中:不可能存在两个物理地址一样的物理页框,
Definition: los_vm_page.c:41
STATIC INLINE VOID OsVmPhysFreeListInit(struct VmPhysSeg *seg)
初始化空闲链表,分配物理页框使用伙伴算法
Definition: los_vm_phys.c:164
STATIC VOID OsVmPhysLruInit(struct VmPhysSeg *seg)
初始化Lru置换链表
Definition: los_vm_phys.c:95
LosVmPage * pageBase
Definition: los_vm_phys.h:88
size_t size
Definition: los_vm_phys.h:87
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPhysPageNumGet()

UINT32 OsVmPhysPageNumGet ( VOID  )

获得物理内存的总页数

在文件 los_vm_phys.c152 行定义.

153{
154 UINT32 nPages = 0;
155 INT32 i;
156
157 for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) {
158 nPages += g_physArea[i].size >> PAGE_SHIFT;//右移12位,相当于除以4K, 计算出总页数
159 }
160
161 return nPages;//返回所有物理内存总页数
162}
这是这个函数的调用关系图:

◆ OsVmPhysPagesFreeContiguous()

VOID OsVmPhysPagesFreeContiguous ( LosVmPage page,
size_t  nPages 
)

连续的释放物理页框, 如果8页连在一块是一起释放的

在文件 los_vm_phys.c420 行定义.

421{
422 paddr_t pa;
423 UINT32 order;
424 size_t n;
425
426 while (TRUE) {//死循环
427 pa = VM_PAGE_TO_PHYS(page);//获取页面物理地址
428 order = VM_PHYS_TO_ORDER(pa);//通过物理地址找到伙伴算法的级别
429 n = VM_ORDER_TO_PAGES(order);//通过级别找到物理页块 (1<<order),意思是如果order=3,就可以释放8个页块
430 if (n > nPages) {//nPages只剩下小于2^order时,退出循环
431 break;
432 }
433 OsVmPhysPagesFree(page, order);//释放伙伴算法对应块组
434 nPages -= n;//总页数减少
435 page += n;//释放的页数增多
436 }
437 //举例剩下 7个页框时,依次用 2^2 2^1 2^0 方式释放
438 while (nPages > 0) {
439 order = LOS_HighBitGet(nPages);//从高到低块组释放
440 n = VM_ORDER_TO_PAGES(order);//2^order次方
441 OsVmPhysPagesFree(page, order);//释放块组
442 nPages -= n;
443 page += n;//相当于page[n]
444 }
445}
UINT16 LOS_HighBitGet(UINT32 bitmap)
获取参数位图中最高位为1的索引位 例如: 00110110 返回 5
Definition: los_bitmap.c:88
unsigned long paddr_t
Definition: los_typedef.h:209
VOID OsVmPhysPagesFree(LosVmPage *page, UINT8 order)
释放物理页框,所谓释放物理页就是把页挂到空闲链表中
Definition: los_vm_phys.c:393
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPhysSegAdd()

VOID OsVmPhysSegAdd ( VOID  )

添加物理段

在文件 los_vm_phys.c127 行定义.

128{
129 INT32 i, ret;
130
131 LOS_ASSERT(g_vmPhysSegNum < VM_PHYS_SEG_MAX);
132
133 for (i = 0; i < (sizeof(g_physArea) / sizeof(g_physArea[0])); i++) {//遍历g_physArea数组
134 ret = OsVmPhysSegCreate(g_physArea[i].start, g_physArea[i].size);//由区划分转成段管理
135 if (ret != 0) {
136 VM_ERR("create phys seg failed");
137 }
138 }
139}
STATIC INT32 OsVmPhysSegCreate(paddr_t start, size_t size)
创建物理段,由区划分转成段管理
Definition: los_vm_phys.c:109
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPhysSegGet()

struct VmPhysSeg * OsVmPhysSegGet ( LosVmPage page)

获取物理页框所在段

在文件 los_vm_phys.c643 行定义.

644{
645 if ((page == NULL) || (page->segID >= VM_PHYS_SEG_MAX)) {
646 return NULL;
647 }
648
649 return (OsGVmPhysSegGet() + page->segID);//等用于OsGVmPhysSegGet()[page->segID]
650}
LosVmPhysSeg * OsGVmPhysSegGet()
获取段数组,全局变量,变量放在 .bbs 区
Definition: los_vm_phys.c:90
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPhysToPage()

LosVmPage * OsVmPhysToPage ( paddr_t  pa,
UINT8  segID 
)

通过物理地址获取所属参数段的物理页框

在文件 los_vm_phys.c250 行定义.

251{
252 struct VmPhysSeg *seg = NULL;
253 paddr_t offset;
254
255 if (segID >= VM_PHYS_SEG_MAX) {
256 LOS_Panic("The page segment id(%d) is invalid\n", segID);
257 }
258 seg = &g_vmPhysSeg[segID];
259 if ((pa < seg->start) || (pa >= (seg->start + seg->size))) {
260 return NULL;
261 }
262
263 offset = pa - seg->start;//得到物理地址的偏移量
264 return (seg->pageBase + (offset >> PAGE_SHIFT));//得到对应的物理页框
265}
NORETURN VOID LOS_Panic(const CHAR *fmt,...)
Kernel panic function.
PADDR_T start
Definition: los_vm_phys.h:86
函数调用图:
这是这个函数的调用关系图:

◆ OsVmVaddrToPage()

LosVmPage * OsVmVaddrToPage ( VOID *  ptr)

通过虚拟地址找映射的物理页框

在文件 los_vm_phys.c295 行定义.

296{
297 struct VmPhysSeg *seg = NULL;
298 PADDR_T pa = LOS_PaddrQuery(ptr);//通过空间的虚拟地址查询物理地址
299 UINT32 segID;
300
301 for (segID = 0; segID < g_vmPhysSegNum; segID++) {//遍历所有段
302 seg = &g_vmPhysSeg[segID];
303 if ((pa >= seg->start) && (pa < (seg->start + seg->size))) {//找到物理地址所在的段
304 return seg->pageBase + ((pa - seg->start) >> PAGE_SHIFT);//段基地址+页偏移索引 得到虚拟地址经映射所在物理页框
305 }
306 }
307
308 return NULL;
309}
PADDR_T LOS_PaddrQuery(VOID *vaddr)
通过虚拟地址查询映射的物理地址
Definition: los_vm_map.c:550
函数调用图:
这是这个函数的调用关系图:

变量说明

◆ g_vmPhysSeg

struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX]
extern

物理内存采用段页式管理,先切段后伙伴算法页

物理内存采用段页式管理,先切段后伙伴算法页

在文件 los_vm_phys.c87 行定义.

◆ g_vmPhysSegNum

INT32 g_vmPhysSegNum
extern

段总数

段数

在文件 los_vm_phys.c88 行定义.