06.02.2015 Views

JOS 实验二实验记录作者:卓达城指导老师:邵志远单位:华中科技大学 ...

JOS 实验二实验记录作者:卓达城指导老师:邵志远单位:华中科技大学 ...

JOS 实验二实验记录作者:卓达城指导老师:邵志远单位:华中科技大学 ...

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>JOS</strong> 实 验 二 实 验 记 录<br />

作 者 : 卓 达 城<br />

指 导 老 师 : 邵 志 远<br />

单 位 : 华 中 科 技 大 学 集 群 网 络 与 服 务 计 算 实 验 室<br />

第 一 步 : 理 解 下 面 这 个 函 数<br />

stab_binsearch(stabs,& region_left,& region_right, type, addr) 函 数<br />

This function is a bi*ch!!!<br />

背 景 :<br />

<strong>JOS</strong> 的 作 者 通 过 kerne.ld 把 调 试 信 息 和 内 核 一 起 加 载 到 内 存 中 去 。 并 提 供 了 四 个 相 应 的 宏 以<br />

记 录 相 关 信 息 。<br />

下 图 是 kernel.ld 中 的 代 码 片 段 :<br />

当 我 们 运 行 完 虚 拟 机 之 后 , 调 试 信 息 和 内 核 一 起 加 载 到 0xf0000000(virtual address) 中<br />

从 以 下 代 码 片 段 中 , 我 们 可 以 找 到 , 调 试 信 息 是 如 何 被 赋 值 到 stab 的 :<br />

调 试 信 息 的 结 构 是 怎 么 样 的 呢 <br />

我 们 可 以 轻 松 地 在 代 码 中 发 现 下 面 的 结 构 :<br />

但 是 它 到 底 放 的 是 什 么 , 这 令 人 满 头 雾 水 。


我 们 可 以 从 init.s 中 找 到 我 们 想 要 的 答 案 。init.s 通 过 命 令 :<br />

gcc -pipe -nostdinc -O2 -fno-builtin -I. -MD -Wall -Wno-format -<br />

D<strong>JOS</strong>_KERNEL -gstabs -c -S kern/init.c<br />

生 成 。<br />

观 察 以 上 代 码 片 段 :<br />

我 们 把 它 放 入 stab 结 构 中 , 我 们 可 以 知 道 :<br />

n_strx 是 函 数 名 ,n_type 是 36 ,n_other 是 0,n_desc 也 是 0,n_value 是 函 数 的 段 偏 移<br />

(eip)<br />

观 察 以 上 代 码 片 段 :<br />

我 们 可 以 猜 测 :<br />

n_str 为 空 , n_type 为 68, n_other 为 0, n_desc 为 行 号 ( 对 一 下 源 代 码 就 知 道 了 ),<br />

n_value 为 函 数 内 偏 移 量 。(I just want to say f*ck!Waste my time for 3 hours!!!)<br />

这 就 是 type 的 类 型 ,0x24 是 36, 跟 上 面 的 代 码 片 段 对 应 。<br />

有 了 以 上 背 景 知 识 , 我 们 开 始 研 究 stab_binsearch 函 数<br />

先 说 说 这 个 函 数 的 返 回 值 和 参 数 :<br />

返 回 值 :<br />

函 数 成 功 找 到 代 码 区 域 就 返 回 0 否 则 返 回 -1<br />

region_left 和 region_right: 根 据 type 返 回 代 码 区 域 的 起 始 地 址 。 如 果 是 函 数 , 返 回 函 数 的 起<br />

始 地 址 和 终 点 地 址 , 如 果 是 代 码 , 返 回 代 码 的 起 始 地 址 的 终 点 地 址 ( 翻 译 成 汇 编 之 后 )。 如<br />

果 是 文 件 或 者 其 它 类 型 , 同 上 。<br />

参 数 :<br />

stabs 调 试 信 息 的 起 始 地 址<br />

region_left: 要 搜 索 的 区 域 的 起 始 地 址<br />

region_right: 要 搜 索 的 区 域 的 终 点<br />

type: 要 搜 索 的 代 码 类 型<br />

addr :eip<br />

这 个 函 数 用 了 二 分 搜 索 法 进 行 搜 索 , 具 体 实 现 请 看 代 码 , 比 较 难 讲 清 楚 , 我 看 也 看 了 很 久<br />

才 明 白 其 中 奥 妙 。 但 是 如 果 了 解 了 上 面 的 背 景 再 看 , 就 会 事 半 功 倍 。 这 里 的 所 有 的 stab 已<br />

经 跟 我 们 的 代 码 运 行 顺 序 是 一 致 的 。<br />

看 完 代 码 之 后 我 们 就 开 始 实 现 我 们 的 Exercise 1, 完 成 debuginfo_eip 函 数<br />

首 先 :<br />

在 debuginfo_eip 函 数 中 , 我 看 到 这 句 代 码


这 句 代 码 是 判 断 函 数 名 字 有 没 有 超 界 的 。 如 果 没 有 , 就 赋 值 。<br />

这 两 句 代 码 求 出 我 们 所 要 找 的 代 码 在 具 体 函 数 中 的 偏 移 量 。 记 着 , 我 们 前 面 说 过 , 当 type<br />

是 代 码 的 时 候 ,n_value 表 示 的 是 偏 移 量 。 第 一 行 代 码 中 的 n_value 表 示 addr 所 在 的 函 数 的<br />

代 码 区 域 的 首 地 址 , addr - info->eip_fn_addr 就 可 以 求 出 偏 移 量 , 下 面 就 可 以 用<br />

stab_binsearch 函 数 找 到 具 体 的 行 号 。<br />

以 下 是 我 们 要 添 加 的 代 码 :<br />

按 照 要 求 , 我 们 还 要 找 出 函 数 的 参 数 个 数 :<br />

所 再 添 加 如 下 代 码 , 我 们 已 经 知 道 了 stab 的 结 构 方 式 (stab 的 顺 序 和 我 们 的 代 码 顺 序 一<br />

样 ), 所 以 以 下 代 码 及 可 以 找 出 参 数 的 个 数 。<br />

然 后 , 在 monitor.c 中 加 入 如 下 代 码 就 完 成 了 第 一 个 Exercise


^^^^^^^^^^^^^^^^^^^^^^zhuodc@qq.com^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br />

写 到 这 里 , 我 确 实 不 想 再 写 了 , 但 是 作 为 一 个 软 件 工 程 的 学 生 , 我 深 深 体 会 到 文 档 的<br />

重 要 性 , 所 以 再 写 。<br />

在 开 始 做 下 面 的 实 验 之 前 , 我 们 想 要 了 解 一 下 <strong>JOS</strong> 的 内 存 结 构 。<br />

先 从 最 基 本 的 boot.S 开 始<br />

在 boot.S 中 ,gdt 如 下<br />

NULL<br />

0x00000000<br />

0x00000000<br />

0x00<br />

0x08<br />

0x10<br />

然 后 系 统 跳 转 到 main.c, 由 于 段 选 择 符 为 0x08, 所 以 基 地 址 为 0x0000000<br />

<strong>JOS</strong> 把 第 一 个 扇 区 加 载 到 0x10000 处 (elf), 然 后 根 据 elf 的 参 数 把 内 核 部 分 加 载 到<br />

0x1000000 处 , 现 在 观 察 kernel.ld, 里 面 定 义 了 开 始 地 址 为 0xF01000000, 所 以<br />

entry.S 里 面 的 代 码 的 eip 都 是 0xF0100000++, 然 后 bootmain 的 最 后 一 句 跳 转 到<br />

0x10000c 处 , 开 始 执 行 entry.S 的 代 码 .<br />

entry.S 中<br />

一 开 始 就 lgdt, 把 gdt 变 了 , 在 lgdt 的 时 候 有 一 个 宏 RELOC, 这 个 宏 的 作 用 是 把 虚 拟 地<br />

址 转 换 成 实 地 址<br />

0xF0100000<br />

- 0xF0000000(KERNBASE)<br />

0x00100000<br />

所 以 , 程 序 能 够 正 确 的 加 载 到 mygdtdesc<br />

加 载 后 gdt 如 下 :<br />

NULL<br />

-KERNBASE<br />

0x00<br />

0x08<br />

-KERNBASE<br />

0x10<br />

然 后 跳 转 到 CODE_SEL, 从 现 在 开 始 , 段 基 地 址 变 成 0X10000000, 所 以 所 有 虚 拟 地 址


(0xF0100000++) 的 地 址 , 经 过 段 转 换 之 后 都 会 变 成 0x00100000++<br />

0x10000000<br />

+0xF0100000 ++(EIP)<br />

0x00100000++<br />

现 在 EIP 是 0xf0100000 基 地 址 是 0x10000000, 程 序 可 以 正 确 运 行 .<br />

分 析 到 这 里 , 我 们 可 以 画 出 比 较 完 整 的 内 存 分 布 图 :<br />

物 理 地 址 虚 拟 地 址 内 核 结 构 ( 虚 拟 地 址 )<br />

0X00 0X00 0XF0100000<br />

text<br />

0x7C00<br />

bootsect<br />

etext<br />

0x10000<br />

elf<br />

0xf0100000<br />

KERN<br />

_STAB_BEGIN_<br />

0x100000<br />

kern<br />

_STAB_END_<br />

STABSTR_BEGIN<br />

_STABSTR_END<br />

edata<br />

end


以 上 数 据 可 以 从 kernel.ld 中 得 到 。<br />

下 面 进 入 pmap.c<br />

I386_detct_memory 中 , 可 以 得 到 一 些 全 局 变 量<br />

base = 640K<br />

extmem = 31744K<br />

maxpa = EXTPHYSMEM + extmem = 32M<br />

npage = maxpa/1024<br />

现 在 进 入 vm_init<br />

先 去 boot_alloc 函 数 , 这 个 函 数 的 作 用 是 在 内 核 地 址 后 分 配 一 块 nbyte 的 内 存 空 间 , 返 回<br />

内 存 空 间 的 首 地 址 , 空 间 的 首 地 址 必 须 是 4k 的 倍 数 。free_mem 指 向 内 存 空 间 末 尾 。<br />

pages = boot_alloc(), 先 内 存 空 间 如 下 图 所 示 :<br />

end<br />

freemem<br />

虚 拟 地 址 :<br />

4K<br />

0xf0100000<br />

pgdir<br />

boot_alloc 中 应 该 添 加 的 代 码 如 下 :<br />

然 后 回 到 vminit 中 :<br />

这 两 句 代 码 暂 时 不 知 道 是 做 什 么 用 的 .<br />

然 后 是<br />

分 配 pages<br />

分 配 完 以 后 , 内 存 布 局 如 下 :<br />

虚 拟 地 址 :<br />

end<br />

4K<br />

freemem


0xf0100000 pgdir pages<br />

接 着 是 page_init:<br />

要 明 白 这 个 函 数 到 底 是 什 么 回 事 , 必 须 要 明 白 pages 数 组 , 到 底 是 怎 么 回 事 .<br />

pages 的 原 理 如 下 图 :<br />

物 理 内 存<br />

PAGE* pages:<br />

空<br />

闲<br />

链<br />

表<br />

4B<br />

4B<br />

4B<br />

4B<br />

4B<br />

.<br />

.<br />

.<br />

.<br />

.<br />

.<br />

.<br />

4K<br />

4K<br />

4K<br />

4K<br />

4K<br />

4K<br />

4K<br />

4K<br />

4K<br />

.<br />

.<br />

.<br />

.<br />

.<br />

.<br />

.<br />

这 里 , 我 们 只 要 知 道 pages[x] 的 地 址 , 就 可 以 计 算 出 对 应 的 物 理 内 存 页 的 物 理 地 址 ( 很 容 易 算<br />

的 ). 然 后 pages[x] 里 面 有 存 储 着 链 表 需 要 的 指 针 , 这 个 链 表 是 记 录 着 那 些 也 是 空 闲 的 .pages[x]<br />

里 面 还 保 存 了 一 个 pp_ref, 用 来 记 录 页 面 的 引 用 次 数 .<br />

然 后 , 我 们 看 看 物 理 内 存 里 面 的 数 据 分 布 是 怎 样 , 如 下 :<br />

物 理 地 址 :<br />

IDT<br />

IO*MEM EXT*MEM end-KERNBASE freemem-KERNBASE<br />

KERN<br />

4K<br />

0X00000000 0x00100000 pgdir-KERNBASE pages - KERNBASE<br />

到 这 里 ,page_init 的 作 用 就 是 把 以 上 有 颜 色 的 部 分 标 记 为 已 经 使 用 。 然 后 再 空 闲 链 表 中 把<br />

以 上 页 删 除 。<br />

代 码 如 下 :


现 在 进 入 page_alloc 函 数 :<br />

这 个 函 数 是 用 来 分 配 一 个 页 。<br />

具 体 是 从 空 闲 链 表 中 删 除 一 个 页 , 然 后 返 回 这 个 页 。 代 码 如 下 :<br />

page_free 函 数 :<br />

就 是 从 空 闲 链 表 中 插 入 一 个 空 闲 页 , 代 码 如 下 :<br />

pgdir_walk 函 数 :<br />

这 个 函 数 是 一 个 重 要 的 函 数 , 基 本 上 如 果 明 白 了 这 个 函 数 之 后 , 所 有 的 函 数 都 理 解 , 也 就<br />

是 说 , 理 解 了 这 个 函 数 之 后 , 整 个 虚 拟 内 存 管 理 系 统 都 会 了 然 于 胸 。<br />

具 体 功 能 是 : 给 出 线 性 地 址 , 然 后 返 回 线 性 地 址 对 应 的 二 级 页 表 的 页 表 项 的 虚 拟 地 址 ( 虚<br />

拟 地 址 , 因 为 在 代 码 中 用 到 的 地 址 必 须 是 虚 拟 地 址 , 但 是 放 在 页 目 录 和 二 级 页 表 中 的 地 址<br />

必 须 是 物 理 地 址 , 因 为 是 cpu 直 接 操 作 这 些 数 据 , 不 是 我 们 的 <strong>JOS</strong> 操 作 )


现 在 先 看 看 页 目 录 的 结 构 :<br />

二 级 页 表<br />

pgdir:<br />

4B( 二 级 页 表 的<br />

物 理 地 址 (10b)<br />

+ 特 权 )<br />

4B<br />

4B<br />

4B<br />

.<br />

.<br />

.<br />

.<br />

.<br />

4B( 物 理 页 的 物 理<br />

地 址 (10b)<br />

4B<br />

4B<br />

4B<br />

4B<br />

.<br />

.<br />

物 理 页<br />

pgdir_walk 返 回 的 虚 拟 地 址 指 向 的 二 级 页 表 项<br />

有 了 以 上 分 析 , 实 现 这 个 函 数 就 不 难 了 , 但 是 一 定 要 搞 清 楚 什 么 时 候 用 虚 拟 地 址 , 什 么 时<br />

候 用 物 理 地 址 , 总 的 来 说 就 是 cpu 自 动 进 行 的 操 作 用 物 理 地 址 , 但 是 我 们 <strong>JOS</strong> 进 行 的 操 作<br />

( 也 就 是 我 们 写 的 代 码 ) 就 用 虚 拟 地 址 。 代 码 如 下 :


把 上 述 道 理 弄 明 白 , 基 本 上 已 经 达 到 我 们 实 验 的 目 的 了 。 下 面 的 函 数 实 现 不 是 事 问 题 :<br />

boot_map_segment 函 数 :<br />

把 指 定 的 线 性 地 址 和 物 理 地 址 绑 定 。 这 很 简 单 , 只 要 在 线 性 地 址 对 应 的 二 级 页 表 中 写 入 物<br />

理 地 址 对 应 的 物 理 页 的 地 址 就 可 以 了 。 代 码 如 下 :


page_lookup 函 数 :<br />

给 出 线 性 地 址 va, 我 只 能 说 代 码 里 面 把 它 写 成 虚 拟 地 址 害 人 不 浅 , 虽 然 我 不 能 说 它 错 !<br />

返 回 va 对 应 的 页 的 虚 拟 地 址 , 就 是 pages 里 面 的 一 项 的 地 址 。 代 码 如 下 :<br />

page_remove 函 数 :<br />

删 除 线 性 地 址 va 对 应 的 一 个 页 。<br />

这 里 把 二 级 页 表 中 的 表 项 置 0, 当 然 还 要 涉 及 到 空 闲 链 表 , 但 是 这 些 事 情 page_decref 已 经<br />

帮 我 们 做 了 。 代 码 如 下 :<br />

page_insert 函 数 :<br />

这 个 函 数 就 是 在 线 性 地 址 va 对 应 的 二 级 页 表 项 插 入 指 定 页 。


具 体 代 码 如 下 :<br />

现 在 是 在 i386_vm_init 里 面 添 加 代 码 :<br />

现 在 分 页 管 理 系 统 的 基 本 函 数 已 经 完 成 , 接 下 来 就 是 要 按 照 <strong>JOS</strong> 作 者 的 设 计 意 图 把 线 性 地<br />

址 映 射 到 对 应 的 物 理 地 址 .<br />

具 体 如 下 图 :


线 性 地 址 :<br />

0X00000000<br />

KSTACKTOP-KSTKSIZE<br />

4M<br />

4M<br />

4M<br />

4M<br />

UPAGES UVPT ULIM KSTACKTOP KERNBASE<br />

pages-..... bootstack-...... 0-.....<br />

上 面 所 写 的 pages-..... 的 意 思 是 pages 的 物 理 地 址 到 后 面 的 一 段 空 间 , 这 里 是 pagespages+npage*sizeof(Page),<br />

bootstack 同 上 ,0 代 表 物 理 地 址 0。<br />

代 码 如 下 :<br />

关 于 一 些 特 权 级 的 说 明 如 下 :


EXERCISE 6<br />

问 题 一 : 上 面 的 图 已 经 回 答 一 切 。<br />

问 题 二 : 这 个 问 题 比 较 有 趣<br />

我 们 之 前 通 过<br />

把 线 性 地 址 [KERNBASE,0XFFFFFFFF) 映 射 到 物 理 地 址 的 [0,0XFFFFFFFF - KERNBASE +1) 处<br />

也 就 是 说 , 如 果 分 页 机 制 开 了 , 我 们 给 出 线 性 地 址 0xf0100000 ++ , 那 么 就 会 映 射 到 物 理 地<br />

址 0x00100000++ 上 。<br />

由 于 当 前 虚 拟 地 址 的 值 是 0XF0100000 ++ , 经 过 段 转 换 之 后 变 成 0x00100000, 如 果 没 有 开<br />

启 分 页 机 制 , 那 么 刚 好 的 内 核 所 在 的 物 理 地 址 。<br />

但 是 如 果 开 启 了 分 页 机 制 之 后 ,0x00100000 二 进 制 是 0000000000 0100000000<br />

0000000000000, 对 应 的 是 页 目 录 的 第 一 项 , 但 是 页 目 录 的 第 一 项 我 们 是 没 有 设 置 映 射 的 ,<br />

所 以 虚 拟 地 址 对 应 的 物 理 地 址 是 我 们 不 知 道 , 但 是 如 果 我 们 把 pgdir[0] =<br />

pgdir[pdx(kernbase)] 之 后 ,pgdir[pdx(0x00100000)] 和 pgdir[pdx(0xf0100000)] 的 值 是 一 样 的 ,<br />

也 就 是 说 线 性 地 址 0x00100000++ 也 是 映 射 到 了 物 理 地 址 0x00100000++ 后 面 。<br />

问 题 三 :<br />

因 为 有 保 护 位 的 原 因 PTE_W PTE_U 这 些 宏 决 定 了 内 存 空 间 的 可 访 问 性 。<br />

问 题 四 :<br />

4G, 因 为 是 32 位 的 地 址 线 。<br />

问 题 五 :<br />

开 销 是 :npage * sizeof(Pages) + pgdir[4k] + 1024 * 4k( 如 果 全 部 二 级 页 表 都 用 上 的 话 ), 如 果<br />

是 4G 的 内 存 , 那 么 npage 的 值 就 会 使 4G/4096<br />

如 果 完 全 明 白 上 面 的 东 西 challenge 应 该 问 题 不 大 。

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!