那麽接续昨天的阅读,我们继续看下去~
接下来,有快取的更新介面。一般来说,当 Linux 要将现有的虚拟->实体记忆体转换
改变为新的值时,其顺序将是以下形式之一::
1) flush_cache_mm(mm);
change_all_page_tables_of(mm);
flush_tlb_mm(mm);
2) flush_cache_range(vma, start, end);
change_range_of_page_tables(mm, start, end);
flush_tlb_range(vma, start, end);
3) flush_cache_page(vma, addr, pfn);
set_pte(pte_pointer, new_pte_val);
flush_tlb_page(vma, addr);
快取级别的更新将永远是第一位,因为这让我们能正确处理那些对快取要求严苛,
且当该位址正被从快取中更新时,需要其虚拟->实体转换存在的系统。
HyperSparc cpu 就是一个具有这种属性的 cpu。
下面的快取刷新介面只需要在特定的 cpu 需要的范围内处理快取更新。
大多数情况下,使用虚拟索引快取的 cpu 上,这些介面必须被实作,
当虚拟->实体转换被改变或移除时,这个虚拟索引的快取必须被更新。
因此,例如,IA32 处理器使用物理索引、物理标记的快取就没有必要实做这些介面,
因为这些快取是完全同步的,并且不依赖转换的讯息。
下面逐一列出这些介面:
1) ``void flush_cache_mm(struct mm_struct *mm)``
这个介面将整个使用者定址空间从快取中清除。
也就是说,在执行後,将没有与 ‘mm’ 相关的快取区块。
这个介面被用来处理整个定址空间的分页表操作,
比如在 exit 和 exec 过程中发生的事情。
2) ``void flush_cache_dup_mm(struct mm_struct *mm)``
这个介面将整个使用者定址空间从快取中清除。
也就是说,在执行後,将没有与 ‘mm’ 相关的快取区块。
这个介面被用来处理整个定址空间的分页表操作,
比如在 fork 过程中发生的事情。
这个选项与 flush_cache_mm 分开,以对 VIPT 快取进行优化。
3) ``void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)``
在这里,我们要从快取中更新一个特定范围的(使用者)虚拟位址。
执行後,在 “start” 到 “end-1” 范围内虚拟位址的 “vma->vm_mm”,
快取中将没有其分页表项。
“vma” 是该区域的备份。这个介面主要是用於 munmap() 类型的操作。
提供这个介面是希望能够找到一个有效率方法来从块取中删除多个页面大小的转换,
而不是让核心为每个可能被修改的分页表项使用 flush_cache_page(见下文)。
4) ``void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)``
这一次我们需要从快取中删除一个 PAGE_SIZE 大小的区间。
‘vma’ 是 Linux 用来纪录程序 mmap 区域的资料结构,
定址空间可以通过 vma->vm_mm 获得。另外,
我们可以通过测试(vma->vm_flags & VM_EXEC),
来查看这个区间是否是可执行的
(这块区间在 “Harvard” 类型的快取中可能是在“指令快取”内)。
“pfn” 表示 “addr” 所对应的实体分页页框
(通过PAGE_SHIFT左移这个值来获得实体位址)。
而这个映射应该从快取中被删除。
在执行之後,被转换成 ‘pfn’ 的虚拟位址 ‘addr’
的 ‘vma->vm_mm’,在快取中不会有任何分页表项。
这主要是在错误处理过程中使用。
5) ``void flush_cache_kmaps(void)``
只有在平台使用 highmem 的情况下才需要实做这个介面。
它将在所有的 kmaps 失效之前被呼叫到。
执行後,核心虚拟位址范围 PKMAP_ADDR(0) 到 PKMAP_ADDR(LAST_PKMAP)
的快取中将没有分页表项。
这个介面应该在 asm/highmem.h 中实做。
6) ``void flush_cache_vmap(unsigned long start, unsigned long end)``
``void flush_cache_vunmap(unsigned long start, unsigned long end)``
在这两个介面中,我们从快取中更新一个特定范围的(核心)虚拟位址。
执行後,核心定址空间的快取中不会有,在 “start” 到 “end-1” 范围内虚拟位址的分页表项。
这两个介面中的前者是在 vmap_range() 装载了分页表项之後呼叫的。
第二个则是在 vunmap_range() 删除分页表项之前呼叫的。
读完这个部分,大致上和昨天读到的内容有些相似,换成了 cache 版本,但有些相关的名词是不太熟悉的,先简单的做个整理:
这部分的文件没有解答昨天有的疑问,反而让我有更多不了解的部分XDDD
然後也延伸出了很多值得做实验观察的部分:
kernel 的记忆体管理子系统真的是很复杂呢!有好多东西可以研究!
那麽今天就先到这,整份文件分为四个部分
<<: Day 4 Ruby 变数与资料型别 Variable and Data Type
>>: Day 19 - Unreal Webcam Fun [更新]
event 查目前网页的 event,开启 Chrome 的开发者工具,点选 Elements,之後...
今年的疫情蛮严重的,希望大家都过得安好,希望疫情快点过去,能回到一些线下技术聚会的时光~ 今天目标:...
重复影像 background-repeat 这个属性可以重复图像在背景 如果是使用小图做素材 可以...
首先来个永丰官方的文件图片作开场吧! (图一:由商户->永丰正向发动的所需参数) 而我们今天要...
第一天,想笔记下我对资讯安全的理解。 资讯安全怎麽来的? 我印象里的历史战争剧中,国家或两个阵营打仗...