put_page(page); return handle_userfault(vmf, VM_UFFD_MISSING); } inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES); // 建立物理页到虚拟页的反向映射 page_add_new_anon_rmap(page, vma, vmf->address, false); mem_cgroup_commit_charge(page, memcg, false, false); // 把物理页添加到活动L...
put_page(page); gotounlock; oom_free_page: put_page(page); oom: returnVM_FAULT_OOM; } 如果是共享则意味着之前以及通过mmap方式在其他进程申请过物理内存,vma应该存在对应物理内存映射,不应该再发生page fault 调用pte_alloc函数来为页面表表项(PTE)分配内存,并传递vma->vm_mm和vmf->pmd作为参数 如果页...
写时复制一般发生在父子进程之间,fork时copy_mm时会将父进程和子进程的页表项都设置为只读,无论是父进程或子进程执行写入都会触发page fault,通过此函数执行写时复制,分配新的page,拷贝旧page到新page, 并修改相应的页表项为读写。参数vmf->vma保存了线性区原有的读写权限 现在先看看a.(1) do_anonymous_page ...
后面的put_page()函数即用于把指定页面映射//到某个进程地址空间中。当然对于内核使用本函数并不需要再使用put_page()进行映射,//因为内核代码和数据空间(16MB)已经对等地映射到物理地址空间。unsignedlongget_free_page(void) { register unsignedlong__res asm("ax"); __asm__("std ; repne ; scasb\n\t...
通过page[0]~page[n-1]中flags、compound_head、compound_dtor成员的特殊串联关系,把这N个page结构体联系在了一起。这产生了一个混乱,很多时候,我们真正想操作的,其实只是compound page的整体,比如get_page、put_page、lock_page、unlock_page等。于是这样的API里面,广泛地存在这样的compound_head操作: ...
通过page[0]~page[n-1]中flags、compound_head、compound_dtor成员的特殊串联关系,把这N个page结构体联系在了一起。这产生了一个混乱,很多时候,我们真正想操作的,其实只是compound page的整体,比如get_page()、put_page()、lock_page()、unlock_page()等。于是这样的API里面,广泛地存在这样的compound_head()...
中断描述符表内可以存放256个描述符,分别对应256个中断 --- 处理中断page fault page_falut中断程序执行肯定要进入内核,首先就是把用户栈相关寄存器状态压栈,也被称为保护现场 //在linux...若共享操作不成功,那么只能从相应文件中读入所缺的数据页面到指定线性地址处
Linux的内存管理是以页展开的,struct page非常重要,同时其维护成本也非常高。 这里主要介绍struct page中_count/_mapcount和flags参数。 flags是页面标志位集合,是内存管理非常重要的部分。 _count表示内核中引用该页面的次数;_mapcount表示页面被进程映射的个数,对反向映射非常重要。
put_page(vmf->page); return0; } put_page(vmf->page); } //单身匿名页面的处理 if(reuse_swap_page(vmf->page, &total_map_swapcount)) { if(total_map_swapcount ==1) { /* * The page is all ours. Move it to * our anon_vma so the rmap code will ...
这里提一嘴,mmap进行映射时,只是在匿名映射与文件映射区划分了一块vma,但这时并没有分配物理内存,即对应的pte为空;在实际访问时,会触发page fault,在缺页处理过程中会为其分配物理页面并更新pte。 缺页异常处理大致流程 大致处理流程如下: //__do_page_fault()// __handle_mm_fault()// handle_pte_fault...