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

注解写时复制(Copy On Write)技术在鸿蒙内核的实现

搜索 @note_pic 方便理解画的字符图
搜索 @note_why 尚未看明白的地方,如果您看明白了,请告知完善
搜索 @note_thinking 一点思考和吐槽的地方
搜索 @note_#if0 由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的
搜索 @note_good 给源码点赞
上级 48a7a977
......@@ -41,44 +41,47 @@
#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 */
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 */
//page_mapping描述的是一个文件在内存中被映射了多少页,<文件,文件页的关系>
/* file mapped in VMM pages */
struct page_mapping {//记录文件页和文件关系的结构体,叫文件页映射
LOS_DL_LIST page_list; /* all pages */ //链表上挂的是属于该文件的所有FilePage,这些页的内容都来源同一个文件
SPIN_LOCK_S list_lock; /* lock protecting it */ //操作page_list的自旋锁
LosMux mux_lock; /* mutex lock */ // //操作page_mapping的互斥量
unsigned long nrpages; /* number of total pages */ //page_list的节点数量
unsigned long flags; //@note_why 全量代码中也没查到源码中对其操作
Atomic ref; /* reference counting */ //引用次数(自增/自减),对应add_mapping/dec_mapping
struct file *host; /* owner of this mapping *///属于哪个文件的映射
};
/* map: full_path(owner) <-> mapping */ //叫文件映射
struct file_map { //为在内核层面文件在内存的身份证,每个需映射到内存的文件必须创建一个file_map,都挂到全局g_file_mapping链表上
LOS_DL_LIST head; //链表节点,用于挂到g_file_mapping上
LosMux lock; /* lock to protect this mapping */
struct page_mapping mapping; //每个文件都有唯一的page_mapping标识其在内存的身份
char *owner; /* owner: full path of file *///文件全路径来标识唯一性
};
/* 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 * /
};
struct file
struct file //文件系统最重要的两个结构体之一,另一个是inode
{
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 */ //与内存的映射 page-cache
void *f_dir; /* DIR struct for iterate the directory if open a directory */ //所在目录
};
#endif
static struct file_map g_file_mapping = {0};
static struct file_map g_file_mapping = {0};//用于挂载所有文件的file_map
/**************************************************************************************************
初始化文件映射模块,
file_map: 每个需映射到内存的文件必须创建一个 file_map,都挂到全g_file_mapping链表上
file_map: 每个需映射到内存的文件必须创建一个 file_map,都挂到全g_file_mapping链表上
page_mapping: 记录的是<文件,文件页>的关系,一个文件在操作过程中被映射成了多少个页,
file:是文件系统管理层面的概念
**************************************************************************************************/
......@@ -132,8 +135,8 @@ void add_mapping(struct file *filep, const char *fullpath)
mapping = find_mapping_nolock(fullpath);//是否已有文件映射
if (mapping) {//有映射过的情况
LOS_AtomicInc(&mapping->ref);//引用自增
filep->f_mapping = mapping;//赋值
mapping->host = filep;
filep->f_mapping = mapping;//记录文件自己在内存的身份
mapping->host = filep; //记录page_mapping的老板
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);//释放锁
return;//收工
}
......@@ -227,7 +230,12 @@ void clear_file_mapping_nolock(const struct page_mapping *mapping)
i++;
}
}
//删除一个映射
/******************************************************************************
删除一个文件映射,需要有个三个地方删除才算断开了文件和内存的联系.
1. 进程文件
******************************************************************************/
int remove_mapping_nolock(const char *fullpath, const struct file *ex_filp)
{
int fd;
......@@ -276,11 +284,11 @@ int remove_mapping_nolock(const char *fullpath, const struct file *ex_filp)
}
(VOID)LOS_MuxDestroy(&mapping->mux_lock);
clear_file_mapping_nolock(mapping);//清除自己
OsFileCacheRemove(mapping);//从缓存中删除自己
clear_file_mapping_nolock(mapping);//清除进程对page_mapping的映射
OsFileCacheRemove(mapping);//从页高速缓存中删除文件页
fmap = LOS_DL_LIST_ENTRY(mapping,
struct file_map, mapping);//找到自己的inode
LOS_ListDelete(&fmap->head);//从链表中摘除自己
struct file_map, mapping);//通过page_mapping找到fmap
LOS_ListDelete(&fmap->head);//从g_file_mapping链表上摘掉自己
LOS_MemFree(m_aucSysMem0, fmap);
out:
......
......@@ -64,23 +64,24 @@ extern "C" {
#if 0 //@note_#if0
//page_mapping描述的是一个文件在内存中被映射了多少页,<文件,文件页的关系>
/* file mapped in VMM pages */
struct page_mapping {
struct page_mapping {//记录文件页和文件关系的结构体,叫文件页映射
LOS_DL_LIST page_list; /* all pages */ //链表上挂的是属于该文件的所有FilePage,这些页的内容都来源同一个文件
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 */
SPIN_LOCK_S list_lock; /* lock protecting it */ //操作page_list的自旋锁
LosMux mux_lock; /* mutex lock */ // //操作page_mapping的互斥量
unsigned long nrpages; /* number of total pages */ //page_list的节点数量
unsigned long flags; //@note_why 全量代码中也没查到源码中对其操作
Atomic ref; /* reference counting */ //引用次数(自增/自减),对应add_mapping/dec_mapping
struct file *host; /* owner of this mapping *///属于哪个文件的映射
};
/* map: full_path(owner) <-> mapping */
struct file_map {
LOS_DL_LIST head;
/* map: full_path(owner) <-> mapping */ //叫文件映射
struct file_map { //为在内核层面文件在内存的身份证,每个需映射到内存的文件必须创建一个file_map,都挂到全局g_file_mapping链表上
LOS_DL_LIST head; //链表节点,用于挂到g_file_mapping上
LosMux lock; /* lock to protect this mapping */
struct page_mapping mapping;
char *owner; /* owner: full path of file */
struct page_mapping mapping; //每个文件都有唯一的page_mapping标识其在内存的身份
char *owner; /* owner: full path of file *///文件全路径来标识唯一性
};
#endif
//文件页结构体
......@@ -89,7 +90,7 @@ typedef struct FilePage {
LOS_DL_LIST lru; //lru节点, 结合 LosVmPhysSeg: LOS_DL_LIST lruList[VM_NR_LRU_LISTS] 理解
LOS_DL_LIST i_mmap; /* list of mappings */ //链表记录文件页被哪些进程映射 MapInfo.node挂上来
UINT32 n_maps; /* num of mapping */ //记录被进程映射的次数
struct VmPhysSeg *physSeg; /* physical memory that file page belongs to */ //物理内存是唯一的
struct VmPhysSeg *physSeg; /* physical memory that file page belongs to */ //物理段:物理页框 = 1:N
struct VmPage *vmPage; //物理页框
struct page_mapping *mapping; //此结构由文件系统提供,用于描述装入点 见于 ..\third_party\NuttX\include\nuttx\fs\fs.h
VM_OFFSET_T pgoff; //页标,文件被切成一页一页读到内存
......
......@@ -95,11 +95,11 @@ typedef struct VmFault {
VADDR_T *pageKVaddr; /* KVaddr of pagefault's vm page's paddr */ //page cache中的虚拟地址
} LosVmPgFault;
//虚拟内存文件操作函数指针,上层开发可理解为 class 里的方法,注意是对线性区的操作
struct VmFileOps {// 文件操作
struct VmFileOps {// 文件操作 见于g_commVmOps
void (*open)(struct VmMapRegion *region); //打开
void (*close)(struct VmMapRegion *region);//关闭
int (*fault)(struct VmMapRegion *region, LosVmPgFault *pageFault);//缺页
void (*remove)(struct VmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T offset);//删除
int (*fault)(struct VmMapRegion *region, LosVmPgFault *pageFault);//缺页,OsVmmFileFault
void (*remove)(struct VmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T offset);//删除 OsVmmFileRemove
};
struct VmMapRegion {//线性区描述符,内核通过线性区管理虚拟地址,而线性地址就是虚拟地址
......
......@@ -147,7 +147,7 @@ STATIC STATUS_T OsDoReadFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)//
return LOS_ERRNO_VM_NO_MEMORY;
}
/* numap a page when cow happend only */
/* numap a page when cow happend only *///仅当写时拷贝发生时取消页面映射
STATIC LosVmPage *OsCowUnmapOrg(LosArchMmu *archMmu, LosVmMapRegion *region, LosVmPgFault *vmf)
{
UINT32 intSave;
......@@ -404,7 +404,7 @@ STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
vmPgFault.vaddr = vaddr;//虚拟地址
vmPgFault.pgoff = ((vaddr - region->range.base) >> PAGE_SHIFT) + region->pgOff;//计算出文件读取位置
vmPgFault.flags = flags;
vmPgFault.pageKVaddr = NULL;//没有物理地址
vmPgFault.pageKVaddr = NULL;//缺失页初始化没有物理地址
status = OsDoFileFault(region, &vmPgFault, flags);//缺页处理
if (status) {
......
......@@ -171,7 +171,9 @@ STATIC LosFilePage *OsPagecacheGetPageAndFill(struct file *filp, VM_OFFSET_T pgO
return page;
}
//从文件filp中读 size 数据到buf中
/******************************************************************************
从文件filp中读 size 数据到buf中
******************************************************************************/
ssize_t OsMappingRead(struct file *filp, char *buf, size_t size)
{
INT32 ret;
......@@ -212,7 +214,7 @@ ssize_t OsMappingRead(struct file *filp, char *buf, size_t size)
readSize = MIN2((PAGE_SIZE - offInPage), readLeft);
(VOID)memcpy_s((VOID *)buf, readLeft, (char *)kvaddr + offInPage, readSize);
(VOID)memcpy_s((VOID *)buf, readLeft, (char *)kvaddr + offInPage, readSize);//将文件页的数据拷贝到buf
buf += readSize;
readLeft -= readSize;
readTotal += readSize;
......@@ -227,69 +229,71 @@ ssize_t OsMappingRead(struct file *filp, char *buf, size_t size)
return readTotal;
}
/******************************************************************************
向页高速缓存中写入数据
******************************************************************************/
ssize_t OsMappingWrite(struct file *filp, const char *buf, size_t size)
{
VADDR_T kvaddr;
UINT32 intSave;
INT32 writeSize = 0;
size_t writeLeft = size;
VM_OFFSET_T pos = file_seek(filp, 0, SEEK_CUR);
VM_OFFSET_T pgOff = pos >> PAGE_SHIFT;
INT32 offInPage = pos % PAGE_SIZE;
VM_OFFSET_T pos = file_seek(filp, 0, SEEK_CUR);//获得要从文件那个位置写入
VM_OFFSET_T pgOff = pos >> PAGE_SHIFT; //计算出文件页的序号
INT32 offInPage = pos % PAGE_SIZE; //计算出文件页内偏移量
LosFilePage *page = NULL;
struct page_mapping *mapping = filp->f_mapping;
struct page_mapping *mapping = filp->f_mapping;//得到文件页映射
INT32 nPages = (ROUNDUP(pos + size, PAGE_SIZE) - ROUNDDOWN(pos, PAGE_SIZE)) >> PAGE_SHIFT;
LOS_SpinLockSave(&mapping->list_lock, &intSave);
for (INT32 i = 0; i < nPages; i++, pgOff++) {
page = OsFindGetEntry(mapping, pgOff);
if (page) {
kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);
OsSetPageLocked(page->vmPage);
OsPageRefIncLocked(page);
} else {
page = OsPageCacheAlloc(mapping, pgOff);
for (INT32 i = 0; i < nPages; i++, pgOff++) {//遍历pgOff,pgOff表示页序号
page = OsFindGetEntry(mapping, pgOff);//通过页序号拿到页高速缓存中的文件页
if (page) {//页高速缓存中有该页
kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);//通过文件页获得虚拟地址(即数据写入地址)
OsSetPageLocked(page->vmPage);//写操作要上锁
OsPageRefIncLocked(page);//因为页可能被其他进程所引用,所以也要上锁
} else {//页高速缓存中没有该页
page = OsPageCacheAlloc(mapping, pgOff);//分配一个文件页
if (page == NULL) {
VM_ERR("Failed to alloc a page frame");
break;
}
kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);
OsAddToPageacheLru(page, mapping, pgOff);
OsSetPageLocked(page->vmPage);
kvaddr = (VADDR_T)(UINTPTR)OsVmPageToVaddr(page->vmPage);//通过文件页获得虚拟地址(即数据写入地址)
OsAddToPageacheLru(page, mapping, pgOff);//将页加入页高速缓存中
OsSetPageLocked(page->vmPage);//写操作要上锁,因为是新页,所以不要 OsPageRefIncLocked
}
//准备工作做好了,才是写入页高速缓存,注意这里只是写缓存,而不是写最终的文件
writeSize = MIN2((PAGE_SIZE - offInPage), writeLeft);//计算出要写入的大小
writeSize = MIN2((PAGE_SIZE - offInPage), writeLeft);
(VOID)memcpy_s((char *)(UINTPTR)kvaddr + offInPage, writeLeft, buf, writeSize);//将内容拷贝到页高速缓存
buf += writeSize; //计算出剩余未写完buf位置
writeLeft -= writeSize; //计算出剩余大小
(VOID)memcpy_s((char *)(UINTPTR)kvaddr + offInPage, writeLeft, buf, writeSize);
buf += writeSize;
writeLeft -= writeSize;
OsMarkPageDirty(page, NULL, offInPage, writeSize);//标记文件页为脏页,从offInPage位置开始脏的.
//注意这里只是做标记,内核并不会马上将数据写入磁盘文件,而是在缺页时写入磁盘,就是著名的 写时拷贝技术.
offInPage = 0;//脏位置复位
OsMarkPageDirty(page, NULL, offInPage, writeSize);
offInPage = 0;
OsCleanPageLocked(page->vmPage);
OsCleanPageLocked(page->vmPage);//释放文件页锁
}
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
file_seek(filp, pos + size - writeLeft, SEEK_SET);
file_seek(filp, pos + size - writeLeft, SEEK_SET);//最后文件要seek到指定的位置
return (size - writeLeft);
}
//解除文件页和进程的映射关系
STATIC VOID OsPageCacheUnmap(LosFilePage *fpage, LosArchMmu *archMmu, VADDR_T vaddr)
{
UINT32 intSave;
LosMapInfo *info = NULL;
LOS_SpinLockSave(&fpage->physSeg->lruLock, &intSave);
info = OsGetMapInfo(fpage, archMmu, vaddr);
info = OsGetMapInfo(fpage, archMmu, vaddr);//获取文件页在进程的映射信息
if (info == NULL) {
VM_ERR("OsPageCacheUnmap get map info fail!");
} else {
OsUnmapPageLocked(fpage, info);
OsUnmapPageLocked(fpage, info);//解除进程和文件页映射关系
}
if (!(OsIsPageMapped(fpage) && ((fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE) ||
OsIsPageDirty(fpage->vmPage)))) {
......@@ -397,13 +401,13 @@ STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
size_t len;
char *buff = NULL;
VM_OFFSET_T oldPos;
struct file *file = fpage->mapping->host;//struct file *host; /* owner of this mapping */ 此映射的所有者
struct file *file = fpage->mapping->host;/* owner of this mapping */ //此映射属于哪个文件,注意<file,page_mapping>是1:1的关系.
if ((file == NULL) || (file->f_inode == NULL)) {//nuttx file 文件描述符
VM_ERR("page cache file error");
return LOS_NOK;
}
oldPos = file_seek(file, 0, SEEK_CUR);//定位到当前位置
oldPos = file_seek(file, 0, SEEK_CUR);////先记录老位置,因为写完页数据后要seek回老位置
buff = (char *)OsVmPageToVaddr(fpage->vmPage);//获取页面的虚拟地址
file_seek(file, (((UINT32)fpage->pgoff << PAGE_SHIFT) + fpage->dirtyOff), SEEK_SET);//移到页面脏数据位置,注意不是整个页面都脏了,可能只脏了一部分
len = fpage->dirtyEnd - fpage->dirtyOff;//计算出脏数据长度
......@@ -413,7 +417,7 @@ STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
(VOID)file_seek(file, oldPos, SEEK_SET);//移回老位置
return LOS_OK;
}
//i_mops: Operations on a mountpoint 可前往 nuttx 查看 fat_operations.writepage为null
//
if (file->f_inode && file->f_inode->u.i_mops->writepage) {//如果mount驱动程序提供了写页的实现
ret = file->f_inode->u.i_mops->writepage(file, (buff + fpage->dirtyOff), len);//使用mount接口回写数据
} else {
......@@ -424,7 +428,7 @@ STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
}
ret = (ret <= 0) ? LOS_NOK : LOS_OK;
OsCleanPageDirty(fpage->vmPage);//撕掉脏页标签,还清白之身,哈哈,臣妾又干净了.
(VOID)file_seek(file, oldPos, SEEK_SET);//写完了脏数据,切回到老位置,一定要回到老位置,因为回写脏数据是内核的行为,而不是用户的行为
(VOID)file_seek(file, oldPos, SEEK_SET);//不管是否写正常,一定要切回到原来位置,很重要!!! 写页是内核的操作,不是用户的操作行为
return ret;
}
......@@ -528,7 +532,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
/* get or create a new cache node */
LOS_SpinLockSave(&mapping->list_lock, &intSave);
fpage = OsFindGetEntry(mapping, vmf->pgoff);//获取文件页
if (fpage != NULL) {//找到了,该页已经在页高速缓存中
if (fpage != NULL) {//找到了,说明该页已经在页高速缓存中
OsPageRefIncLocked(fpage);
} else {//真的缺页了,页高速缓存中没找到
fpage = OsPageCacheAlloc(mapping, vmf->pgoff);//分配一个文件页,将数据初始化好,包括vmpage(物理页框)
......@@ -537,36 +541,36 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
return LOS_NOK;
}
newCache = true;
newCache = true;//分配了新文件页
}
OsSetPageLocked(fpage->vmPage);//对vmpage上锁
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
kvaddr = OsVmPageToVaddr(fpage->vmPage);//获取该页框在内核空间的虚拟地址
kvaddr = OsVmPageToVaddr(fpage->vmPage);//获取该页框在内核空间的虚拟地址,因为 page cache本身就是在内核空间,
/* read file to new page cache */
if (newCache) {//新cache
oldPos = file_seek(file, 0, SEEK_CUR);//相对当前位置偏移,记录偏移后的位置 NUTTX
file_seek(file, fpage->pgoff << PAGE_SHIFT, SEEK_SET);// 相对开始位置偏移
oldPos = file_seek(file, 0, SEEK_CUR);//先记录老位置,因为读完页数据后要seek回老位置
file_seek(file, fpage->pgoff << PAGE_SHIFT, SEEK_SET);//定位到要开始读的位置,从fpage->pgoff << PAGE_SHIFT 文件位置开始读.
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);//从文件中读取一页数据到kvaddr
} else {
ret = file_read(file, kvaddr, PAGE_SIZE);//将4K数据读到虚拟地址,磁盘数据进入物理页框 fpage->pgoff << PAGE_SHIFT 处
ret = file_read(file, kvaddr, PAGE_SIZE);//将磁盘4K数据读到物理页框的kvaddr地址中,真正写到了fpage->vmPage->physAddr中.
}
file_seek(file, oldPos, SEEK_SET);//再切回原来位置,一定要切回,很重要!!! 因为缺页是内核的操作,不是用户逻辑行为
file_seek(file, oldPos, SEEK_SET);//不管是否读写正常,一定要切回到原来位置,很重要!!! 因为缺页->读页是内核的操作,不是用户的操作行为
if (ret == 0) {
VM_ERR("Failed to read from file!");
OsReleaseFpage(mapping, fpage);
return LOS_NOK;
}
LOS_SpinLockSave(&mapping->list_lock, &intSave);
OsAddToPageacheLru(fpage, mapping, vmf->pgoff);//将fpage加入 pageCache 和 LruCache
OsAddToPageacheLru(fpage, mapping, vmf->pgoff);//将fpage挂入pageCache 和 LruCache
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
}
LOS_SpinLockSave(&mapping->list_lock, &intSave);
/* cow fault case no need to save mapinfo */
if (!((vmf->flags & VM_MAP_PF_FLAG_WRITE) && !(region->regionFlags & VM_MAP_REGION_FLAG_SHARED))) {
OsAddMapInfo(fpage, &region->space->archMmu, (vaddr_t)vmf->vaddr);//既不共享,也不可写 就不用回写磁盘啦
OsAddMapInfo(fpage, &region->space->archMmu, (vaddr_t)vmf->vaddr);//添加<虚拟地址,文件页>的映射关系,如此进程以后就能通过虚拟地址操作文件页了.
fpage->flags = region->regionFlags;
}
......@@ -575,7 +579,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
OsMarkPageDirty(fpage, region, 0, 0);//标记为脏页,要回写磁盘,内核会在适当的时候回写磁盘
}
vmf->pageKVaddr = kvaddr;//将文件页的虚拟地址带给缺陷页
vmf->pageKVaddr = kvaddr;//缺陷页记录文件页的虚拟地址
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
return LOS_OK;
}
......
......@@ -197,7 +197,7 @@ VOID OsPageRefDecNoLock(LosFilePage *fpage)
page = fpage->vmPage;
isOrgActive = OsIsPageActive(page);
if (!OsIsPageReferenced(page) && OsIsPageActive(page)) {
if (!OsIsPageReferenced(page) && OsIsPageActive(page)) {//[ref:0,act:1]的情况
OsCleanPageActive(page);
OsSetPageReferenced(page);
} else if (OsIsPageReferenced(page)) {
......@@ -208,7 +208,7 @@ VOID OsPageRefDecNoLock(LosFilePage *fpage)
OsMoveToInactiveList(fpage);
}
}
//缩小活动页链表
//缩小活动页链表
VOID OsShrinkActiveList(LosVmPhysSeg *physSeg, int nScan)
{
LosFilePage *fpage = NULL;
......
#ifndef _NOTE_FS_H
#define _NOTE_FS_H
#if 0
共享内存写保持同步
文件页下标不变,写的内容大于4k时,产生缺页继续写page cache ,
脏页,凭文件页下标+脏页偏移量写回磁盘
#endif
#endif
#ifndef _NOTE_IPC_H
#define _NOTE_IPC_H
/****************************************************************
#if 0
信号量是为了解决task的资源同步问题,有多少资源就设多大的资源最大值
信号量机制:
以一个停车场的运作为例。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,
......@@ -20,11 +17,8 @@
当前资源计数器决定不会大于最大资源计数
最大资源计数,表示可以控件的最大资源数量
当前资源计数,表示当前可用资源的数量
#endif
****************************************************************/
/* */
/******************************************************************************
******************************************************************************/
......
git add -A
git commit -m '注解1.对缺页中断的处理 2.物理地址的管理
搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
搜索 @note_#if0 是由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的。
搜索 @note_good 是注者给源码点赞的地方
git commit -m '注解写时复制(Copy On Write)技术在鸿蒙内核的实现
搜索 @note_pic 方便理解画的字符图
搜索 @note_why 尚未看明白的地方,如果您看明白了,请告知完善
搜索 @note_thinking 一点思考和吐槽的地方
搜索 @note_#if0 由第三方项目提供不由内核源码中定义的极为重要的结构体,为方便理解而添加的
搜索 @note_good 给源码点赞
'
git push origin master
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册