Download presentation
Presentation is loading. Please wait.
1
Linux 操作系统分析 中国科学技术大学计算机系 陈香兰( 0512 - 87161312 ) xlanchen@ustc.edu.cn 助教:裴建国、冯晓静 Autumn 2008
2
上次课内容回顾 Linux 简介 Linux 内核分析的一些基础知识 操作系统基本概念 堆栈 用户态 / 内核态 虚拟内存 分析和实验验证环境 VMware SourceInsight
3
基于 i386 体系结构的 Linux 启动代码分析 中国科学技术大学计算机系 陈香兰( 0512 - 87161312 ) xlanchen@ustc.edu.cn Autumn 2008
4
主要内容 源代码简介 启动代码简介 Linux 内核代码组成分析 Linux 的启动层次 Linux 的启动分析 需要的技能: makefile 阅读能力 gcc ; ld ; nm ;等
5
源代码来源 根据《 Understanding the Linux Kernel 》( 2 nd Edition ),我们采用 Linux-2.4.18 ,《 Understanding the Linux Kernel 》( 2 nd Edition ) 有中文版 下载地址: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux- 2.4.18.tar.gz 解压缩后,建立 Source Insight 工程
6
Linux-2.4.18 阅读 linux 目录下的 README 关于 Linux 的介绍 该版本内核支持的体系结构 如何配置、编译、安装
7
Linux 内核源代码中的主要子目录 Documentation 内核方面的相关文档。 arch 与体系结构相关的代码。对应于每个 支持的体系结构,有一个相应的目录 如 i386 、 arm 、 alpha 等。每个体系结 构子目录下包含几个主要的子目录: kernel 与体系结构相关的核心代码 mm 与体系结构相关的内存管理代码 lib 与体系结构相关的库代码 include 内核头文件。对每种支持的体系结构 有相应的子目录。 init 内核初始化代码。
8
kernel 内核管理代码。 mm 内存管理代码。 ipc 进程间通讯代码。 net 网络部分代码。 lib 与体系结构无关的内核库代码。 drivers 设备驱动代码。每类设备有相应的子 目录,如 char 、 block 、 net 等 fs 文件系统代码。每个支持文件系统有 相应的子目录,如 ext2 、 proc 等。 modules 可动态加载的模块。 Scripts 配置核心的脚本文件。
9
考虑 Arch 为 i386 在 arch/i386 下存在如下目录 I386 的启动源代码文件目录 I386 的核心源代码文件目录 I386 的库源代码文件目录 I386 的数学仿真源代码文件目录 I386 的内存管理源代码文件目录 I386 的配置文件 I386 的体系相关部分的 Makefile I386 的 Linux 内核的链接描述文件
10
I386 的启动代码文件 在 arch/i386/boot 目录下 在 arch/i386/boot/compressed 目录下 I386 的体系结构相关部分的启动代码 都采用汇编码写的 启动扇区中的启动代码, 其目标码必然是 512 字节 I386 初始化 内核解压缩
11
在 arch/i386/kernel 目录下的.S 文件 在 init 目录下 32 位启动代码 这是体系结构无关部分, i386 体系结构相关部分的启动, 其目的就是进入 main.c 中的 start_kernel 处执行
12
阅读 documentation/i386/boot.txt documentation/i386/boot.txt 对于 i386 平台,由于一些历史的原因,因此 Linux 的启动比较复杂 这个文档包含如下内容 1 、 Linux/i386 的启动协议( 4 个) 2 、内存布局图 3 、实模式下的内核头结构 4 、内核的命令行( command line )
13
5 、启动配置示例 6 、装载 Linux 的剩余部分 7 、特殊的命令行参数 8 、运行内核 9 、高级启动回调函数
14
阅读顶层目录下的 Makefile 找到缺省目标 链接
15
找到 vmlinux vmlinux 找到 vmlinux 所依赖的各个文件或者目标 可以看到 vmlinux 包含如下内容 i386/kernel/head.S + init/main.c + init/version.o + CORE_FILES + DRIVERS + NETWORKS + LIBS
16
若 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
17
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
18
下面根据在 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
19
I386 机器的启动层次 BIOS (Basic I/O System) Boot loader 软盘启动、硬盘启动 Linux kernel
20
BIOS 加电, RESET 引脚 初始化寄存器; CS:IP = 0xfffffff0, in ROM ROM BIOS BIOS 启动内容 POST (上电自检) 初始化硬件设备 搜索一个操作系统来启动 根据配置,操作系统可以在软盘 / 硬盘 /CD_ROM 上 把对应设备的第一个扇区的内容( boot loader 或部分)拷贝到 RAM(0x7c00) 处 跳转到 0x7c00 处执行 CPU 加电后,将会初始化程序指针到某个约定 好的地址上取指令运行,在这个地指处,往往 安排了启动相关的代码,例如 BIOS 或者 reset 向量处理入口
21
Boot loader (引导装载程序) BIOS 调用 Boot loader 来把操作系统的内核映像装载到 RAM 中 考虑 IBM PC 的启动 软盘启动: BIOS 拷贝第一个扇区的内容( bootsect )到 RAM ( 0x7c00 )中 硬盘启动: 硬盘的第一个扇区:主引导记录 MBR, Master Boot Record , MBR 存 储该硬盘的分区表 + 一小段引导程序 这个引导程序用来装载 OS 所在分区的第一个扇区( boot loader )的 内容到 RAM 中 这个引导程序也可以被替换
22
Linux 的 Boot Loader 典型的有: LILO 和 Grub LILO ( Linux Loader ) 可以被安装在 OS 分区的第一个扇区(启动扇区) 也可以代替 MBR 中的引导程序 事实上, LILO 的代码尺寸大于一个扇区,因此被分成两 个部分 MBR 或启动扇区部分 剩余部分 第一部分也被 BIOS 装载到 RAM 中 0x7c00 的位置 第一部分在运行时将自己完整的装载到 RAM 中
23
Linux 的 Boot Loader 通常 LILO 或 GRUB 会显示一个已安装操作系统 的列表 按照用户的选择(或者按照缺省项)装载目标操 作系统运行 可能装载操作系统指定的启动代码运行 可能直接装载操作系统内核来运行
24
LILO 的 OS 启动过程 显示 “Loading…” 操作系统前 512 字节(一个扇区大小, bootsect ) 的内容被装载到 RAM 的 0x90000 紧接着的内容( setup )被装在到 0x90200 其他操作系统内核被装载到 对于小内核: 0x10000 (即 64K 处),称为低装载 对于大内核: 0x100000 (即 1M 处),称为高装载 跳转到 setup 处运行
25
I386 内核的启动 启动方式 软盘启动:从 bootsect 开始运行 硬盘启动:从 setup 开始运行 在进入 bootsect.S 的源代码讲解之前,我们先看 一下加载 i386 内核的内存布局图 BIOS bootsect LILO , Grub 等 boot loader setup 0x7c00: 0x90200:
26
硬件角度: I386 实模式下的内存布局图 RAM 1-MB ROM-BIOS VIDEO-BIOS VRAM 0xA0000 0xC0000 0xF0000 0x00000
27
I386 内核从实模式开始启动运行 首先看一下什么是实模式 实模式是为了兼容早期的 CPU 而设置的 i386 系统总是始于实模式 实模式下 地址总线: 20 位 内存范围: 0~1MB 逻辑地址 = 段地址 + 段内偏移 段地址 = 段寄存器中的值 *16 (或左移 4 位) 段寄存器: cs/ds/es/fs/gs 段寄存器长度: 16bit 段长: 16 位偏移 64KB
28
加载 I386 内核的内存布局图 zImage/Image 的内核加载器所使用的经 典的内存布局( 1M=0x100000 )
29
软盘启动, bootsect.S bootsect.S 0x7c00 0x90000 0x7c00, BIOS 0x90000, lilo 堆栈, 0x3ff4(0x4000-12), 向下增长 磁盘参数表, 12Bytes , 0x3ff4~0x4000 显示 “Loading” Setup 0x90200 系统 小内核, 0x10000 ( 64KB 处),低装载 大内核, 0x100000 ( 1MB 处),高装载 setup ljmp …… go:…… ljmp …… 0x7C00 低 高 0x7E00 0x90000 0x90200 ljmp …… go:…… ljmp …… cs:ip 0x4000 0x4000-12 cs:ip ss sp setup sys 0x10000 cs:ip
30
硬盘启动,两阶段引导 装载 LILO ( LInuxLOader ) 第一个扇区 … 装载 LINUX Bootsect.S 0x90000 Setup.S 0x90200 系统 0x10000 0x100000 跳转到 setup
31
启动第一步,小结 总之,在跳转到 setup 的时候,内存里面的代码 布局为 0x90000 : bootsect 0x90200 : setup 低装载: 0x10000 :带解压的 vmlinux 高装载: 0x100000 :带解压的 bvmlinux 实模式下的内核头结构 包括 bootsect 的最后和 setup 开始的位置 从 bootsect 的偏移 0x1F1 开始,具体描述参见 documentation/i386/boot.txt documentation/i386/boot.txt
32
Setup Setup : 0x90200 初始化硬件设备并为内核程序 的执行建立环境 内存检测 键盘 视频 磁盘控制器 IBM 微通道总线 MCA PS/2 设备(总线鼠标) APM BIOS 若低装载,将系统移动到 0x1000 处( 4KB 处) 否则,不必 临时 IDT 和临时 GDT FPU PIC, 16 个硬件中断 中断 向量 32~47 实模式 保护模式 Startup_32
33
关于保护模式: 在 setup 中,从实模式 保护模式 保护模式下,地址总线 32 位,访存范围为 4GB 原来的段寄存器现在被称作段选择子,与 GDT 表配合使用 GDT 表由 gdtr 指示其位置和长度 使用特殊的指令进行操作: sgdt/lgdt
34
图示 descriptor Global Descriptor Table GDTR descriptor Interrupt Descriptor Table IDTR indexTIRPL 2 1 0 15 Segment selector 线性空间 (没有开启 页表机制 时,即物 理空间)
35
段描述符的格式 段基址、 段长度、 其他属性
36
一般装载 gdt 和 idt 之后,要重新装载段寄存器 cs 、 ds 、 es 、 fs 、 gs cs 通常通过一条长跳转指令装载 其他数据段寄存器直接设置
37
在 compressed/head.S 和 head.S 中都定义了 startup_32 但是 head.S 中,被压缩在 vmlinux 中还没有解压缩 只有 compressed/head.S 的 startup_32 是可用的 zImage 中,在 0x1000 处 bzImage 中,在 0x100000 处
38
Compressed/head.S Startup_32 初始化段寄存器和一个临时堆栈 初始化 BSS 段 解压缩 高装载或低装载 解压缩 0x100000 ( 1MB ) 跳转到 0x100000 处
39
解压缩后, vmlinux 在 0x100000 处 根据 vmlinux.lds , vmlinux 的地址被链接为 0xc0000000+0x100000 处 vmlinux.lds 如何正确运行呢? 此时仍然是实模式,还没有进入保护模式、分页、映 射好 没有长跳转,只使用采用相对地址的近距离跳转
40
Head.S Startup_32 初始化段寄存器 设置页目录和页表, 分页 建立进程 0 的内核堆栈 Setup_idt 拷贝系统参数 识别处理器 GDT 、 IDT Start_kernel 页目录: swapper_pg_dir 页表: pg0 和 pg1 ???如何从 0 ~ 8M 的空 间中转入 3G 以上的地址 空间中运行的???
41
控制寄存器( Control Registers ) CR0 CR1 CR2 CR3 与内存相关
42
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
43
CR1 、 CR2 、 CR3 CR1 :保留 CR2 :在缺页异常的时候,记录缺页地址 CR3 :记录页目录所在的物理地址和两个标记 (PCD & PWT)
44
请注意 setup.S 和 head.S 中的 gdt/ldt setup.S head.S 后者比前者多了一些 用户代码段和数据段 其他
45
作业 2 i386 实模式下是如何解决 20 位地址空间和 16 位段 寄存器之间的不匹配问题的? i386 保护模式下的段寄存器的内容与实模式下段 寄存器的内容一样么?如何解释? 简单叙述一下 Linux 的 bzImage 的软盘启动过程
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.