52#ifdef LOSCFG_KERNEL_VM
59 struct Vnode *vnode = NULL;
67 }
else if (region->
regionFlags & VM_MAP_REGION_FLAG_HEAP) {
69 }
else if (region->
regionFlags & VM_MAP_REGION_FLAG_STACK) {
71 }
else if (region->
regionFlags & VM_MAP_REGION_FLAG_TEXT) {
73 }
else if (region->
regionFlags & VM_MAP_REGION_FLAG_VDSO) {
75 }
else if (region->
regionFlags & VM_MAP_REGION_FLAG_MMAP) {
77 }
else if (region->
regionFlags & VM_MAP_REGION_FLAG_SHM) {
92 RB_SCAN_SAFE(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
99 VM_ERR(
"overlap between regions:\n"
100 "flags:%#x base:%p size:%08x space:%p\n"
101 "flags:%#x base:%p size:%08x space:%p",
106 RB_SCAN_SAFE_END(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
130 RB_SCAN_SAFE(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
133 RB_SCAN_SAFE_END(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
150 if (actualPm == NULL) {
156 freeMem = totalMem - memUsed;
160 memUsed = SYS_MEM_SIZE_DEFAULT - (totalCount << PAGE_SHIFT);
165 LOS_DL_LIST_FOR_EACH_ENTRY(space, spaceList,
LosVmSpace, node) {
170 UProcessUsed += pmTmp;
175 memUsed += ((usedCount << PAGE_SHIFT) - UProcessUsed);
189 if ((sharePm == NULL) && (actualPm == NULL)) {
211 if (sharePm != NULL) {
215 if (actualPm != NULL) {
223 RB_SCAN_SAFE(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
227 for (; size > 0; vaddr += PAGE_SIZE, size -= PAGE_SIZE) {
239 if (sharePm != NULL) {
240 *sharePm += PAGE_SIZE;
242 if (actualPm != NULL) {
243 *actualPm += PAGE_SIZE / shareRef;
246 if (actualPm != NULL) {
247 *actualPm += PAGE_SIZE;
251 RB_SCAN_SAFE_END(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)
262 SCHEDULER_LOCK(intSave);
269 if (processCB->
vmSpace == space) {
270 SCHEDULER_UNLOCK(intSave);
274 SCHEDULER_UNLOCK(intSave);
288 for (vaddr = region->
range.
base; vaddr < region->range.base + region->
range.
size; vaddr = vaddr + PAGE_SIZE) {
290 if (status == LOS_OK) {
292 if (pssPages == NULL) {
298 pss += ((ref > 0) ? (1.0 / ref) : 1);
305 if (pssPages != NULL) {
306 *pssPages = (
UINT32)(pss + 0.5);
319 RB_SCAN_SAFE(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
322 RB_SCAN_SAFE_END(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
329 UINT32 cacheFlags = archFlags & VM_MAP_REGION_FLAG_CACHE_MASK;
330 UINT32 flagSize = FLAG_SIZE * BITMAP_BITS_PER_WORD *
sizeof(
CHAR);
332 if (archMmuFlagsStr == NULL) {
335 (VOID)memset_s(archMmuFlagsStr, flagSize, 0, flagSize);
336 switch (cacheFlags) {
338 (VOID)strcat_s(archMmuFlagsStr, flagSize,
" CH\0");
341 (VOID)strcat_s(archMmuFlagsStr, flagSize,
" UC\0");
344 (VOID)strcat_s(archMmuFlagsStr, flagSize,
" UD\0");
347 (VOID)strcat_s(archMmuFlagsStr, flagSize,
" WC\0");
353 static const CHAR FLAGS[BITMAP_BITS_PER_WORD][FLAG_SIZE] = {
354 [0 ... (__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_USER) - 2)] =
"???\0",
355 [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_USER) - 1] =
" US\0",
356 [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_READ) - 1] =
" RD\0",
357 [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_WRITE) - 1] =
" WR\0",
358 [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_EXECUTE) - 1] =
" EX\0",
359 [__builtin_ffsl(VM_MAP_REGION_FLAG_NS) - 1] =
" NS\0",
360 [__builtin_ffsl(VM_MAP_REGION_FLAG_INVALID) - 1] =
" IN\0",
361 [__builtin_ffsl(VM_MAP_REGION_FLAG_INVALID) ... (BITMAP_BITS_PER_WORD - 1)] =
"???\0",
364 for (index = FLAG_START; index < BITMAP_BITS_PER_WORD; index++) {
365 if (FLAGS[index][0] ==
'?') {
369 if (archFlags & (1UL << index)) {
370 UINT32 status = strcat_s(archMmuFlagsStr, flagSize, FLAGS[index]);
377 return archMmuFlagsStr;
387 if (flagsStr == NULL) {
390 PRINTK(
"\t %#010x %-32.32s %#010x %#010x %-15.15s %4d %4d\n",
392 region->
range.
size, flagsStr, regionPages, pssPages);
409 PRINTK(
"\r\n PID aspace name base size pages \n");
410 PRINTK(
" ---- ------ ---- ---- ----- ----\n");
412 space->
base, space->
size, spacePages);
416 PRINTK(
"\r\n\t region name base size mmu_flags pages pg/ref\n");
417 PRINTK(
"\t ------ ---- ---- ---- --------- ----- -----\n");
418 RB_SCAN_SAFE(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
420 if (region != NULL) {
424 PRINTK(
"region is NULL\n");
426 RB_SCAN_SAFE_END(&space->
regionRbTree, pstRbNode, pstRbNodeNext)
434 LOS_DL_LIST_FOR_EACH_ENTRY(space, aspaceList,
LosVmSpace, node) {
446 if (space == NULL || region == NULL) {
458 UINT32 l1Index = vaddr >> MMU_DESCRIPTOR_L1_SMALL_SHIFT;
462 PTE_T *l2Table = NULL;
472 l2Index = (vaddr % MMU_DESCRIPTOR_L1_SMALL_SIZE) >> PAGE_SHIFT;
473 if (l2Table == NULL) {
480 PRINTK(
"vaddr %p, l1Index %d, ttEntry %p, l2Table %p, l2Index %d, pfn %p count %d\n",
483 PRINTK(
"vaddr %p, l1Index %d, ttEntry %p\n", vaddr, l1Index, ttEntry);
487 PRINTK(
"%s, error vaddr: %#x, l2Table: %#x, l2Index: %#x\n", __FUNCTION__, vaddr, l2Table, l2Index);
497 for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
520 UINT32 totalFreePages = 0;
525 UINT32 listCount[VM_LIST_ORDER_MAX] = {0};
531#ifdef LOSCFG_SHELL_CMD_DEBUG
532 PRINTK(
"\r\n phys_seg base size free_pages \n");
533 PRINTK(
" -------- ------- ---------- --------- \n");
535 PRINTK(
" 0x%08x 0x%08x 0x%08x %8u \n", seg, seg->
start, seg->
size, segFreePages);
536 totalFreePages += segFreePages;
537 totalPages += (seg->
size >> PAGE_SHIFT);
540 for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
544 for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
545 PRINTK(
"order = %d, free_count = %d\n", flindex, listCount[flindex]);
554 PRINTK(
"\n\rpmm pages: total = %u, used = %u, free = %u\n",
555 totalPages, (totalPages - totalFreePages), totalFreePages);
564 if (usedCount == NULL || totalCount == NULL) {
572 if (physSeg->
size > 0) {
573 *totalCount += physSeg->
size >> PAGE_SHIFT;
575 *usedCount += (*totalCount - segFreePages);
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
UINT8 * m_aucSysMem1
系统动态内存池地址的起始地址 @note_thinking 能否不要用 0,1来命名核心变量 ???
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
UINT32 LOS_MemPoolSizeGet(const VOID *pool)
获取指定动态内存池的总大小
UINT32 LOS_MemTotalUsedGet(VOID *pool)
获取指定动态内存池的总使用量大小
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
STATUS_T LOS_ArchMmuQuery(const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。 本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限
原子操作 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-atomic....
LITE_OS_SEC_BSS LosProcessCB * g_processCBArray
进程池数组
LITE_OS_SEC_BSS UINT32 g_processMaxNum
进程最大数量,默认64个
STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)
VOID LOS_SpinUnlockRestore(SPIN_LOCK_S *lock, UINT32 intSave)
VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
LosProcessCB * OsGetPIDByAspace(LosVmSpace *space)
通过虚拟空间获取进程实体
UINT32 OsCountRegionPages(LosVmSpace *space, LosVmMapRegion *region, UINT32 *pssPages)
统计虚拟空间中某个线性区的页数
VOID OsDumpAspace(LosVmSpace *space)
dump 指定虚拟空间的信息
VOID OsVmPhysUsedInfoGet(UINT32 *usedCount, UINT32 *totalCount)
获取物理内存的使用信息,两个参数接走数据
VOID OsDumpPte(VADDR_T vaddr)
dump 页表项
UINT32 OsKProcessPmUsage(LosVmSpace *kSpace, UINT32 *actualPm)
内核空间物理内存使用情况统计
UINT32 OsShellCmdProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
shell task 物理内存的使用情况
UINT32 OsShellCmdProcessVmUsage(LosVmSpace *space)
shell task 进程虚拟内存的使用情况
VOID OsDumpAllAspace(VOID)
查看所有进程使用虚拟内存的情况
CHAR * OsArchFlagsToStr(const UINT32 archFlags)
STATUS_T OsRegionOverlapCheck(LosVmSpace *space, LosVmMapRegion *region)
const CHAR * OsGetRegionNameOrFilePath(LosVmMapRegion *region)
VOID OsDumpRegion2(LosVmSpace *space, LosVmMapRegion *region)
VOID OsVmPhysDump(VOID)
dump 物理内存
UINT32 OsVmPhySegPagesGet(LosVmPhysSeg *seg)
获取段剩余页框数
UINT32 OsCountAspacePages(LosVmSpace *space)
统计虚拟空间的总页数
UINT32 OsUProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
虚拟空间物理内存的使用情况,参数同时带走共享物理内存 sharePm和actualPm 单位是字节
INT32 OsRegionOverlapCheckUnlock(LosVmSpace *space, LosVmMapRegion *region)
STATIC INLINE STATUS_T LOS_MuxAcquire(LosMux *m)
STATIC INLINE STATUS_T LOS_MuxRelease(LosMux *m)
LosMux * OsGVmSpaceMuxGet(VOID)
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
映射类型为文件的线性区是否有效
LosVmSpace * LOS_SpaceGet(VADDR_T vaddr)
获取虚拟地址对应的进程空间结构体指针
LOS_DL_LIST * LOS_GetVmSpaceList(VOID)
获取进程空间链表指针 g_vmSpaceList中挂的是进程空间 g_kVmSpace, g_vMallocSpace,所有用户进程的空间(独有一个进程空间)
LosVmSpace * LOS_GetKVmSpace(VOID)
内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间
LosVmPage * LOS_VmPageGet(PADDR_T paddr)
通过物理地址获取页框
@ VM_LRU_ACTIVE_ANON
活动匿名页(swap)
@ VM_LRU_ACTIVE_FILE
活动文件页(磁盘)
@ VM_LRU_INACTIVE_FILE
非活动文件页(磁盘)
@ VM_LRU_INACTIVE_ANON
非活动匿名页(swap)
struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX]
物理内存采用段页式管理,先切段后伙伴算法页
VADDR_T * LOS_PaddrToKVaddr(PADDR_T paddr)
通过物理地址获取内核虚拟地址
CHAR processName[OS_PCB_NAME_LEN]
struct VmMapRegion::@4::VmRegionFile rf
union VmMapRegion::@4 unTypeData
LosVmSpace * space
所属虚拟空间,虚拟空间由多个线性区组成
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
size_t lruSize[VM_NR_LRU_LISTS]
5个双循环链表大小,如此方便得到size
struct VmFreeList freeList[VM_LIST_ORDER_MAX]
虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系