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

浏览源代码.

函数

const CHAROsGetRegionNameOrFilePath (LosVmMapRegion *region)
 
INT32 OsRegionOverlapCheckUnlock (LosVmSpace *space, LosVmMapRegion *region)
 
UINT32 OsShellCmdProcessVmUsage (LosVmSpace *space)
 shell task 进程虚拟内存的使用情况 更多...
 
UINT32 OsShellCmdProcessPmUsage (LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
 shell task 物理内存的使用情况 更多...
 
UINT32 OsUProcessPmUsage (LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
 虚拟空间物理内存的使用情况,参数同时带走共享物理内存 sharePm和actualPm 单位是字节 更多...
 
UINT32 OsKProcessPmUsage (LosVmSpace *kAspace, UINT32 *actualPm)
 内核空间物理内存使用情况统计 更多...
 
VOID OsDumpAspace (LosVmSpace *space)
 dump 指定虚拟空间的信息 更多...
 
UINT32 OsCountRegionPages (LosVmSpace *space, LosVmMapRegion *region, UINT32 *pssPages)
 统计虚拟空间中某个线性区的页数 更多...
 
UINT32 OsCountAspacePages (LosVmSpace *space)
 统计虚拟空间的总页数 更多...
 
VOID OsDumpAllAspace (VOID)
 查看所有进程使用虚拟内存的情况 更多...
 
VOID OsVmPhysDump (VOID)
 dump 物理内存 更多...
 
VOID OsVmPhysUsedInfoGet (UINT32 *usedCount, UINT32 *totalCount)
 获取物理内存的使用信息,两个参数接走数据 更多...
 
INT32 OsRegionOverlapCheck (LosVmSpace *space, LosVmMapRegion *region)
 
VOID OsDumpPte (VADDR_T vaddr)
 dump 页表项 更多...
 
LosProcessCBOsGetPIDByAspace (LosVmSpace *space)
 通过虚拟空间获取进程实体 更多...
 
CHAROsArchFlagsToStr (const UINT32 archFlags)
 

函数说明

◆ OsArchFlagsToStr()

CHAR * OsArchFlagsToStr ( const UINT32  archFlags)

在文件 los_vm_dump.c326 行定义.

327{
328 UINT32 index;
329 UINT32 cacheFlags = archFlags & VM_MAP_REGION_FLAG_CACHE_MASK;
330 UINT32 flagSize = FLAG_SIZE * BITMAP_BITS_PER_WORD * sizeof(CHAR);
331 CHAR *archMmuFlagsStr = (CHAR *)LOS_MemAlloc(m_aucSysMem0, flagSize);
332 if (archMmuFlagsStr == NULL) {
333 return NULL;
334 }
335 (VOID)memset_s(archMmuFlagsStr, flagSize, 0, flagSize);
336 switch (cacheFlags) {
337 case 0UL:
338 (VOID)strcat_s(archMmuFlagsStr, flagSize, " CH\0");
339 break;
340 case 1UL:
341 (VOID)strcat_s(archMmuFlagsStr, flagSize, " UC\0");
342 break;
343 case 2UL:
344 (VOID)strcat_s(archMmuFlagsStr, flagSize, " UD\0");
345 break;
346 case 3UL:
347 (VOID)strcat_s(archMmuFlagsStr, flagSize, " WC\0");
348 break;
349 default:
350 break;
351 }
352
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",
362 };
363
364 for (index = FLAG_START; index < BITMAP_BITS_PER_WORD; index++) {
365 if (FLAGS[index][0] == '?') {
366 continue;
367 }
368
369 if (archFlags & (1UL << index)) {
370 UINT32 status = strcat_s(archMmuFlagsStr, flagSize, FLAGS[index]);
371 if (status != 0) {
372 PRINTK("error\n");
373 }
374 }
375 }
376
377 return archMmuFlagsStr;
378}
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
函数调用图:
这是这个函数的调用关系图:

◆ OsCountAspacePages()

UINT32 OsCountAspacePages ( LosVmSpace space)

统计虚拟空间的总页数

在文件 los_vm_dump.c312 行定义.

313{
314 UINT32 spacePages = 0;
315 LosVmMapRegion *region = NULL;
316 LosRbNode *pstRbNode = NULL;
317 LosRbNode *pstRbNodeNext = NULL;
318
319 RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
320 region = (LosVmMapRegion *)pstRbNode;
321 spacePages += OsCountRegionPages(space, region, NULL);
322 RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
323 return spacePages;
324}
UINT32 OsCountRegionPages(LosVmSpace *space, LosVmMapRegion *region, UINT32 *pssPages)
统计虚拟空间中某个线性区的页数
Definition: los_vm_dump.c:278
LosRbTree regionRbTree
Definition: los_vm_map.h:148
函数调用图:
这是这个函数的调用关系图:

◆ OsCountRegionPages()

UINT32 OsCountRegionPages ( LosVmSpace space,
LosVmMapRegion region,
UINT32 pssPages 
)

统计虚拟空间中某个线性区的页数

在文件 los_vm_dump.c278 行定义.

279{
280 UINT32 regionPages = 0;
281 PADDR_T paddr;
282 VADDR_T vaddr;
283 UINT32 ref;
284 STATUS_T status;
285 float pss = 0;
286 LosVmPage *page = NULL;
287
288 for (vaddr = region->range.base; vaddr < region->range.base + region->range.size; vaddr = vaddr + PAGE_SIZE) {
289 status = LOS_ArchMmuQuery(&space->archMmu, vaddr, &paddr, NULL);
290 if (status == LOS_OK) {
291 regionPages++;
292 if (pssPages == NULL) {
293 continue;
294 }
295 page = LOS_VmPageGet(paddr);
296 if (page != NULL) {
297 ref = LOS_AtomicRead(&page->refCounts);
298 pss += ((ref > 0) ? (1.0 / ref) : 1);
299 } else {
300 pss += 1;
301 }
302 }
303 }
304
305 if (pssPages != NULL) {
306 *pssPages = (UINT32)(pss + 0.5);
307 }
308
309 return regionPages;
310}
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
Definition: los_atomic.h:123
STATUS_T LOS_ArchMmuQuery(const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。 本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限
Definition: los_arch_mmu.c:569
unsigned long PADDR_T
Definition: los_typedef.h:207
unsigned long VADDR_T
Definition: los_typedef.h:208
int STATUS_T
Definition: los_typedef.h:215
LosVmPage * LOS_VmPageGet(PADDR_T paddr)
通过物理地址获取页框
Definition: los_vm_page.c:120
UINT32 size
Definition: los_vm_map.h:85
VADDR_T base
Definition: los_vm_map.h:84
LosVmMapRange range
Definition: los_vm_map.h:123
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
Definition: los_vm_page.h:53
Atomic refCounts
Definition: los_vm_page.h:57
LosArchMmu archMmu
Definition: los_vm_map.h:157
函数调用图:
这是这个函数的调用关系图:

◆ OsDumpAllAspace()

VOID OsDumpAllAspace ( VOID  )

查看所有进程使用虚拟内存的情况

在文件 los_vm_dump.c430 行定义.

431{
432 LosVmSpace *space = NULL;
433 LOS_DL_LIST *aspaceList = LOS_GetVmSpaceList();//获取所有空间链表
434 LOS_DL_LIST_FOR_EACH_ENTRY(space, aspaceList, LosVmSpace, node) {//循环取出进程虚拟空间
435 (VOID)LOS_MuxAcquire(&space->regionMux);
436 OsDumpAspace(space);//dump 空间
437 (VOID)LOS_MuxRelease(&space->regionMux);
438 }
439 return;
440}
VOID OsDumpAspace(LosVmSpace *space)
dump 指定虚拟空间的信息
Definition: los_vm_dump.c:396
STATIC INLINE STATUS_T LOS_MuxAcquire(LosMux *m)
Definition: los_vm_lock.h:48
STATIC INLINE STATUS_T LOS_MuxRelease(LosMux *m)
Definition: los_vm_lock.h:53
LOS_DL_LIST * LOS_GetVmSpaceList(VOID)
获取进程空间链表指针 g_vmSpaceList中挂的是进程空间 g_kVmSpace, g_vMallocSpace,所有用户进程的空间(独有一个进程空间)
Definition: los_vm_map.c:135
虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间
Definition: los_vm_map.h:146
LosMux regionMux
Definition: los_vm_map.h:149
函数调用图:
这是这个函数的调用关系图:

◆ OsDumpAspace()

VOID OsDumpAspace ( LosVmSpace space)

dump 指定虚拟空间的信息

在文件 los_vm_dump.c396 行定义.

397{
398 LosVmMapRegion *region = NULL;
399 LosRbNode *pstRbNode = NULL;
400 LosRbNode *pstRbNodeNext = NULL;
401 UINT32 spacePages;
402 LosProcessCB *pcb = OsGetPIDByAspace(space);//通过虚拟空间找到进程实体
403
404 if (pcb == NULL) {
405 return;
406 }
407 //进程ID | 进程虚拟内存控制块地址信息 | 虚拟内存起始地址 | 虚拟内存大小 | 已使用的物理页数量
408 spacePages = OsCountAspacePages(space);//获取空间的页数
409 PRINTK("\r\n PID aspace name base size pages \n");
410 PRINTK(" ---- ------ ---- ---- ----- ----\n");
411 PRINTK(" %-4d %#010x %-10.10s %#010x %#010x %d\n", pcb->processID, space, pcb->processName,
412 space->base, space->size, spacePages);
413
414 //虚拟区间控制块地址信息 | 虚拟区间类型 | 虚拟区间起始地址 | 虚拟区间大小 | 虚拟区间mmu映射属性 | 已使用的物理页数量(包括共享内存部分 | 已使用的物理页数量
415
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)//按region 轮询统计
419 region = (LosVmMapRegion *)pstRbNode;
420 if (region != NULL) {
421 OsDumpRegion2(space, region);
422 (VOID)OsRegionOverlapCheck(space, region);
423 } else {
424 PRINTK("region is NULL\n");
425 }
426 RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
427 return;
428}
LosProcessCB * OsGetPIDByAspace(LosVmSpace *space)
通过虚拟空间获取进程实体
Definition: los_vm_dump.c:256
STATUS_T OsRegionOverlapCheck(LosVmSpace *space, LosVmMapRegion *region)
Definition: los_vm_dump.c:442
VOID OsDumpRegion2(LosVmSpace *space, LosVmMapRegion *region)
Definition: los_vm_dump.c:380
UINT32 OsCountAspacePages(LosVmSpace *space)
统计虚拟空间的总页数
Definition: los_vm_dump.c:312
UINT32 processID
CHAR processName[OS_PCB_NAME_LEN]
VADDR_T base
Definition: los_vm_map.h:150
UINT32 size
Definition: los_vm_map.h:151
函数调用图:
这是这个函数的调用关系图:

◆ OsDumpPte()

VOID OsDumpPte ( VADDR_T  vaddr)

dump 页表项

在文件 los_vm_dump.c456 行定义.

457{
458 UINT32 l1Index = vaddr >> MMU_DESCRIPTOR_L1_SMALL_SHIFT;
459 LosVmSpace *space = LOS_SpaceGet(vaddr);//通过虚拟地址获取空间,内核分三个空间 内核进程空间,内核堆空间,用户进程空间
460 UINT32 ttEntry;
461 LosVmPage *page = NULL;
462 PTE_T *l2Table = NULL;
463 UINT32 l2Index;
464
465 if (space == NULL) {
466 return;
467 }
468
469 ttEntry = space->archMmu.virtTtb[l1Index];//找到 L1 页面项
470 if (ttEntry) {
471 l2Table = LOS_PaddrToKVaddr(MMU_DESCRIPTOR_L1_PAGE_TABLE_ADDR(ttEntry));//找到L1页面项对应的 L2表
472 l2Index = (vaddr % MMU_DESCRIPTOR_L1_SMALL_SIZE) >> PAGE_SHIFT;//找到L2页面项
473 if (l2Table == NULL) {
474 goto ERR;
475 }
476 page = LOS_VmPageGet(l2Table[l2Index] & ~(PAGE_SIZE - 1));//获取物理页框
477 if (page == NULL) {
478 goto ERR;
479 }
480 PRINTK("vaddr %p, l1Index %d, ttEntry %p, l2Table %p, l2Index %d, pfn %p count %d\n",
481 vaddr, l1Index, ttEntry, l2Table, l2Index, l2Table[l2Index], LOS_AtomicRead(&page->refCounts));//打印L1 L2 页表项
482 } else {//不在L1表
483 PRINTK("vaddr %p, l1Index %d, ttEntry %p\n", vaddr, l1Index, ttEntry);
484 }
485 return;
486ERR:
487 PRINTK("%s, error vaddr: %#x, l2Table: %#x, l2Index: %#x\n", __FUNCTION__, vaddr, l2Table, l2Index);
488}
unsigned long PTE_T
Definition: los_typedef.h:213
LosVmSpace * LOS_SpaceGet(VADDR_T vaddr)
获取虚拟地址对应的进程空间结构体指针
Definition: los_vm_map.c:117
VADDR_T * LOS_PaddrToKVaddr(PADDR_T paddr)
通过物理地址获取内核虚拟地址
Definition: los_vm_phys.c:688
VADDR_T * virtTtb
Definition: los_arch_mmu.h:90
函数调用图:
这是这个函数的调用关系图:

◆ OsGetPIDByAspace()

LosProcessCB * OsGetPIDByAspace ( LosVmSpace space)

通过虚拟空间获取进程实体

在文件 los_vm_dump.c256 行定义.

257{
258 UINT32 pid;
259 UINT32 intSave;
260 LosProcessCB *processCB = NULL;
261
262 SCHEDULER_LOCK(intSave);
263 for (pid = 0; pid < g_processMaxNum; ++pid) {//循环进程池,进程池本质是个数组
264 processCB = g_processCBArray + pid;
265 if (OsProcessIsUnused(processCB)) {//进程还没被分配使用
266 continue;//继续找呗
267 }
268
269 if (processCB->vmSpace == space) {//找到了
270 SCHEDULER_UNLOCK(intSave);
271 return processCB;
272 }
273 }
274 SCHEDULER_UNLOCK(intSave);
275 return NULL;
276}
LITE_OS_SEC_BSS LosProcessCB * g_processCBArray
进程池数组
Definition: los_process.c:80
LITE_OS_SEC_BSS UINT32 g_processMaxNum
进程最大数量,默认64个
Definition: los_process.c:86
STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)
LosVmSpace * vmSpace
函数调用图:
这是这个函数的调用关系图:

◆ OsGetRegionNameOrFilePath()

const CHAR * OsGetRegionNameOrFilePath ( LosVmMapRegion region)

在文件 los_vm_dump.c57 行定义.

58{
59 struct Vnode *vnode = NULL;
60 if (region == NULL) {
61 return "";
62#ifdef LOSCFG_FS_VFS
63 } else if (LOS_IsRegionFileValid(region)) {
64 vnode = region->unTypeData.rf.vnode;
65 return vnode->filePath;
66#endif
67 } else if (region->regionFlags & VM_MAP_REGION_FLAG_HEAP) {//堆区
68 return "HEAP";
69 } else if (region->regionFlags & VM_MAP_REGION_FLAG_STACK) {//栈区
70 return "STACK";
71 } else if (region->regionFlags & VM_MAP_REGION_FLAG_TEXT) {//文本区
72 return "Text";
73 } else if (region->regionFlags & VM_MAP_REGION_FLAG_VDSO) {//虚拟动态链接对象区(Virtual Dynamically Shared Object、VDSO)
74 return "VDSO";
75 } else if (region->regionFlags & VM_MAP_REGION_FLAG_MMAP) {//映射区
76 return "MMAP";
77 } else if (region->regionFlags & VM_MAP_REGION_FLAG_SHM) {//共享区
78 return "SHM";
79 } else {
80 return "";
81 }
82 return "";
83}
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
映射类型为文件的线性区是否有效
Definition: los_vm_map.c:512
struct VmMapRegion::@4::VmRegionFile rf
union VmMapRegion::@4 unTypeData
UINT32 regionFlags
Definition: los_vm_map.h:125
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
char * filePath
Definition: vnode.h:182
函数调用图:
这是这个函数的调用关系图:

◆ OsKProcessPmUsage()

UINT32 OsKProcessPmUsage ( LosVmSpace kAspace,
UINT32 actualPm 
)

内核空间物理内存使用情况统计

在文件 los_vm_dump.c138 行定义.

139{
140 UINT32 memUsed;
141 UINT32 totalMem;
142 UINT32 freeMem;
143 UINT32 usedCount = 0;
144 UINT32 totalCount = 0;
145 LosVmSpace *space = NULL;
146 LOS_DL_LIST *spaceList = NULL;
147 UINT32 UProcessUsed = 0;
148 UINT32 pmTmp;
149
150 if (actualPm == NULL) {
151 return 0;
152 }
153
156 freeMem = totalMem - memUsed;
157
158 OsVmPhysUsedInfoGet(&usedCount, &totalCount);
159 /* Kernel resident memory, include default heap memory */
160 memUsed = SYS_MEM_SIZE_DEFAULT - (totalCount << PAGE_SHIFT);
161
162 spaceList = LOS_GetVmSpaceList();//获取虚拟空间链表,上面挂了所有虚拟空间
163 LosMux *vmSpaceListMux = OsGVmSpaceMuxGet();
164 (VOID)LOS_MuxAcquire(vmSpaceListMux);
165 LOS_DL_LIST_FOR_EACH_ENTRY(space, spaceList, LosVmSpace, node) {//遍历链表
166 if (space == LOS_GetKVmSpace()) {//内核空间不统计
167 continue;
168 }
169 (VOID)OsUProcessPmUsage(space, NULL, &pmTmp);//统计用户空间物理内存的使用情况
170 UProcessUsed += pmTmp;//用户空间物理内存叠加
171 }
172 (VOID)LOS_MuxRelease(vmSpaceListMux);
173
174 /* Kernel dynamic memory, include extended heap memory */ //内核动态内存,包括扩展堆内存
175 memUsed += ((usedCount << PAGE_SHIFT) - UProcessUsed);
176 /* Remaining heap memory */ //剩余堆内存
177 memUsed -= freeMem;
178
179 *actualPm = memUsed;
180 return memUsed;
181}
UINT8 * m_aucSysMem1
系统动态内存池地址的起始地址 @note_thinking 能否不要用 0,1来命名核心变量 ???
Definition: los_memory.c:108
UINT32 LOS_MemPoolSizeGet(const VOID *pool)
获取指定动态内存池的总大小
Definition: los_memory.c:1603
UINT32 LOS_MemTotalUsedGet(VOID *pool)
获取指定动态内存池的总使用量大小
Definition: los_memory.c:1628
VOID OsVmPhysUsedInfoGet(UINT32 *usedCount, UINT32 *totalCount)
获取物理内存的使用信息,两个参数接走数据
Definition: los_vm_dump.c:558
UINT32 OsUProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
虚拟空间物理内存的使用情况,参数同时带走共享物理内存 sharePm和actualPm 单位是字节
Definition: los_vm_dump.c:199
LosMux * OsGVmSpaceMuxGet(VOID)
LosVmSpace * LOS_GetKVmSpace(VOID)
内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间
Definition: los_vm_map.c:130
Definition: los_mux.h:73
函数调用图:
这是这个函数的调用关系图:

◆ OsRegionOverlapCheck()

INT32 OsRegionOverlapCheck ( LosVmSpace space,
LosVmMapRegion region 
)

在文件 los_vm_dump.c442 行定义.

443{
444 int ret;
445
446 if (space == NULL || region == NULL) {
447 return -1;
448 }
449
450 (VOID)LOS_MuxAcquire(&space->regionMux);
451 ret = OsRegionOverlapCheckUnlock(space, region);
452 (VOID)LOS_MuxRelease(&space->regionMux);
453 return ret;
454}
INT32 OsRegionOverlapCheckUnlock(LosVmSpace *space, LosVmMapRegion *region)
Definition: los_vm_dump.c:85
函数调用图:
这是这个函数的调用关系图:

◆ OsRegionOverlapCheckUnlock()

INT32 OsRegionOverlapCheckUnlock ( LosVmSpace space,
LosVmMapRegion region 
)

在文件 los_vm_dump.c85 行定义.

86{
87 LosVmMapRegion *regionTemp = NULL;
88 LosRbNode *pstRbNode = NULL;
89 LosRbNode *pstRbNodeNext = NULL;
90
91 /* search the region list */
92 RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
93 regionTemp = (LosVmMapRegion *)pstRbNode;
94 if (region->range.base == regionTemp->range.base && region->range.size == regionTemp->range.size) {
95 continue;
96 }
97 if (((region->range.base + region->range.size) > regionTemp->range.base) &&
98 (region->range.base < (regionTemp->range.base + regionTemp->range.size))) {
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",
102 region->regionFlags, region->range.base, region->range.size, region->space,
103 regionTemp->regionFlags, regionTemp->range.base, regionTemp->range.size, regionTemp->space);
104 return -1;
105 }
106 RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
107
108 return 0;
109}
LosVmSpace * space
所属虚拟空间,虚拟空间由多个线性区组成
Definition: los_vm_map.h:121
这是这个函数的调用关系图:

◆ OsShellCmdProcessPmUsage()

UINT32 OsShellCmdProcessPmUsage ( LosVmSpace space,
UINT32 sharePm,
UINT32 actualPm 
)

shell task 物理内存的使用情况

在文件 los_vm_dump.c183 行定义.

184{
185 if (space == NULL) {
186 return 0;
187 }
188
189 if ((sharePm == NULL) && (actualPm == NULL)) {
190 return 0;
191 }
192
193 if (space == LOS_GetKVmSpace()) {
194 return OsKProcessPmUsage(space, actualPm);
195 }
196 return OsUProcessPmUsage(space, sharePm, actualPm);
197}
UINT32 OsKProcessPmUsage(LosVmSpace *kSpace, UINT32 *actualPm)
内核空间物理内存使用情况统计
Definition: los_vm_dump.c:138
函数调用图:
这是这个函数的调用关系图:

◆ OsShellCmdProcessVmUsage()

UINT32 OsShellCmdProcessVmUsage ( LosVmSpace space)

shell task 进程虚拟内存的使用情况

在文件 los_vm_dump.c111 行定义.

112{
113 LosVmMapRegion *region = NULL;
114 LosRbNode *pstRbNode = NULL;
115 LosRbNode *pstRbNodeNext = NULL;
116 UINT32 used = 0;
117
118 if (space == NULL) {
119 return 0;
120 }
121
122 if (space == LOS_GetKVmSpace()) {//内核空间
123 OsShellCmdProcessPmUsage(space, NULL, &used);
124 return used;
125 }
126 UINT32 ret = LOS_MuxAcquire(&space->regionMux);
127 if (ret != 0) {
128 return 0;
129 }
130 RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)//开始扫描红黑树
131 region = (LosVmMapRegion *)pstRbNode;//拿到线性区,注意LosVmMapRegion结构体的第一个变量就是pstRbNode,所以可直接(LosVmMapRegion *)转
132 used += region->range.size;//size叠加,算出总使用
133 RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)//结束扫描红黑树
134 (VOID)LOS_MuxRelease(&space->regionMux);
135 return used;
136}
UINT32 OsShellCmdProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
shell task 物理内存的使用情况
Definition: los_vm_dump.c:183
函数调用图:
这是这个函数的调用关系图:

◆ OsUProcessPmUsage()

UINT32 OsUProcessPmUsage ( LosVmSpace space,
UINT32 sharePm,
UINT32 actualPm 
)

虚拟空间物理内存的使用情况,参数同时带走共享物理内存 sharePm和actualPm 单位是字节

在文件 los_vm_dump.c199 行定义.

200{
201 LosVmMapRegion *region = NULL;
202 LosRbNode *pstRbNode = NULL;
203 LosRbNode *pstRbNodeNext = NULL;
204 LosVmPage *page = NULL;
205 VADDR_T vaddr;
206 size_t size;
207 PADDR_T paddr;
208 STATUS_T ret;
209 INT32 shareRef;
210
211 if (sharePm != NULL) {
212 *sharePm = 0;
213 }
214
215 if (actualPm != NULL) {
216 *actualPm = 0;
217 }
218
219 ret = LOS_MuxAcquire(&space->regionMux);
220 if (ret != 0) {
221 return 0;
222 }
223 RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
224 region = (LosVmMapRegion *)pstRbNode;
225 vaddr = region->range.base;
226 size = region->range.size;
227 for (; size > 0; vaddr += PAGE_SIZE, size -= PAGE_SIZE) {
228 ret = LOS_ArchMmuQuery(&space->archMmu, vaddr, &paddr, NULL);
229 if (ret < 0) {
230 continue;
231 }
232 page = LOS_VmPageGet(paddr);
233 if (page == NULL) {
234 continue;
235 }
236
237 shareRef = LOS_AtomicRead(&page->refCounts);//ref 大于1 说明page被其他空间也引用了,这就是共享内存核心定义!
238 if (shareRef > 1) {
239 if (sharePm != NULL) {
240 *sharePm += PAGE_SIZE;//一页 4K 字节
241 }
242 if (actualPm != NULL) {
243 *actualPm += PAGE_SIZE / shareRef;//这个就有点意思了,碰到共享内存的情况,平分!哈哈。。。
244 }
245 } else {
246 if (actualPm != NULL) {
247 *actualPm += PAGE_SIZE;//算自己的
248 }
249 }
250 }
251 RB_SCAN_SAFE_END(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)
252 (VOID)LOS_MuxRelease(&space->regionMux);
253 return *actualPm;
254}
signed int INT32
Definition: los_typedef.h:60
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPhysDump()

VOID OsVmPhysDump ( VOID  )

dump 物理内存

在文件 los_vm_dump.c516 行定义.

517{
518 LosVmPhysSeg *seg = NULL;
519 UINT32 segFreePages;
520 UINT32 totalFreePages = 0;
521 UINT32 totalPages = 0;
522 UINT32 segIndex;
523 UINT32 intSave;
524 UINT32 flindex;
525 UINT32 listCount[VM_LIST_ORDER_MAX] = {0};
526
527 for (segIndex = 0; segIndex < g_vmPhysSegNum; segIndex++) {//循环取段
528 seg = &g_vmPhysSeg[segIndex];
529 if (seg->size > 0) {
530 segFreePages = OsVmPhySegPagesGet(seg);
531#ifdef LOSCFG_SHELL_CMD_DEBUG
532 PRINTK("\r\n phys_seg base size free_pages \n");
533 PRINTK(" -------- ------- ---------- --------- \n");
534#endif
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);
538
539 LOS_SpinLockSave(&seg->freeListLock, &intSave);
540 for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
541 listCount[flindex] = seg->freeList[flindex].listCnt;
542 }
543 LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
544 for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
545 PRINTK("order = %d, free_count = %d\n", flindex, listCount[flindex]);
546 }
547
548 PRINTK("active anon %d\n", seg->lruSize[VM_LRU_ACTIVE_ANON]);
549 PRINTK("inactive anon %d\n", seg->lruSize[VM_LRU_INACTIVE_ANON]);
550 PRINTK("active file %d\n", seg->lruSize[VM_LRU_ACTIVE_FILE]);
551 PRINTK("inactive file %d\n", seg->lruSize[VM_LRU_INACTIVE_FILE]);
552 }
553 }
554 PRINTK("\n\rpmm pages: total = %u, used = %u, free = %u\n",
555 totalPages, (totalPages - totalFreePages), totalFreePages);
556}
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
UINT32 OsVmPhySegPagesGet(LosVmPhysSeg *seg)
获取段剩余页框数
Definition: los_vm_dump.c:490
INT32 g_vmPhysSegNum
段总数
Definition: los_vm_phys.c:88
@ VM_LRU_ACTIVE_ANON
活动匿名页(swap)
Definition: los_vm_phys.h:76
@ 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
struct VmPhysSeg g_vmPhysSeg[VM_PHYS_SEG_MAX]
物理内存采用段页式管理,先切段后伙伴算法页
Definition: los_vm_phys.c:87
UINT32 listCnt
空闲物理页总数
Definition: los_vm_phys.h:68
物理段描述符
Definition: los_vm_phys.h:85
size_t lruSize[VM_NR_LRU_LISTS]
5个双循环链表大小,如此方便得到size
Definition: los_vm_phys.h:92
SPIN_LOCK_S freeListLock
Definition: los_vm_phys.h:89
struct VmFreeList freeList[VM_LIST_ORDER_MAX]
Definition: los_vm_phys.h:90
size_t size
Definition: los_vm_phys.h:87
PADDR_T start
Definition: los_vm_phys.h:86
函数调用图:
这是这个函数的调用关系图:

◆ OsVmPhysUsedInfoGet()

VOID OsVmPhysUsedInfoGet ( UINT32 usedCount,
UINT32 totalCount 
)

获取物理内存的使用信息,两个参数接走数据

在文件 los_vm_dump.c558 行定义.

559{
560 UINT32 index;
561 UINT32 segFreePages;
562 LosVmPhysSeg *physSeg = NULL;
563
564 if (usedCount == NULL || totalCount == NULL) {
565 return;
566 }
567 *usedCount = 0;
568 *totalCount = 0;
569
570 for (index = 0; index < g_vmPhysSegNum; index++) {//循环取段
571 physSeg = &g_vmPhysSeg[index];
572 if (physSeg->size > 0) {
573 *totalCount += physSeg->size >> PAGE_SHIFT;//叠加段的总页数
574 segFreePages = OsVmPhySegPagesGet(physSeg);//获取段的剩余页数
575 *usedCount += (*totalCount - segFreePages);//叠加段的使用页数
576 }
577 }
578}
函数调用图:
这是这个函数的调用关系图: