NetBSD 内存管理系统 UVM 浅析
2006-08-09 22:57:02 来源:WEB开发网首先一大堆代码已确定 pre-fault 的范围, 如果是 wired 的地方, 我们不应该做 pre-fault (narrow == TRUE). 从 788 行开始的代码, 开始了真正的 pre-fault 操作. 其主要方法就是将可以 active 的页面 active 掉, 并填充 pages 数组. 注意 821 行, 如果一个中心页面 (真正 fault 的地方) 能够来到这里, 说明在 amap 中有其相应的表项, 那它肯定是因为基于 amap 的 COW 而 fault 掉的, 因此 shadow = TRUE, fault 在上层 (amap 层).
接着, 根据 fault 的层次, 有 Case1 和 Case 2 两分支. 我们先来看 Case 1 分支, 其代码真正开始在 1028 行.
B: line 1076, handling loan
XXX
C: line 1163, handling COW (case 1B)
如果是 COW 且 anon 的引用数大于 1, 我们就需要创建一个新 anon 以及页面, 复制数据 (uvm_pagecopy()), 把新结点替换进 amap (amap_add). 否则, 我们只需将 fault 位复原而继续使用. XXX. why?
D: line 901
这是属于 Case B 的代码. 我们来到这里, 说明其 obj 的 pager 中没有 pgo_fault 函数自主处理 fault 情况, 我们要使用它的 pgo_get 函数来处理 fault 情况.
我们首先调用 obj 的 pgo_get 函数读取所需的页面数据 (不要忘了我们有做 pre-fault, 所以要取出的不是仅一个页面的数据), pgo_get 会填充 pages 里需要处理 (== NULL) 且能够处理的表项, 激活有效的项 (否则又被换出了), 我们在这里还得到 uobjpage, 即真正 fault 的地方的 page. 注意 uobjpage 不在这里进行写入 pmap 等的处理, 因为在后面, 我们还要再去处理这个页面, 可能还要将它倒回 anon (Case 2B).
底层页面分配
vm_page 是 UVM 硬件无关部分所管理的最小单位和最底层对象. 其声明在 vm_page.h, 除了一些链接属性外 (前面的注释有解释). 还有指向所属的 anon 或 object 的反向指针, 显然, 它们之中只能有一个非 NULL, 还有其对应的物理地址, 以及机器相关的部分.
更多精彩
赞助商链接