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

文件是如何映射到内存的?理解页高速缓存(page cache)是关键

搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
搜索 @note_#if0 是由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的。
上级 add28132
......@@ -25,9 +25,11 @@
搜索 **[@note_pic]()** 可查看绘制的全部字符图
搜索 **[@note_why]()** 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 **[@note_why]()** 是注者尚未看明白的地方,如果您看明白了,请Pull Request告诉注者完善
搜索 **[@note_thinking]()** 是注者的思考和吐槽鸿蒙源码的地方
搜索 **[@note_thinking]()** 是注者的思考和建议
搜索 **[@note_#if0]()** 是由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的。
- ### **理解内核的三个层级**
......
......@@ -37,17 +37,18 @@
#include "los_list.h"
#include "los_atomic.h"
#include "los_vm_filemap.h"
/******************************************************************
#if 0 //@note_#if0
定义见于 ..\third_party\NuttX\include\nuttx\fs\fs.h
typedef volatile INT32 Atomic;
struct page_mapping {
LOS_DL_LIST page_list; /* all pages * /
SPIN_LOCK_S list_lock; /* lock protecting it * /
LOS_DL_LIST page_list; /* all pages */
SPIN_LOCK_S list_lock; /* lock protecting it */
LosMux mux_lock; /* mutex lock * /
unsigned long nrpages; /* number of total pages * /
unsigned long nrpages; /* number of total pages */
unsigned long flags;
Atomic ref; /* reference counting * /
struct file *host; /* owner of this mapping * /
Atomic ref; /* reference counting */
struct file *host; /* owner of this mapping */
};
/* map: full_path(owner) <-> mapping * /
......@@ -60,26 +61,32 @@ struct file_map {
struct file
{
unsigned int f_magicnum; /* file magic number * /
int f_oflags; /* Open mode flags * /
FAR struct inode *f_inode; /* Driver interface * /
loff_t f_pos; /* File position * /
unsigned long f_refcount; /* reference count * /
char *f_path; /* File fullpath * /
void *f_priv; /* Per file driver private data * /
const char *f_relpath; /* realpath * /
struct page_mapping *f_mapping; /* mapping file to memory * /
void *f_dir; /* DIR struct for iterate the directory if open a directory * /
unsigned int f_magicnum; /* file magic number */
int f_oflags; /* Open mode flags */
FAR struct inode *f_inode; /* Driver interface */
loff_t f_pos; /* File position */
unsigned long f_refcount; /* reference count */
char *f_path; /* File fullpath */
void *f_priv; /* Per file driver private data */
const char *f_relpath; /* realpath */
struct page_mapping *f_mapping; /* mapping file to memory */
void *f_dir; /* DIR struct for iterate the directory if open a directory */
};
#endif
******************************************************************/
static struct file_map g_file_mapping = {0};
//初始化文件映射
/**************************************************************************************************
初始化文件映射模块,
file_map: 每个需映射到内存的文件必须创建一个 file_map,都挂到全部g_file_mapping链表上
page_mapping: 记录的是<文件,文件页>的关系,一个文件在操作过程中被映射成了多少个页,
file:是文件系统管理层面的概念
**************************************************************************************************/
uint init_file_mapping()
{
uint ret;
LOS_ListInit(&g_file_mapping.head);//初始化文件映射的链表
LOS_ListInit(&g_file_mapping.head);//初始化全局文件映射节点,所有文件的映射都将g_file_mapping.head挂在链表上
ret = LOS_MuxInit(&g_file_mapping.lock, NULL);//初始化文件映射互斥锁
if (ret != LOS_OK) {
......@@ -88,20 +95,24 @@ uint init_file_mapping()
return ret;
}
//通过文件名查找文件映射,不用锁的方式
//以无锁的方式通过文件名查找文件映射并返回
static struct page_mapping *find_mapping_nolock(const char *fullpath)
{
struct file_map *fmap = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(fmap, &g_file_mapping.head, struct file_map, head) {//遍历文件映射链表
if (!strcmp(fmap->owner, fullpath)) {//对比文件路径
if (!strcmp(fmap->owner, fullpath)) {//用整个文件路径来标识文件的唯一性
return &fmap->mapping;
}
}
return NULL;
}
//添加一个文件映射
/**************************************************************************************************
增加一个文件映射,这个函数被do_open()函数调用,每打开一次文件就会调用一次
注意不同的进程打开同一个文件,拿到的file是不一样的。
https://blog.csdn.net/cywosp/article/details/38965239
**************************************************************************************************/
void add_mapping(struct file *filep, const char *fullpath)
{
void *tmp = NULL;
......@@ -118,7 +129,7 @@ void add_mapping(struct file *filep, const char *fullpath)
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);//操作临界区,先拿锁
path_len = strlen(fullpath) + 1;
mapping = find_mapping_nolock(fullpath);//先看有米有映射过
mapping = find_mapping_nolock(fullpath);//是否已有文件映射
if (mapping) {//有映射过的情况
LOS_AtomicInc(&mapping->ref);//引用自增
filep->f_mapping = mapping;//赋值
......@@ -131,9 +142,9 @@ void add_mapping(struct file *filep, const char *fullpath)
fmap = (struct file_map *)LOS_MemAlloc(m_aucSysMem0, fmap_len);//分配一个file_map
/* page-cache as a optimization feature, just return when out of memory *///页面缓存作为一个优化功能,当内存不足时返回
/* page-cache as a optimization feature, just return when out of memory */
if (!fmap) {
if (!fmap) {//页面缓存作为一个优化功能,当内存不足时返回
PRINT_WARN("%s-%d: Mem alloc failed. fmap length(%d)\n",
__FUNCTION__, __LINE__, fmap_len);
return;
......@@ -150,9 +161,9 @@ void add_mapping(struct file *filep, const char *fullpath)
}
(void)memset_s(fmap, fmap_len, 0, fmap_len);//清0
fmap->owner = tmp;//赋值,此时owner指向内核区
fmap->owner = tmp;//赋值,此时owner指向内核区,但要记得释放掉
LOS_AtomicSet(&fmap->mapping.ref, 1);//引用设为1
(void)strcpy_s(fmap->owner, path_len, fullpath);//从用户区 拷贝到内核区
(void)strcpy_s(fmap->owner, path_len, fullpath);//将参数fullpath由用户区拷贝到内核区 @note_thinking 鸿蒙提供了专门的拷贝函数 arch_copy_from_user 为啥不用?
LOS_ListInit(&fmap->mapping.page_list);//初始化文件映射的页表链表,上面将会挂这个文件映射的所有虚拟内存页
LOS_SpinInit(&fmap->mapping.list_lock);//初始化文件映射的自旋锁
......@@ -160,16 +171,16 @@ void add_mapping(struct file *filep, const char *fullpath)
if (retval != LOS_OK) {
PRINT_ERR("%s %d, Create mutex for mapping.mux_lock failed, status: %d\n", __FUNCTION__, __LINE__, retval);
}
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);//先拿全局变量g_file_mapping的互斥锁
LOS_ListTailInsert(&g_file_mapping.head, &fmap->head);//因为要将本次文件挂上去
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);//拿锁操作g_file_mapping
LOS_ListTailInsert(&g_file_mapping.head, &fmap->head);//将文件映射结点挂入全局链表
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);//释放锁
filep->f_mapping = &fmap->mapping;//映射互绑操作,都是自己人了,
filep->f_mapping->host = filep;//文件互绑操作,亲上加亲了。
filep->f_mapping = &fmap->mapping;//<file,file_map>之间互绑
filep->f_mapping->host = filep;//<file,file_map>之间互绑,从此相亲相爱一家人
return;
}
//查找文件映射
//通过参数路径查找文件映射并返回
struct page_mapping *find_mapping(const char *fullpath)
{
struct page_mapping *mapping = NULL;
......@@ -180,7 +191,7 @@ struct page_mapping *find_mapping(const char *fullpath)
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
mapping = find_mapping_nolock(fullpath);//找
mapping = find_mapping_nolock(fullpath);//找啊找!外面加锁了,就无需再锁了
if (mapping) {//找到
LOS_AtomicInc(&mapping->ref);//引用自增
}
......@@ -189,7 +200,7 @@ struct page_mapping *find_mapping(const char *fullpath)
return mapping;
}
//引用递减
//引用递减,删除或关闭文件时 由 files_close_internal调用
void dec_mapping(struct page_mapping *mapping)
{
if (mapping == NULL) {
......@@ -202,17 +213,17 @@ void dec_mapping(struct page_mapping *mapping)
}
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
}
//清除文件映射,无锁方式
//以无锁方式清除文件映射
void clear_file_mapping_nolock(const struct page_mapping *mapping)
{
unsigned int i = 3; /* file start fd */
struct file *filp = NULL;
while (i < CONFIG_NFILE_DESCRIPTORS) {//循环遍历查找
while (i < CONFIG_NFILE_DESCRIPTORS) {//循环遍历查找,0,1,2已经固定分配了,固从3始
filp = &tg_filelist.fl_files[i];//一个个来
if (filp->f_mapping == mapping) {//发现一样
filp->f_mapping = NULL;//直接NULL,注意这里并没有break,而是继续撸到最后,这里如果break了会怎样? @note_thinking
}
if (filp->f_mapping == mapping) {//找到了
filp->f_mapping = NULL;//直接NULL,注意这里并没有break,而是继续撸到最后,因为 file:mapping 是 N:1的关系
}//仔细想想:多个进程会使用同一个page_mapping,因为page_mapping的创建是由fullPath来唯一标识的
i++;
}
}
......@@ -295,7 +306,7 @@ int remove_mapping(const char *fullpath, const struct file *ex_filp)
(void)sem_post(&f_list->fl_sem);//发出信号量
return OK;
}
//重命名文件映射,
void rename_mapping(const char *src_path, const char *dst_path)
{
int ret;
......
......@@ -97,7 +97,7 @@ void los_vfs_init(void)//系统调用了los_vfs_init()后,会将"/"作为root_
}
dev->i_mode |= S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
retval = init_file_mapping();//初始化文件映射
retval = init_file_mapping();//初始化文件映射模块
if (retval != LOS_OK) {
PRINT_ERR("Page cache file map init failed\n");
return;
......
......@@ -48,6 +48,41 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/**************************************************************************************************
磁盘高速缓存是一种软件机制,它允许系统把通常存放在磁盘上的一些数据保留在 RAM 中,以便对那些数据的
进一步访问不用再访问磁盘而能尽快得到满足。
页高速缓存中的信息单位是一个完整的页。
一个页包含的磁盘块在物理上不一定相邻,所以不能用设备号和块号标识,而是通过页的所有者和所有者数据中的索引来识别。
页高速缓存可以缓存以下内容
A.普通文件数据
B.含有目录的页
C.直接从快设备读取的页
D.用户进程数据的页
E.特殊文件系统的文件页
**************************************************************************************************/
#if 0 //@note_#if0
//page_mapping描述的是一个文件在内存中被映射了多少页,<文件,文件页的关系>
/* file mapped in VMM pages */
struct page_mapping {
LOS_DL_LIST page_list; /* all pages */ //文件映射的所有页链表,这些页的内容都来源同一个文件
SPIN_LOCK_S list_lock; /* lock protecting it */
LosMux mux_lock; /* mutex lock */ //
unsigned long nrpages; /* number of total pages */
unsigned long flags;
Atomic ref; /* reference counting */
struct file *host; /* owner of this mapping *///属于哪个文件的映射
};
/* map: full_path(owner) <-> mapping */
struct file_map {
LOS_DL_LIST head;
LosMux lock; /* lock to protect this mapping */
struct page_mapping mapping;
char *owner; /* owner: full path of file */
};
#endif
//文件页结构体
typedef struct FilePage {
LOS_DL_LIST node; //节点
......
......@@ -89,9 +89,9 @@ struct VmSpace;
typedef struct VmSpace LosVmSpace;
//缺页结构信息体
typedef struct VmFault {
UINT32 flags; /* FAULT_FLAG_xxx flags */
unsigned long pgoff; /* Logical page offset based on region */
VADDR_T vaddr; /* Faulting virtual address */
UINT32 flags; /* FAULT_FLAG_xxx flags */ //缺页标识
unsigned long pgoff; /* Logical page offset based on region */ //基于线性区的逻辑页偏移量
VADDR_T vaddr; /* Faulting virtual address */ //产生缺页的虚拟地址
VADDR_T *pageKVaddr; /* KVaddr of pagefault's vm page's paddr */
//pageKVaddr为缺页的vm页面物理地址对应的内核虚拟地址,这里要说明下啥意思,缺页的意思是此进程的虚拟空间中没有这个虚拟地址的映射,
//但并不代表物理页框没有被别的进程虚拟空间所映射.一定要理解这里!
......
......@@ -60,7 +60,7 @@ struct VmFreeList {
UINT32 listCnt; //双循环链表节点总数
};
//针对匿名页和文件页各拆分成一个活跃,一个不活跃的链表。
enum OsLruList {
enum OsLruList {//Lru全称是Least Recently Used,即最近最久未使用的意思
VM_LRU_INACTIVE_ANON = 0, //非活动匿名页 LRU 链表(swap)
VM_LRU_ACTIVE_ANON, //活动匿名页 LRU 链表(swap)
VM_LRU_INACTIVE_FILE, //非活动文件页 LRU 链表(磁盘)
......
......@@ -48,32 +48,32 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
//增加页到页高速缓存
STATIC VOID OsPageCacheAdd(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
LosFilePage *fpage = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {//遍历page_list链表
if (fpage->pgoff > pgoff) {
LOS_ListTailInsert(&fpage->node, &page->node);
LOS_ListTailInsert(&fpage->node, &page->node);//挂到链表上
goto done_add;
}
}
LOS_ListTailInsert(&mapping->page_list, &page->node);
LOS_ListTailInsert(&mapping->page_list, &page->node);//挂到链表上
OsSetPageLRU(page->vmPage); //将页面加入LRU表
OsSetPageLRU(page->vmPage); //给页面贴上LRU标签
done_add:
mapping->nrpages++;
}
//将页面加到活动文件页LRU链表上
VOID OsAddToPageacheLru(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
OsPageCacheAdd(page, mapping, pgoff);
OsLruCacheAdd(page, VM_LRU_ACTIVE_FILE);
}
//从页高速缓存上删除页
VOID OsPageCacheDel(LosFilePage *fpage)
{
/* delete from file cache list */
......@@ -492,7 +492,11 @@ VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
}
//文件缺页时的处理,先读入磁盘数据,再重新读页数据
/**************************************************************************************************
文件缺页时的处理,先读入磁盘数据,再重新读页数据
**************************************************************************************************/
INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
{
INT32 ret;
......@@ -505,7 +509,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {//文件是否映射到了内存
VM_ERR("Input param is NULL");
return LOS_NOK;
}
......@@ -518,7 +522,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
if (fpage != NULL) {
OsPageRefIncLocked(fpage);
} else {
fpage = OsPageCacheAlloc(mapping, vmf->pgoff);//其中分配一个vmpage(物理页框) + fpage
fpage = OsPageCacheAlloc(mapping, vmf->pgoff);//分配一个vmpage(物理页框) + fpage
if (fpage == NULL) {
VM_ERR("Failed to alloc a page frame");
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
......@@ -535,7 +539,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
oldPos = file_seek(file, 0, SEEK_CUR);//相对当前位置偏移,记录偏移后的位置 NUTTX
file_seek(file, fpage->pgoff << PAGE_SHIFT, SEEK_SET);// 相对开始位置偏移
if (file->f_inode && file->f_inode->u.i_mops->readpage) {//见于 NUTTX fat_operations.readpage = NULL
ret = file->f_inode->u.i_mops->readpage(file, (char *)kvaddr, PAGE_SIZE);
ret = file->f_inode->u.i_mops->readpage(file, (char *)kvaddr, PAGE_SIZE);//从文件中读取一页数据到kvaddr
} else {
ret = file_read(file, kvaddr, PAGE_SIZE);//将4K数据读到虚拟地址,磁盘数据进入物理页框 fpage->pgoff << PAGE_SHIFT 处
}
......@@ -630,7 +634,7 @@ VOID OsFileCacheRemove(struct page_mapping *mapping)
LosVmFileOps g_commVmOps = {//
.open = NULL,
.close = NULL,
.fault = OsVmmFileFault, //缺页处理
.fault = OsVmmFileFault, //缺页中断处理
.remove = OsVmmFileRemove,//删除页
};
......@@ -692,8 +696,11 @@ LosFilePage *OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff)
}
/* need mutex & change memory to dma zone. */
//Direct Memory Access(存储器直接访问)指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据。
//整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU只需在数据传输开始和结束时做一点处理(开始和结束时候要做中断处理)
/**************************************************************************************************
以页高速缓存方式分配一个文件页 LosFilePage
Direct Memory Access(存储器直接访问)指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据。
整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU只需在数据传输开始和结束时做一点处理(开始和结束时候要做中断处理)
**************************************************************************************************/
LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
{
VOID *kvaddr = NULL;
......@@ -701,13 +708,13 @@ LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
LosVmPage *vmPage = NULL;
LosFilePage *fpage = NULL;
vmPage = LOS_PhysPageAlloc(); //分配一个物理页
vmPage = LOS_PhysPageAlloc(); //分配一个物理页
if (vmPage == NULL) {
VM_ERR("alloc vm page failed");
return NULL;
}
physSeg = OsVmPhysSegGet(vmPage);//通过页获取所在seg
kvaddr = OsVmPageToVaddr(vmPage);//获取内核空间的虚拟地址,具体点进去看函数说明,这里一定要理解透彻
kvaddr = OsVmPageToVaddr(vmPage);//获取内核空间的虚拟地址,具体点进去看函数说明,这里一定要理解透彻
if ((physSeg == NULL) || (kvaddr == NULL)) {
LOS_PhysPageFree(vmPage); //异常情况要释放vmPage
VM_ERR("alloc vm page failed!");
......@@ -731,9 +738,9 @@ LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
fpage->dirtyEnd = 0; //脏页结束位置
fpage->physSeg = physSeg; //页框所属段.其中包含了 LRU LIST ==
fpage->vmPage = vmPage; //物理页框
fpage->mapping = mapping; //page_mapping 见于 NUTTX
fpage->mapping = mapping; //记录所有文件页映射
fpage->pgoff = pgoff; //偏移
(VOID)memset_s(kvaddr, PAGE_SIZE, 0, PAGE_SIZE);//4K地址清0
(VOID)memset_s(kvaddr, PAGE_SIZE, 0, PAGE_SIZE);//页内数据清0
return fpage;
}
......
......@@ -418,14 +418,14 @@ VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len)
return vaddr;
}
//映射类型为文件的线性区是否有效
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
{
struct file *filep = NULL;
if ((region != NULL) && (LOS_IsRegionTypeFile(region)) &&
(region->unTypeData.rf.file != NULL)) {
(region->unTypeData.rf.file != NULL)) {//满足文件映射的条件
filep = region->unTypeData.rf.file;
if (region->unTypeData.rf.fileMagic == filep->f_magicnum) {
if (region->unTypeData.rf.fileMagic == filep->f_magicnum) {//魔法数字未被改变
return TRUE;
}
}
......
......@@ -261,7 +261,7 @@ VOID *OsVmPageToVaddr(LosVmPage *page)//
VADDR_T vaddr;
vaddr = KERNEL_ASPACE_BASE + page->physAddr - SYS_MEM_BASE;//page->physAddr - SYS_MEM_BASE 得到物理地址上的偏移量
//因在整个虚拟内存中内核空间和用户空间是通过地址隔离的,如此很巧妙的就把该物理页映射到了内核空间
//内核空间的vmPage是不会被置换的,所以是常驻内存,内核空间初始化mmu时就映射好了L1表
//内核空间的vmPage是不会被置换的,因为是常驻内存,内核空间初始化mmu时就映射好了L1表
return (VOID *)(UINTPTR)vaddr;
}
//通过虚拟地址找映射的物理页框
......
......@@ -35,8 +35,8 @@
#include "fs/file.h"
#include "los_vm_filemap.h"
/* unmap a lru page by map record info caller need lru lock *///通过映射记录信息调用者需要lru锁来取消一个映射lru页面
VOID OsUnmapPageLocked(LosFilePage *page, LosMapInfo *info)
/* unmap a lru page by map record info caller need lru lock */
VOID OsUnmapPageLocked(LosFilePage *page, LosMapInfo *info)//通过映射记录信息调用者需要lru锁来取消一个映射lru页面
{
if (page == NULL || info == NULL) {
VM_ERR("UnmapPage error input null!");
......@@ -60,8 +60,8 @@ VOID OsUnmapAllLocked(LosFilePage *page)
}
}
/* add a new lru node to lru list, lruType can be file or anon *///在lru列表中添加一个新的lru节点,lruType可以是文件或匿名
VOID OsLruCacheAdd(LosFilePage *fpage, enum OsLruList lruType)
/* add a new lru node to lru list, lruType can be file or anon */
VOID OsLruCacheAdd(LosFilePage *fpage, enum OsLruList lruType)//在lru列表中添加一个新的lru节点,lruType可以是文件或匿名
{
UINT32 intSave;
LosVmPhysSeg *physSeg = fpage->physSeg; //得到页面对应段
......@@ -76,8 +76,8 @@ VOID OsLruCacheAdd(LosFilePage *fpage, enum OsLruList lruType)
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);//解锁
}
/* dellete a lru node, caller need hold lru_lock *///删除lru节点,调用者需要拿到lru锁
VOID OsLruCacheDel(LosFilePage *fpage)
/* dellete a lru node, caller need hold lru_lock */
VOID OsLruCacheDel(LosFilePage *fpage)//删除lru节点,调用者需要拿到lru锁
{
LosVmPhysSeg *physSeg = fpage->physSeg; //得到页面对应段
int type = OsIsPageActive(fpage->vmPage) ? VM_LRU_ACTIVE_FILE : VM_LRU_INACTIVE_FILE;//得到页面LRU类型
......@@ -92,8 +92,8 @@ BOOL OsInactiveListIsLow(LosVmPhysSeg *physSeg)
physSeg->lruSize[VM_LRU_INACTIVE_FILE]) ? TRUE : FALSE;//直接对比size,效率杠杠的
}
/* move a page from inactive list to active list head *///将页面从非活动列表移动到活动列表
STATIC INLINE VOID OsMoveToActiveList(LosFilePage *fpage)
/* move a page from inactive list to active list head */
STATIC INLINE VOID OsMoveToActiveList(LosFilePage *fpage)//将页面从非活动列表移动到活动列表
{
LosVmPhysSeg *physSeg = fpage->physSeg; //得到页面对应段
......
......@@ -26,8 +26,7 @@
/* */
/**************************************************************************************************
*
*
**************************************************************************************************/
......
git add -A
git commit -m '理解线性区是理解虚拟内存的关键,丰富对线性区的注解
git commit -m '文件是如何映射到内存的?理解页高速缓存(page cache)是关键
搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
搜索 @note_#if0 是由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的。
'
git push origin master
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册