Presentation is loading. Please wait.

Presentation is loading. Please wait.

Linux 操作系统分析 中国科学技术大学计算机系 陈香兰( 0512 - 87161312 ) 助教:裴建国、冯晓静 Autumn 2008.

Similar presentations


Presentation on theme: "Linux 操作系统分析 中国科学技术大学计算机系 陈香兰( 0512 - 87161312 ) 助教:裴建国、冯晓静 Autumn 2008."— Presentation transcript:

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 的软盘启动过程


Download ppt "Linux 操作系统分析 中国科学技术大学计算机系 陈香兰( 0512 - 87161312 ) 助教:裴建国、冯晓静 Autumn 2008."

Similar presentations


Ads by Google