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

浏览源代码.

结构体

struct  page_mapping
 
struct  file_map
 
struct  FilePage
 文件页结构体 更多...
 
struct  MapInfo
 虚拟地址和文件页的映射信息,在一个进程使用文件页之前,需要提前做好文件页在此内存空间的映射关系,如此通过虚拟内存就可以对文件页读写操作. 更多...
 

类型定义

typedef struct FilePage LosFilePage
 文件页结构体 更多...
 
typedef struct MapInfo LosMapInfo
 虚拟地址和文件页的映射信息,在一个进程使用文件页之前,需要提前做好文件页在此内存空间的映射关系,如此通过虚拟内存就可以对文件页读写操作. 更多...
 
typedef struct ProcessCB LosProcessCB
 

枚举

enum  OsPageFlags {
  FILE_PAGE_FREE , FILE_PAGE_LOCKED , FILE_PAGE_REFERENCED , FILE_PAGE_DIRTY ,
  FILE_PAGE_LRU , FILE_PAGE_ACTIVE , FILE_PAGE_SHARED
}
 Flags由 bitmap 管理 更多...
 

函数

STATIC INLINE VOID OsSetPageLocked (LosVmPage *page)
 给页面贴上被锁的标签 更多...
 
STATIC INLINE VOID OsCleanPageLocked (LosVmPage *page)
 给页面撕掉被锁的标签 更多...
 
STATIC INLINE VOID OsSetPageDirty (LosVmPage *page)
 给页面贴上数据被修改的标签 更多...
 
STATIC INLINE VOID OsCleanPageDirty (LosVmPage *page)
 给页面撕掉数据被修改的标签 更多...
 
STATIC INLINE VOID OsSetPageActive (LosVmPage *page)
 给页面贴上活动的标签 更多...
 
STATIC INLINE VOID OsCleanPageActive (LosVmPage *page)
 给页面撕掉活动的标签 更多...
 
STATIC INLINE VOID OsSetPageLRU (LosVmPage *page)
 给页面贴上置换页的标签 更多...
 
STATIC INLINE VOID OsSetPageFree (LosVmPage *page)
 给页面贴上被释放的标签 更多...
 
STATIC INLINE VOID OsCleanPageFree (LosVmPage *page)
 给页面撕掉被释放的标签 更多...
 
STATIC INLINE VOID OsSetPageReferenced (LosVmPage *page)
 给页面贴上被引用的标签 更多...
 
STATIC INLINE VOID OsCleanPageReferenced (LosVmPage *page)
 给页面撕掉被引用的标签 更多...
 
STATIC INLINE BOOL OsIsPageActive (LosVmPage *page)
 页面是否活动 更多...
 
STATIC INLINE BOOL OsIsPageLocked (LosVmPage *page)
 页面是否被锁 更多...
 
STATIC INLINE BOOL OsIsPageReferenced (LosVmPage *page)
 页面是否被引用,只被一个进程引用的页叫私有页,多个进程引用就是共享页,此为共享内存的本质所在 更多...
 
STATIC INLINE BOOL OsIsPageDirty (LosVmPage *page)
 页面是否为脏页,所谓脏页就是页内数据是否被更新过,只有脏页才会有写时拷贝 更多...
 
STATIC INLINE BOOL OsIsPageMapped (LosFilePage *page)
 文件页是否映射过了 更多...
 
STATIC INLINE VOID OsSetPageShared (LosVmPage *page)
 
STATIC INLINE VOID OsCleanPageShared (LosVmPage *page)
 给页面撕掉共享页标签 更多...
 
STATIC INLINE BOOL OsIsPageShared (LosVmPage *page)
 是否为共享页 更多...
 
INT32 OsVfsFileMmap (struct file *filep, LosVmMapRegion *region)
 
STATUS_T OsNamedMMap (struct file *filep, LosVmMapRegion *region)
 
VOID OsVmmFileRegionFree (struct file *filep, LosProcessCB *processCB)
 
LosFilePageOsPageCacheAlloc (struct page_mapping *mapping, VM_OFFSET_T pgoff)
 
LosFilePageOsFindGetEntry (struct page_mapping *mapping, VM_OFFSET_T pgoff)
 
LosMapInfoOsGetMapInfo (LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
 通过虚拟地址获取文件页映射信息,archMmu每个进程都有属于自己的mmu 更多...
 
VOID OsAddMapInfo (LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
 
VOID OsDelMapInfo (LosVmMapRegion *region, LosVmPgFault *pgFault, BOOL cleanDirty)
 删除映射信息 更多...
 
VOID OsFileCacheFlush (struct page_mapping *mapping)
 文件缓存冲洗,把所有fpage冲洗一边,把脏页洗到dirtyList中,配合OsFileCacheRemove理解 更多...
 
VOID OsFileCacheRemove (struct page_mapping *mapping)
 
VOID OsUnmapPageLocked (LosFilePage *page, LosMapInfo *info)
 
VOID OsUnmapAllLocked (LosFilePage *page)
 解除文件页在所有进程的映射 更多...
 
VOID OsLruCacheAdd (LosFilePage *fpage, enum OsLruList lruType)
 
VOID OsLruCacheDel (LosFilePage *fpage)
 
LosFilePageOsDumpDirtyPage (LosFilePage *oldPage)
 备份脏页,老脏页撕掉脏页标签 更多...
 
VOID OsDoFlushDirtyPage (LosFilePage *fpage)
 冲洗脏页数据,将脏页数据回写磁盘 更多...
 
VOID OsDeletePageCacheLru (LosFilePage *page)
 删除页高速缓存和LRU,对应 OsAddToPageacheLru 更多...
 
VOID OsPageRefDecNoLock (LosFilePage *page)
 
VOID OsPageRefIncLocked (LosFilePage *page)
 
int OsTryShrinkMemory (size_t nPage)
 
VOID OsMarkPageDirty (LosFilePage *fpage, LosVmMapRegion *region, int off, int len)
 
VOID ResetPageCacheHitInfo (int *try, int *hit)
 
struct file_mapGetFileMappingList (void)
 

详细描述

 磁盘高速缓存是一种软件机制,它允许系统把通常存放在磁盘上的一些数据保留在 RAM 中,以便对那些数据的
 进一步访问不用再访问磁盘而能尽快得到满足。
 页高速缓存中的信息单位是一个完整的页。
 一个页包含的磁盘块在物理上不一定相邻,所以不能用设备号和块号标识,而是通过页的所有者和所有者数据中的索引来识别。
 页高速缓存可以缓存以下内容
     A.普通文件数据
     B.含有目录的页 
     C.直接从快设备读取的页 
     D.用户进程数据的页
     E.特殊文件系统的文件页
版本
作者
weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
日期
2021-12-9

在文件 los_vm_filemap.h 中定义.

类型定义说明

◆ LosFilePage

typedef struct FilePage LosFilePage

文件页结构体

◆ LosMapInfo

typedef struct MapInfo LosMapInfo

虚拟地址和文件页的映射信息,在一个进程使用文件页之前,需要提前做好文件页在此内存空间的映射关系,如此通过虚拟内存就可以对文件页读写操作.

◆ LosProcessCB

typedef struct ProcessCB LosProcessCB

在文件 los_vm_filemap.h231 行定义.

枚举类型说明

◆ OsPageFlags

Flags由 bitmap 管理

枚举值
FILE_PAGE_FREE 

空闲页

FILE_PAGE_LOCKED 

被锁页

FILE_PAGE_REFERENCED 

被引用页

FILE_PAGE_DIRTY 

脏页

FILE_PAGE_LRU 

LRU置换页

FILE_PAGE_ACTIVE 

活动页

FILE_PAGE_SHARED 

共享页

在文件 los_vm_filemap.h120 行定义.

120 {
121 FILE_PAGE_FREE, ///< 空闲页
122 FILE_PAGE_LOCKED, ///< 被锁页
123 FILE_PAGE_REFERENCED, ///< 被引用页
124 FILE_PAGE_DIRTY, ///< 脏页
125 FILE_PAGE_LRU, ///< LRU置换页
126 FILE_PAGE_ACTIVE, ///< 活动页
127 FILE_PAGE_SHARED, ///< 共享页
128};
@ FILE_PAGE_FREE
空闲页
@ FILE_PAGE_REFERENCED
被引用页
@ FILE_PAGE_DIRTY
脏页
@ FILE_PAGE_LOCKED
被锁页
@ FILE_PAGE_LRU
LRU置换页
@ FILE_PAGE_SHARED
共享页
@ FILE_PAGE_ACTIVE
活动页

函数说明

◆ GetFileMappingList()

struct file_map * GetFileMappingList ( void  )

在文件 vfs_file_mapping.c364 行定义.

365{
366 return &g_file_mapping;
367}
static struct file_map g_file_mapping
用于挂载所有文件的file_map

◆ OsAddMapInfo()

VOID OsAddMapInfo ( LosFilePage page,
LosArchMmu archMmu,
VADDR_T  vaddr 
)

在文件 los_vm_filemap.c127 行定义.

128{
129 LosMapInfo *info = NULL;
130
131 info = (LosMapInfo *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosMapInfo));//分配一个映射信息
132 if (info == NULL) {
133 VM_ERR("OsAddMapInfo alloc memory failed!");
134 return;
135 }
136 info->page = page; //文件页
137 info->archMmu = archMmu;//进程MMU,完成虚实地址转换
138 info->vaddr = vaddr; //虚拟地址
139
140 LOS_ListAdd(&page->i_mmap, &info->node);//将 LosMapInfo 节点挂入链表
141 page->n_maps++;//映射总数++
142}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
Definition: los_list.h:217
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
LOS_DL_LIST i_mmap
UINT32 n_maps
虚拟地址和文件页的映射信息,在一个进程使用文件页之前,需要提前做好文件页在此内存空间的映射关系,如此通过虚拟内存就可以对文件页读写操作.
LosFilePage * page
文件页中只记录物理地址,是不会变的.但它是需要被多个进程访问,和映射的.
VADDR_T vaddr
虚拟地址.每个进程访问同一个文件页的虚拟地址都是不一样的
LosArchMmu * archMmu
mmu完成vaddr和page->vmPage->physAddr物理地址的映射
LOS_DL_LIST node
节点,挂到page->i_mmap链表上.链表上记录要操作文件页的进程对这个page的映射信息
函数调用图:
这是这个函数的调用关系图:

◆ OsCleanPageActive()

STATIC INLINE VOID OsCleanPageActive ( LosVmPage page)

给页面撕掉活动的标签

在文件 los_vm_filemap.h160 行定义.

161{
163}
VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
对状态字的某一标志位进行清0操作
Definition: los_bitmap.c:69
UINT32 flags
Definition: los_vm_page.h:58
函数调用图:
这是这个函数的调用关系图:

◆ OsCleanPageDirty()

STATIC INLINE VOID OsCleanPageDirty ( LosVmPage page)

给页面撕掉数据被修改的标签

在文件 los_vm_filemap.h150 行定义.

151{
153}
函数调用图:
这是这个函数的调用关系图:

◆ OsCleanPageFree()

STATIC INLINE VOID OsCleanPageFree ( LosVmPage page)

给页面撕掉被释放的标签

在文件 los_vm_filemap.h175 行定义.

176{
178}
函数调用图:

◆ OsCleanPageLocked()

STATIC INLINE VOID OsCleanPageLocked ( LosVmPage page)

给页面撕掉被锁的标签

在文件 los_vm_filemap.h140 行定义.

141{
143}
函数调用图:
这是这个函数的调用关系图:

◆ OsCleanPageReferenced()

STATIC INLINE VOID OsCleanPageReferenced ( LosVmPage page)

给页面撕掉被引用的标签

在文件 los_vm_filemap.h185 行定义.

186{
188}
函数调用图:
这是这个函数的调用关系图:

◆ OsCleanPageShared()

STATIC INLINE VOID OsCleanPageShared ( LosVmPage page)

给页面撕掉共享页标签

在文件 los_vm_filemap.h221 行定义.

222{
223 LOS_BitmapClr(&page->flags, FILE_PAGE_SHARED);//共享页位 置0
224}
函数调用图:
这是这个函数的调用关系图:

◆ OsDeletePageCacheLru()

VOID OsDeletePageCacheLru ( LosFilePage page)

删除页高速缓存和LRU,对应 OsAddToPageacheLru

在文件 los_vm_filemap.c157 行定义.

158{
159 /* delete form lru list */
160 OsLruCacheDel(page); //将页面从lru列表中删除
161 /* delete from cache lits and free pmm if need */
162 OsPageCacheDel(page); //从page缓存中删除
163}
VOID OsPageCacheDel(LosFilePage *fpage)
从页高速缓存上删除页
VOID OsLruCacheDel(LosFilePage *fpage)
Definition: los_vm_scan.c:85
函数调用图:
这是这个函数的调用关系图:

◆ OsDelMapInfo()

VOID OsDelMapInfo ( LosVmMapRegion region,
LosVmPgFault pgFault,
BOOL  cleanDirty 
)

删除映射信息

在文件 los_vm_filemap.c348 行定义.

349{
350 UINT32 intSave;
351 LosMapInfo *info = NULL;
352 LosFilePage *fpage = NULL;
353 struct page_mapping *mapping = NULL;
354
355 if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
356 return;
357 }
358
359 mapping = &region->unTypeData.rf.vnode->mapping;
360 LOS_SpinLockSave(&mapping->list_lock, &intSave);
361 fpage = OsFindGetEntry(mapping, vmf->pgoff);
362 if (fpage == NULL) {
363 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
364 return;
365 }
366
367 if (cleanDirty) {
368 OsCleanPageDirty(fpage->vmPage);//恢复干净页
369 }
370 info = OsGetMapInfo(fpage, &region->space->archMmu, (vaddr_t)vmf->vaddr);//通过虚拟地址获取映射信息
371 if (info != NULL) {
372 fpage->n_maps--;
373 LOS_ListDelete(&info->node);
375 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
377 return;
378 }
379 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
380}
STATIC INLINE VOID LOS_AtomicDec(Atomic *v)
Atomic auto-decrement. | 对32bit原子数据做减1
Definition: los_atomic.h:323
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
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 long vaddr_t
Definition: los_typedef.h:206
unsigned int UINT32
Definition: los_typedef.h:57
LosMapInfo * OsGetMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
通过虚拟地址获取文件页映射信息,archMmu每个进程都有属于自己的mmu
LosFilePage * OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff)
STATIC INLINE VOID OsCleanPageDirty(LosVmPage *page)
给页面撕掉数据被修改的标签
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
映射类型为文件的线性区是否有效
Definition: los_vm_map.c:512
文件页结构体
struct VmPage * vmPage
物理页框
struct VmMapRegion::@4::VmRegionFile rf
union VmMapRegion::@4 unTypeData
LosVmSpace * space
所属虚拟空间,虚拟空间由多个线性区组成
Definition: los_vm_map.h:121
Atomic refCounts
Definition: los_vm_page.h:57
LosArchMmu archMmu
Definition: los_vm_map.h:157
SPIN_LOCK_S list_lock
函数调用图:
这是这个函数的调用关系图:

◆ OsDoFlushDirtyPage()

VOID OsDoFlushDirtyPage ( LosFilePage fpage)

冲洗脏页数据,将脏页数据回写磁盘

在文件 los_vm_filemap.c326 行定义.

327{
328 if (fpage == NULL) {
329 return;
330 }
331 (VOID)OsFlushDirtyPage(fpage);
333}
STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
冲洗脏页,回写磁盘
函数调用图:
这是这个函数的调用关系图:

◆ OsDumpDirtyPage()

LosFilePage * OsDumpDirtyPage ( LosFilePage oldPage)

备份脏页,老脏页撕掉脏页标签

在文件 los_vm_filemap.c310 行定义.

311{
312 LosFilePage *newFPage = NULL;
313
314 newFPage = (LosFilePage *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosFilePage));
315 if (newFPage == NULL) {
316 VM_ERR("Failed to allocate for temp page!");
317 return NULL;
318 }
319
320 OsCleanPageDirty(oldFPage->vmPage);
321 (VOID)memcpy_s(newFPage, sizeof(LosFilePage), oldFPage, sizeof(LosFilePage));//直接内存拷贝
322
323 return newFPage;
324}
struct FilePage LosFilePage
文件页结构体
函数调用图:
这是这个函数的调用关系图:

◆ OsFileCacheFlush()

VOID OsFileCacheFlush ( struct page_mapping mapping)

文件缓存冲洗,把所有fpage冲洗一边,把脏页洗到dirtyList中,配合OsFileCacheRemove理解

在文件 los_vm_filemap.c453 行定义.

454{
455 UINT32 intSave;
456 UINT32 lruLock;
457 LOS_DL_LIST_HEAD(dirtyList);//LOS_DL_LIST list = { &(list), &(list) };
458 LosFilePage *ftemp = NULL;
459 LosFilePage *fpage = NULL;
460
461 if (mapping == NULL) {
462 return;
463 }
464 LOS_SpinLockSave(&mapping->list_lock, &intSave);
465 LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {//循环从page_list中取node给fpage
466 LOS_SpinLockSave(&fpage->physSeg->lruLock, &lruLock);
467 if (OsIsPageDirty(fpage->vmPage)) {//是否为脏页
468 ftemp = OsDumpDirtyPage(fpage);//这里挺妙的,copy出一份新页,老页变成了非脏页继续用
469 if (ftemp != NULL) {
470 LOS_ListTailInsert(&dirtyList, &ftemp->node);//将新页插入脏页List,等待回写磁盘
471 }
472 }
473 LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, lruLock);
474 }
475 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
476
477 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, ftemp, &dirtyList, LosFilePage, node) {//仔细看这个宏,关键在 &(item)->member != (list);
478 OsDoFlushDirtyPage(fpage);//立马洗掉,所以dirtyList可以不是全局变量
479 }
480}
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
LosFilePage * OsDumpDirtyPage(LosFilePage *oldFPage)
备份脏页,老脏页撕掉脏页标签
VOID OsDoFlushDirtyPage(LosFilePage *fpage)
冲洗脏页数据,将脏页数据回写磁盘
STATIC INLINE BOOL OsIsPageDirty(LosVmPage *page)
页面是否为脏页,所谓脏页就是页内数据是否被更新过,只有脏页才会有写时拷贝
LOS_DL_LIST_HEAD(g_vmSpaceList)
初始化全局虚拟空间节点,所有虚拟空间都挂到此节点上.
struct VmPhysSeg * physSeg
LOS_DL_LIST node
节点,节点挂到page_mapping.page_list上,链表以 pgoff 从小到大方式排序.
SPIN_LOCK_S lruLock
用于置换的自旋锁,用于操作lruList
Definition: los_vm_phys.h:91
LOS_DL_LIST page_list
函数调用图:
这是这个函数的调用关系图:

◆ OsFileCacheRemove()

VOID OsFileCacheRemove ( struct page_mapping mapping)

在文件 los_vm_filemap.c486 行定义.

487{
488 UINT32 intSave;
489 UINT32 lruSave;
490 SPIN_LOCK_S *lruLock = NULL;
491 LOS_DL_LIST_HEAD(dirtyList);//定义一个叫dirtyList的双循环链表并初始化,用于挂脏页
492 LosFilePage *ftemp = NULL;
493 LosFilePage *fpage = NULL;
494 LosFilePage *fnext = NULL;
495
496 LOS_SpinLockSave(&mapping->list_lock, &intSave);//多进程操作,必须上锁.
497 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &mapping->page_list, LosFilePage, node) {//遍历文件在内存中产生的所有文件页(例如1,4,8页)不一定连续,取决于用户的读取顺序
498 lruLock = &fpage->physSeg->lruLock;
499 LOS_SpinLockSave(lruLock, &lruSave);//@note_why 自旋锁有必要从这里开始上锁吗?
500 if (OsIsPageDirty(fpage->vmPage)) {//数据是脏页吗,脏页就是被修改过数据的页
501 ftemp = OsDumpDirtyPage(fpage);//做这个拷贝动作是为了fpage的统一下线,因为数据回写磁盘的速度是很慢的,如果直接在这里处理脏数据
502 if (ftemp != NULL) {//会导致函数持有mapping->list_lock自旋锁的时间太长了,影响其他CPU的处理效率
503 LOS_ListTailInsert(&dirtyList, &ftemp->node);//将临时脏页挂到记录脏页链表上
504 }
505 }
506
507 OsDeletePageCacheLru(fpage);//删除高速缓存和从置换链表中下线
508 LOS_SpinUnlockRestore(lruLock, lruSave);
509 }
510 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);//恢复自旋锁,不能让别的CPU等太久
511
512 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &dirtyList, LosFilePage, node) {//到这里,再来慢慢的统一处理脏页数据
513 OsDoFlushDirtyPage(fpage);//遍历脏页链表,一页一页处理
514 }
515}
VOID OsDeletePageCacheLru(LosFilePage *page)
删除页高速缓存和LRU,对应 OsAddToPageacheLru
函数调用图:
这是这个函数的调用关系图:

◆ OsFindGetEntry()

LosFilePage * OsFindGetEntry ( struct page_mapping mapping,
VM_OFFSET_T  pgoff 
)

在文件 los_vm_filemap.c571 行定义.

572{
573 LosFilePage *fpage = NULL;
574
575 LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {//遍历文件页
576 if (fpage->pgoff == pgoff) {//找到指定的页,
577 return fpage;
578 }
579
580 if (fpage->pgoff > pgoff) {//大于之前还没有找到,说明不在链表中,往后的也不用找了,
581 break;//因为 mapping->page_list节点上的数据都是按 fpage->pgoff 从小到大的顺序排列的.
582 }
583 }
584
585 return NULL;
586}
VM_OFFSET_T pgoff
页标,文件被切成一页一页读到内存
这是这个函数的调用关系图:

◆ OsGetMapInfo()

LosMapInfo * OsGetMapInfo ( LosFilePage page,
LosArchMmu archMmu,
VADDR_T  vaddr 
)

通过虚拟地址获取文件页映射信息,archMmu每个进程都有属于自己的mmu

在文件 los_vm_filemap.c144 行定义.

145{
146 LosMapInfo *info = NULL;
147 LOS_DL_LIST *immap = &page->i_mmap;//一个文件页被多个进程映射
148
149 LOS_DL_LIST_FOR_EACH_ENTRY(info, immap, LosMapInfo, node) {//遍历每个节点
150 if ((info->archMmu == archMmu) && (info->vaddr == vaddr) && (info->page == page)) {//全等时返回
151 return info;
152 }
153 }
154 return NULL;
155}
这是这个函数的调用关系图:

◆ OsIsPageActive()

STATIC INLINE BOOL OsIsPageActive ( LosVmPage page)

页面是否活动

在文件 los_vm_filemap.h190 行定义.

191{
192 return BIT_GET(page->flags, FILE_PAGE_ACTIVE);
193}
这是这个函数的调用关系图:

◆ OsIsPageDirty()

STATIC INLINE BOOL OsIsPageDirty ( LosVmPage page)

页面是否为脏页,所谓脏页就是页内数据是否被更新过,只有脏页才会有写时拷贝

在文件 los_vm_filemap.h205 行定义.

206{
207 return BIT_GET(page->flags, FILE_PAGE_DIRTY);
208}
这是这个函数的调用关系图:

◆ OsIsPageLocked()

STATIC INLINE BOOL OsIsPageLocked ( LosVmPage page)

页面是否被锁

在文件 los_vm_filemap.h195 行定义.

196{
197 return BIT_GET(page->flags, FILE_PAGE_LOCKED);
198}
这是这个函数的调用关系图:

◆ OsIsPageMapped()

STATIC INLINE BOOL OsIsPageMapped ( LosFilePage page)

文件页是否映射过了

在文件 los_vm_filemap.h210 行定义.

211{
212 return (page->n_maps != 0);//由映射的次数来判断
213}
这是这个函数的调用关系图:

◆ OsIsPageReferenced()

STATIC INLINE BOOL OsIsPageReferenced ( LosVmPage page)

页面是否被引用,只被一个进程引用的页叫私有页,多个进程引用就是共享页,此为共享内存的本质所在

在文件 los_vm_filemap.h200 行定义.

201{
202 return BIT_GET(page->flags, FILE_PAGE_REFERENCED);
203}
这是这个函数的调用关系图:

◆ OsIsPageShared()

STATIC INLINE BOOL OsIsPageShared ( LosVmPage page)

是否为共享页

在文件 los_vm_filemap.h226 行定义.

227{
228 return BIT_GET(page->flags, FILE_PAGE_SHARED);
229}
这是这个函数的调用关系图:

◆ OsLruCacheAdd()

VOID OsLruCacheAdd ( LosFilePage fpage,
enum OsLruList  lruType 
)

在文件 los_vm_scan.c69 行定义.

70{
71 UINT32 intSave;
72 LosVmPhysSeg *physSeg = fpage->physSeg; //得到页面对应段
73 LosVmPage *page = fpage->vmPage; //得到物理页面
74
75 LOS_SpinLockSave(&physSeg->lruLock, &intSave);//自旋锁:最多只能被一个内核持有,CPU内核 互斥锁
76 OsSetPageActive(page); //设置页面为活动页
77 OsCleanPageReferenced(page);//清除页面被引用位
78 physSeg->lruSize[lruType]++; //lruType页总size++
79 LOS_ListTailInsert(&physSeg->lruList[lruType], &fpage->lru);//加入lruType页双循环链表中
80
81 LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);//解锁
82}
STATIC INLINE VOID OsSetPageActive(LosVmPage *page)
给页面贴上活动的标签
STATIC INLINE VOID OsCleanPageReferenced(LosVmPage *page)
给页面撕掉被引用的标签
LOS_DL_LIST lru
lru节点, 结合 LosVmPhysSeg: LOS_DL_LIST lruList[VM_NR_LRU_LISTS] 理解
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
Definition: los_vm_page.h:53
物理段描述符
Definition: los_vm_phys.h:85
LOS_DL_LIST lruList[VM_NR_LRU_LISTS]
页面置换算法,5个双循环链表头,它们分别描述五中不同类型的链表
Definition: los_vm_phys.h:93
size_t lruSize[VM_NR_LRU_LISTS]
5个双循环链表大小,如此方便得到size
Definition: los_vm_phys.h:92
函数调用图:
这是这个函数的调用关系图:

◆ OsLruCacheDel()

VOID OsLruCacheDel ( LosFilePage fpage)

在文件 los_vm_scan.c85 行定义.

86{
87 LosVmPhysSeg *physSeg = fpage->physSeg; //得到页面对应段
88 int type = OsIsPageActive(fpage->vmPage) ? VM_LRU_ACTIVE_FILE : VM_LRU_INACTIVE_FILE;//得到页面LRU类型
89
90 physSeg->lruSize[type]--; //type页总size--
91 LOS_ListDelete(&fpage->lru);//将自己从lru链表中摘出来
92}
STATIC INLINE BOOL OsIsPageActive(LosVmPage *page)
页面是否活动
@ VM_LRU_ACTIVE_FILE
活动文件页(磁盘)
Definition: los_vm_phys.h:78
@ VM_LRU_INACTIVE_FILE
非活动文件页(磁盘)
Definition: los_vm_phys.h:77
函数调用图:
这是这个函数的调用关系图:

◆ OsMarkPageDirty()

VOID OsMarkPageDirty ( LosFilePage fpage,
LosVmMapRegion region,
int  off,
int  len 
)
这是这个函数的调用关系图:

◆ OsNamedMMap()

STATUS_T OsNamedMMap ( struct file filep,
LosVmMapRegion region 
)

有名映射,可理解为文件映射,跟匿名映射相对应 参数filep是广义的文件,在鸿蒙内核,目录/普通文件/字符设备/块设备/网络套接字/管道/链接 都是文件

在文件 los_vm_filemap.c536 行定义.

537{
538 struct Vnode *vnode = NULL;
539 if (filep == NULL) {
540 return LOS_ERRNO_VM_MAP_FAILED;
541 }
542 file_hold(filep);
543 vnode = filep->f_vnode;
544 VnodeHold();
545 vnode->useCount++;
546 VnodeDrop();
547 if (filep->ops != NULL && filep->ops->mmap != NULL) {
548 if (vnode->type == VNODE_TYPE_CHR || vnode->type == VNODE_TYPE_BLK) {//块设备或者字符设备 /dev/..
549 LOS_SetRegionTypeDev(region);//设置为设备类型
550 } else {
551 LOS_SetRegionTypeFile(region);//设置为文件类型
552 }
553 int ret = filep->ops->mmap(filep, region);
554 if (ret != LOS_OK) {
555 file_release(filep);
556 return LOS_ERRNO_VM_MAP_FAILED;
557 }
558 } else {
559 VM_ERR("mmap file type unknown");
560 file_release(filep);
561 return LOS_ERRNO_VM_MAP_FAILED;
562 }
563 file_release(filep);
564 return LOS_OK;
565}
STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion *region)
设置线性区为文件映射
Definition: los_vm_map.h:250
STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion *region)
设为设备映射线性区
Definition: los_vm_map.h:260
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
enum VnodeType type
Definition: vnode.h:165
int useCount
Definition: vnode.h:166
int VnodeDrop(void)
归还锁
Definition: vnode.c:292
@ VNODE_TYPE_CHR
Definition: vnode.h:139
@ VNODE_TYPE_BLK
Definition: vnode.h:138
int VnodeHold(void)
拿锁,封装互斥量
Definition: vnode.c:283
函数调用图:
这是这个函数的调用关系图:

◆ OsPageCacheAlloc()

LosFilePage * OsPageCacheAlloc ( struct page_mapping mapping,
VM_OFFSET_T  pgoff 
)

以页高速缓存方式分配一个文件页 LosFilePage Direct Memory Access(存储器直接访问)指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据。 整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU只需在数据传输开始和结束时做一点处理(开始和结束时候要做中断处理)

在文件 los_vm_filemap.c594 行定义.

595{
596 VOID *kvaddr = NULL;
597 LosVmPhysSeg *physSeg = NULL;
598 LosVmPage *vmPage = NULL;
599 LosFilePage *fpage = NULL;
600
601 vmPage = LOS_PhysPageAlloc(); //先分配一个物理页
602 if (vmPage == NULL) {
603 VM_ERR("alloc vm page failed");
604 return NULL;
605 }
606 physSeg = OsVmPhysSegGet(vmPage);//通过页获取所在seg
607 kvaddr = OsVmPageToVaddr(vmPage);//获取内核空间的虚拟地址,具体点进去看函数说明,这里一定要理解透彻!
608 if ((physSeg == NULL) || (kvaddr == NULL)) {
609 LOS_PhysPageFree(vmPage); //异常情况要释放vmPage
610 VM_ERR("alloc vm page failed!");
611 return NULL;
612 }
613
614 fpage = (LosFilePage *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosFilePage));//从内存池中分配一个filePage
615 if (fpage == NULL) {
616 LOS_PhysPageFree(vmPage); //异常情况要释放vmPage
617 VM_ERR("Failed to allocate for page!");
618 return NULL;
619 }
620
621 (VOID)memset_s((VOID *)fpage, sizeof(LosFilePage), 0, sizeof(LosFilePage));//调标准库函数 置0
622
623 LOS_ListInit(&fpage->i_mmap); //初始化映射,链表上挂 MapInfo
624 LOS_ListInit(&fpage->node); //节点初始化
625 LOS_ListInit(&fpage->lru); //LRU初始化
626 fpage->n_maps = 0; //映射次数
627 fpage->dirtyOff = PAGE_SIZE; //默认页尾部,相当于没有脏数据
628 fpage->dirtyEnd = 0; //脏页结束位置
629 fpage->physSeg = physSeg; //页框所属段.其中包含了 LRU LIST ==
630 fpage->vmPage = vmPage; //物理页框
631 fpage->mapping = mapping; //记录所有文件页映射
632 fpage->pgoff = pgoff; //将文件切成一页页,页标
633 (VOID)memset_s(kvaddr, PAGE_SIZE, 0, PAGE_SIZE);//页内数据清0
634
635 return fpage;
636}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
VOID LOS_PhysPageFree(LosVmPage *page)
释放一个物理页框
Definition: los_vm_phys.c:546
struct VmPhysSeg * OsVmPhysSegGet(LosVmPage *page)
获取物理页框所在段
Definition: los_vm_phys.c:643
LosVmPage * LOS_PhysPageAlloc(VOID)
申请一个物理页
Definition: los_vm_phys.c:566
VOID * OsVmPageToVaddr(LosVmPage *page)
通过page获取内核空间的虚拟地址 参考OsArchMmuInit #define SYS_MEM_BASE DDR_MEM_ADDR /* physical memory base 物理地址的起始...
Definition: los_vm_phys.c:288
UINT16 dirtyOff
脏页的页内偏移地址
struct page_mapping * mapping
此结构由文件系统提供,用于描述装入点 见于 ..\third_party\NuttX\fs\fs.h
UINT16 dirtyEnd
脏页的结束位置
函数调用图:
这是这个函数的调用关系图:

◆ OsPageRefDecNoLock()

VOID OsPageRefDecNoLock ( LosFilePage page)

在文件 los_vm_scan.c189 行定义.

190{
191 BOOL isOrgActive;
192 LosVmPage *page = NULL;
193
194 if (fpage == NULL) {
195 return;
196 }
197
198 page = fpage->vmPage;
199 isOrgActive = OsIsPageActive(page);
200
201 if (!OsIsPageReferenced(page) && OsIsPageActive(page)) {//[ref:0,act:1]的情况
202 OsCleanPageActive(page);
204 } else if (OsIsPageReferenced(page)) {
206 }
207
208 if (isOrgActive && !OsIsPageActive(page)) {
210 }
211}
size_t BOOL
Definition: los_typedef.h:88
STATIC INLINE BOOL OsIsPageReferenced(LosVmPage *page)
页面是否被引用,只被一个进程引用的页叫私有页,多个进程引用就是共享页,此为共享内存的本质所在
STATIC INLINE VOID OsSetPageReferenced(LosVmPage *page)
给页面贴上被引用的标签
STATIC INLINE VOID OsCleanPageActive(LosVmPage *page)
给页面撕掉活动的标签
STATIC INLINE VOID OsMoveToInactiveList(LosFilePage *fpage)
Definition: los_vm_scan.c:112
函数调用图:
这是这个函数的调用关系图:

◆ OsPageRefIncLocked()

VOID OsPageRefIncLocked ( LosFilePage page)

在文件 los_vm_scan.c145 行定义.

146{
147 BOOL isOrgActive;
148 UINT32 intSave;
149 LosVmPage *page = NULL;
150
151 if (fpage == NULL) {
152 return;
153 }
154
155 LOS_SpinLockSave(&fpage->physSeg->lruLock, &intSave);//要处理lruList,先拿锁
156
157 page = fpage->vmPage;//拿到物理页框
158 isOrgActive = OsIsPageActive(page);//页面是否在活动
159
160 if (OsIsPageReferenced(page) && !OsIsPageActive(page)) {//身兼 不活动和引用标签
161 OsCleanPageReferenced(page);//撕掉引用标签 ref:1, act:0 --> ref:0, act:1
162 OsSetPageActive(page); //贴上活动标签
163 } else if (!OsIsPageReferenced(page)) {
164 OsSetPageReferenced(page);//ref:0, act:0 --> ref:1, act:0
165 }
166
167 if (!isOrgActive && OsIsPageActive(page)) {
168 /* move inactive to active */
169 OsMoveToActiveList(fpage);
170 /* no change, move head */
171 } else {
172 if (OsIsPageActive(page)) {
173 OsMoveToActiveHead(fpage);
174 } else {
176 }
177 }
178
179 LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, intSave);
180}
STATIC INLINE VOID OsMoveToActiveList(LosFilePage *fpage)
Definition: los_vm_scan.c:101
STATIC INLINE VOID OsMoveToActiveHead(LosFilePage *fpage)
Definition: los_vm_scan.c:123
STATIC INLINE VOID OsMoveToInactiveHead(LosFilePage *fpage)
Definition: los_vm_scan.c:131
函数调用图:
这是这个函数的调用关系图:

◆ OsSetPageActive()

STATIC INLINE VOID OsSetPageActive ( LosVmPage page)

给页面贴上活动的标签

在文件 los_vm_filemap.h155 行定义.

156{
158}
VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos)
对状态字的某一标志位进行置1操作
Definition: los_bitmap.c:60
函数调用图:
这是这个函数的调用关系图:

◆ OsSetPageDirty()

STATIC INLINE VOID OsSetPageDirty ( LosVmPage page)

给页面贴上数据被修改的标签

在文件 los_vm_filemap.h145 行定义.

146{
148}
函数调用图:
这是这个函数的调用关系图:

◆ OsSetPageFree()

STATIC INLINE VOID OsSetPageFree ( LosVmPage page)

给页面贴上被释放的标签

在文件 los_vm_filemap.h170 行定义.

171{
173}
函数调用图:

◆ OsSetPageLocked()

STATIC INLINE VOID OsSetPageLocked ( LosVmPage page)

给页面贴上被锁的标签

在文件 los_vm_filemap.h135 行定义.

136{
138}
函数调用图:
这是这个函数的调用关系图:

◆ OsSetPageLRU()

STATIC INLINE VOID OsSetPageLRU ( LosVmPage page)

给页面贴上置换页的标签

在文件 los_vm_filemap.h165 行定义.

166{
168}
函数调用图:

◆ OsSetPageReferenced()

STATIC INLINE VOID OsSetPageReferenced ( LosVmPage page)

给页面贴上被引用的标签

在文件 los_vm_filemap.h180 行定义.

181{
183}
函数调用图:
这是这个函数的调用关系图:

◆ OsSetPageShared()

STATIC INLINE VOID OsSetPageShared ( LosVmPage page)

The follow three functions is used to SHM module | 给页面贴上共享页标签

在文件 los_vm_filemap.h216 行定义.

217{
218 LOS_BitmapSet(&page->flags, FILE_PAGE_SHARED);//设为共享页面,共享页位 置0
219}
函数调用图:
这是这个函数的调用关系图:

◆ OsTryShrinkMemory()

int OsTryShrinkMemory ( size_t  nPage)

在文件 los_vm_scan.c340 行定义.

341{
342 return 0;
343}
函数调用图:
这是这个函数的调用关系图:

◆ OsUnmapAllLocked()

VOID OsUnmapAllLocked ( LosFilePage page)

解除文件页在所有进程的映射

在文件 los_vm_scan.c57 行定义.

58{
59 LosMapInfo *info = NULL;
60 LosMapInfo *next = NULL;
61 LOS_DL_LIST *immap = &page->i_mmap;
62
63 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(info, next, immap, LosMapInfo, node) {//遍历 immap->info 链表
64 OsUnmapPageLocked(page, info);
65 }
66}
VOID OsUnmapPageLocked(LosFilePage *page, LosMapInfo *info)
Definition: los_vm_scan.c:44
函数调用图:
这是这个函数的调用关系图:

◆ OsUnmapPageLocked()

VOID OsUnmapPageLocked ( LosFilePage page,
LosMapInfo info 
)

在文件 los_vm_scan.c44 行定义.

45{
46 if (page == NULL || info == NULL) {
47 VM_ERR("UnmapPage error input null!");
48 return;
49 }
50 page->n_maps--;
51 LOS_ListDelete(&info->node);
53 LOS_ArchMmuUnmap(info->archMmu, info->vaddr, 1);
54 LOS_MemFree(m_aucSysMem0, info);//释放虚拟
55}
STATUS_T LOS_ArchMmuUnmap(LosArchMmu *archMmu, VADDR_T vaddr, size_t count)
LOS_ArchMmuUnmap 解除进程空间虚拟地址区间与物理地址区间的映射关系
Definition: los_arch_mmu.c:619
函数调用图:
这是这个函数的调用关系图:

◆ OsVfsFileMmap()

INT32 OsVfsFileMmap ( struct file filep,
LosVmMapRegion region 
)

在文件 los_vm_filemap.c639 行定义.

640{
641 UNUSED(filep);
642 UNUSED(region);
643 return ENOERR;
644}

◆ OsVmmFileRegionFree()

VOID OsVmmFileRegionFree ( struct file filep,
LosProcessCB processCB 
)

◆ ResetPageCacheHitInfo()

VOID ResetPageCacheHitInfo ( int try,
int hit 
)

在文件 los_vm_filemap.c58 行定义.

59{
64}
static int g_totalPageCacheTry
static int g_totalPageCacheHit
这是这个函数的调用关系图: