Presentation is loading. Please wait.

Presentation is loading. Please wait.

Linux 操作系统分析 主讲:陈香兰 助教:贾永泉、毛熠璐 3606864-83 (西区电三 421 ) Autumn 2007.

Similar presentations


Presentation on theme: "Linux 操作系统分析 主讲:陈香兰 助教:贾永泉、毛熠璐 3606864-83 (西区电三 421 ) Autumn 2007."— Presentation transcript:

1 Linux 操作系统分析 主讲:陈香兰 助教:贾永泉、毛熠璐 xlanchen@ustc.edu.cn 3606864-83 (西区电三 421 ) Autumn 2007

2 xlanchen@2007.9.13Linux Operating System Analysis2 上次课内容回顾 Linux 简介 Linux 内核分析的一些基础知识 操作系统基本概念 堆栈 用户态 / 内核态 虚拟内存

3 基于 i386 体系结构的 Linux 启动代码分析 xlanchen@2007.9.13

4 Linux Operating System Analysis4 主要内容 源代码简介 启动代码简介 Linux 内核代码组成分析 Linux 的启动层次 Linux 的启动分析

5 xlanchen@2007.9.13Linux Operating System Analysis5 源代码来源 根据《 Understanding the Linux Kernel 》 ( 2 nd Edition ),我们采用 Linux-2.4.18 有中文版 下载地址: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux- 2.4.18.tar.gz 加压缩后,建立 Source Insight 工程

6 xlanchen@2007.9.13Linux Operating System Analysis6 Source Insight 可以用来辅助代码阅读 到 http://www.sourceinsight.com/ 上可以下载 到它的试用版,试用期估计在 30 天左右 http://www.sourceinsight.com/

7 xlanchen@2007.9.13Linux Operating System Analysis7 Linux-2.6.11 阅读 linux 目录下的 README 关于 Linux 的介绍 该版本内核支持的体系结构 如何配置、编译、安装

8 xlanchen@2007.9.13Linux Operating System Analysis8 Linux 内核源代码中的主要子目录 Documentation 内核方面的相关文档。 arch 与体系结构相关的代码。对应于每个 支持的体系结构,有一个相应的目录 如 i386 、 arm 、 alpha 等。每个体系结 构子目录下包含几个主要的子目录: kernel 与体系结构相关的核心代码 mm 与体系结构相关的内存管理代码 lib 与体系结构相关的库代码 include 内核头文件。对每种支持的体系结构 有相应的子目录。 init 内核初始化代码。

9 xlanchen@2007.9.13Linux Operating System Analysis9 kernel 内核管理代码。 mm 内存管理代码。 ipc 进程间通讯代码。 net 网络部分代码。 lib 与体系结构无关的内核库代码。 drivers 设备驱动代码。每类设备有相应的子 目录,如 char 、 block 、 net 等 fs 文件系统代码。每个支持文件系统有 相应的子目录,如 ext2 、 proc 等。 modules 可动态加载的模块。 Scripts 配置核心的脚本文件。

10 xlanchen@2007.9.13Linux Operating System Analysis10 考虑 Arch 为 i386 在 arch/i386 下存在如下目录 I386 的启动源代码文件目录 I386 的核心源代码文件目录 I386 的库源代码文件目录 I386 的数学仿真源代码文件目录 I386 的内存管理源代码文件目录 I386 的配置文件 I386 的体系相关部分的 Makefile I386 的 Linux 内核的链接描述文件

11 xlanchen@2007.9.13Linux Operating System Analysis11 I386 的启动代码文件 在 arch/i386/boot 目录下 在 arch/i386/boot/compressed 目录下 I386 的体系结构相关部分的启动代码 都采用汇编码写的 启动扇区中的启动代码, 其目标码必然是 512 字节 I386 初始化 内核解压缩

12 xlanchen@2007.9.13Linux Operating System Analysis12 在 arch/i386/kernel 目录下的.S 文件 在 init 目录下 32 位启动代码 这是体系结构无关部分, i386 体系结构相关部分的启动, 其目的就是进入 main.c 中的 start_kernel 处执行

13 xlanchen@2007.9.13Linux Operating System Analysis13 阅读 documentation/i386/boot.txt 对于 i386 平台,由于一些历史的原因,因此 Linux 的启动比较复杂 这个文档包含如下内容 1 、 Linux/i386 的启动协议( 4 个) 2 、内存布局图 3 、实模式下的内核头结构 4 、内核的命令行( command line )

14 xlanchen@2007.9.13Linux Operating System Analysis14 5 、启动配置示例 6 、装载 Linux 的剩余部分 7 、特殊的命令行参数 8 、运行内核 9 、高级启动回调函数 关于其中的一些内容,我们将在合适的时候说 明

15 xlanchen@2007.9.13Linux Operating System Analysis15 阅读顶层目录下的 Makefile 找到缺省目标 链接

16 xlanchen@2007.9.13Linux Operating System Analysis16 找到 vmlinux vmlinux 找到 vmlinux 所依赖的各个文件或者目标 可以看到 vmlinux 包含如下内容 i386/kernel/head.S + init/main.c + init/version.o + CORE_FILES + DRIVERS + NETWORKS + LIBS

17 xlanchen@2007.9.13Linux Operating System Analysis17 若 make install 在 i386 的 Makefile 中有 install 规则 若 make boot/bzImage/zImage 等等,则要找 到对应的目标然后进行 make boot 在顶层的 Makefile 中可以找到 boot 规则 boot bzImage/zImage 可以在 i386 的 Makefile 中找到相应 规则 Makefile 其他的 zXXX/bzXXX 也都依赖于 boot 下的 zImage/bzImage 它们最终都找到 i386/boot 的 Makefile

18 xlanchen@2007.9.13Linux Operating System Analysis18 i386/boot 的 Makefile 看 i386/boot 的 Makefile Makefile z 代表压缩; b 代表大内核 可见 compressed 下的 vmlinux/bvmlinux 为 compressed/head.S + 压缩后的顶层目录下的 vmlinux zImage 为 bootsect + setup + compressed/vmlinux bzImage 为 bbootsect + bsetup + compressed/bvmlinux

19 xlanchen@2007.9.13Linux Operating System Analysis19 下面根据在 bzImage/zImage 中的顺序,我们 依次看启动相关的源代码和相关概念 arch/i386/boot/bootsect.S arch/i386/boot/setup.S arch/i386/boot/compressed/head.S arch/i386/kernel/head.S 最后进入 kernel/main.C

20 xlanchen@2007.9.13Linux Operating System Analysis20 I386 机器的启动层次 BIOS (Basic I/O System) Boot loader 软盘启动、硬盘启动 Linux kernel

21 xlanchen@2007.9.13Linux Operating System Analysis21 BIOS 加电, RESET 引脚 初始化寄存器; CS:IP = 0xfffffff0, in ROM ROM  BIOS BIOS 启动内容 POST (上电自检) 初始化硬件设备 搜索一个操作系统来启动 根据配置,操作系统可以在软盘 / 硬盘 /CD_ROM 上 把对应设备的第一个扇区的内容( boot loader 或部分)拷贝 到 RAM(0x7c00) 处 跳转到 0x7c00 处执行

22 xlanchen@2007.9.13Linux Operating System Analysis22 Boot loader (引导装载程序) BIOS 调用 Boot loader 来把操作系统的内核映像装载 到 RAM 中 考虑 IBM PC 的启动 软盘启动: BIOS 拷贝第一个扇区的内容( bootsect )到 RAM ( 0x7c00 )中 硬盘启动: 硬盘的第一个扇区:主引导记录 MBR, Master Boot Record , MBR 存储该硬盘的分区表 + 一小段引导程序 这个引导程序用来装载 OS 所在分区的第一个扇区( boot loader )的内容到 RAM 中 这个引导程序也可以被替换

23 xlanchen@2007.9.13Linux Operating System Analysis23 Linux 的 Boot Loader 典型的有: LILO 和 Grub LILO ( Linux Loader ) 可以被安装在 OS 分区的第一个扇区(启动扇区) 也可以代替 MBR 中的引导程序 事实上, LILO 的代码尺寸大于一个扇区,因此被分成 两个部分 MBR 或启动扇区部分 剩余部分 第一部分也被 BIOS 装载到 RAM 中 0x7c00 的位置 第一部分在运行时将自己完整的装载到 RAM 中

24 xlanchen@2007.9.13Linux Operating System Analysis24 Linux 的 Boot Loader 通常 LILO 或 GRUB 会显示一个已安装操作系统 的列表 按照用户的选择(或者按照缺省项)装载目标 操作系统运行 可能装载操作系统指定的启动代码运行 可能直接装载操作系统内核来运行

25 xlanchen@2007.9.13Linux Operating System Analysis25 LILO 的 OS 启动过程 显示 “Loading…” 操作系统前 512 (一个扇区大小, bootsect ) 的内容被装载到 RAM 的 0x90000 紧接着的内容( setup )被装在到 0x90200 其他操作系统内核被装载到 对于小内核: 0x10000 (即 64K 处),称为低装载 对于大内核: 0x100000 (即 1M 处),称为高装载 跳转到 setup 处运行

26 xlanchen@2007.9.13Linux Operating System Analysis26 I386 内核的启动 启动方式 软盘启动:从 bootsect 开始运行 硬盘启动:从 setup 开始运行 在进入 bootsect.S 的源代码讲解之前,我们先 看一下加载 i386 内核的内存布局图

27 xlanchen@2007.9.13Linux Operating System Analysis27 硬件角度: I386 实模式下的内存布局图 RAM 1-MB ROM-BIOS VIDEO-BIOS VRAM 0xA0000 0xC0000 0xF0000 0x00000

28 xlanchen@2007.9.13Linux Operating System Analysis28 I386 内核从实模式开始启动运行 首先看一下什么是实模式 实模式是为了兼容早期的 CPU 而设置的 i386 系统总是始于实模式 实模式下 地址总线: 20 位 内存范围: 0~1MB 逻辑地址 = 段地址 + 段内偏移 段地址 = 段寄存器中的值 *16 (或左移 4 位) 段寄存器长度: 16bit

29 xlanchen@2007.9.13Linux Operating System Analysis29 加载 I386 内核的内存布局图 zImage/Image 的内核加载器所使用的经 典的内存布局( 1M=0x100000 ) 低装载情况

30 xlanchen@2007.9.13Linux Operating System Analysis30 软盘启动, bootsect.S bootsect.S 0x7c00  0x90000 0x7c00, BIOS 0x90000, lilo 堆栈, 0x3ff4(0x4000-12), 向下增长 磁盘参数表, 12Bytes , 0x3ff4~0x4000 显示 “Loading” Setup  0x90200 系统 小内核, 0x10000 ( 64KB 处),低装载 大内核, 0x100000 ( 1MB 处),高装载 setup

31 xlanchen@2007.9.13Linux Operating System Analysis31 硬盘启动,两阶段引导 装载 LILO ( LInuxLOader ) 第一个扇区 … 装载 LINUX Bootsect.S  0x90000 Setup.S  0x90200 系统 0x10000 0x100000 跳转到 setup

32 xlanchen@2007.9.13Linux Operating System Analysis32 启动第一步,小结 总之,在跳转到 setup 的时候,内存里面的代 码布局为 0x90000 : bootsect 0x90200 : setup 低装载: 0x10000 :带解压的 vmlinux 高装载: 0x100000 :带解压的 bvmlinux 实模式下的内核头结构 包括 bootsect 的最后和 setup 开始的位置 从 bootsect 的偏移 0x1F1 开始,具体描述参见 documentation/i386/boot.txt documentation/i386/boot.txt

33 xlanchen@2007.9.13Linux Operating System Analysis33 Setup Setup : 0x90200 初始化硬件设备并为内核程 序的执行建立环境 内存检测 键盘 视频 磁盘控制器 IBM 微通道总线 MCA PS/2 设备(总线鼠标) APM BIOS 若低装载,将系统移动到 0x1000 处( 4KB 处) 否则,不必 临时 IDT 和临时 GDT FPU PIC, 16 个硬件中断  中断向 量 32~47 实模式  保护模式 Startup_32

34 xlanchen@2007.9.13Linux Operating System Analysis34 在 compressed/head.S 和 head.S 中都定义了 startup_32 但是 head.S 中,被压缩在 vmlinux 中还没有解压缩 只有 compressed/head.S 的 startup_32 是可用的 zImage 中,在 0x1000 处 bzImage 中,在 0x100000 处

35 xlanchen@2007.9.13Linux Operating System Analysis35 Compressed/head.S Startup_32 初始化段寄存器和一个临时堆栈 初始化 BSS 段 解压缩 高装载或低装载  解压缩  0x100000 ( 1MB ) 跳转到 0x100000 处

36 xlanchen@2007.9.13Linux Operating System Analysis36 解压缩后, vmlinux 在 0x100000 处 根据 vmlinux.lds , vmlinux 的地址被链接为 0xc0000000+0x100000 处 vmlinux.lds 如何正确运行呢? 此时仍然是实模式,还没有进入保护模式、分页、 映射好 没有长跳转,只使用采用相对地址的近距离跳转

37 xlanchen@2007.9.13Linux Operating System Analysis37 Head.S Startup_32 初始化段寄存器 建立进程 0 的内核堆栈 Setup_idt 拷贝系统参数 识别处理器 GDT 、 IDT Start_kernel

38 xlanchen@2007.9.13Linux Operating System Analysis38 与内存相关的一些概念 在实模式下,地址总线 20 位,访存范围为 1MB , 物理地址使用段址:偏移的方式表示 段址保存在段寄存器中,段寄存器有: cs/ds/es/fs/gs 16 位寄存器,偏移也是 16 位,因此最大段长为 2 16 =0x10000=64KB 物理地址 = 段寄存器 ×16+ 偏移

39 xlanchen@2007.9.13Linux Operating System Analysis39 保护模式下,地址总线 32 位,访存范围为 4GB 原来的段寄存器现在被称作段选择子,与 GDT 表配合使用 GDT 表由 gdtr 指示其位置和长度 使用特殊的指令进行操作: sgdt/lgdt

40 xlanchen@2007.9.13Linux Operating System Analysis40 图示 descriptor Interrupt Descriptor Table Global Descriptor Table GDTR IDTR

41 xlanchen@2007.9.13Linux Operating System Analysis41 查看 setup.S 和 head.S 中的 gdt/ldt setup.S head.S 一般装载 gdt 和 idt 之后,要重新装载段寄存器 cs 、 ds 、 es 、 fs 、 gs cs 通常通过一条长跳转指令装载 其他数据段寄存器直接设置

42 xlanchen@2007.9.13Linux Operating System Analysis42 控制寄存器( Control Registers ) CR0 CR1 CR2 CR3 与内存相关

43 xlanchen@2007.9.13Linux Operating System Analysis43 CR0 CR0, MSW register (Machine Status Word, 32-bit version) 包含系统控制位,用于控制操作模式和状态 Instruction: lmsw LINUX’ setup.S: movw $1, %ax lmsw %ax jmp flush_instr // why? flush_instr: To turn on the PE-bit (enables protected-mode), PE-bit (Protection Enabled) 0  CPU is in real-mode, 1  CPU is in protected-mode

44 xlanchen@2007.9.13Linux Operating System Analysis44 CR1 、 CR2 、 CR3 CR1 :保留 CR2 :在缺页异常的时候,记录缺页地址 CR3 :记录页目录所在的物理地址和两个标记 (PCD & PWT)

45 xlanchen@2007.9.13Linux Operating System Analysis45 作业 2 i386 实模式下是如何解决 20 位地址空间和 16 位 段寄存器之间的不匹配问题的? i386 保护模式下的段寄存器的内容与实模式下 段寄存器的内容一样么?如何解释? 简单叙述一下 Linux 的 bzImage 的软盘启动过程


Download ppt "Linux 操作系统分析 主讲:陈香兰 助教:贾永泉、毛熠璐 3606864-83 (西区电三 421 ) Autumn 2007."

Similar presentations


Ads by Google