2010 第2章 Linux中的启动代码分析
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
主要相关的代码是在arch/i386/boot中: bootsect.S:这是linux引导扇区的源代码 setup.S:这是辅助程序的一部分,初始化工作 video.S:这是辅助程序的另外一部分,用于引
导过程中的屏幕显示 另外,子目录compressed中还有两个源代码文件 head.S,misc.c。用于内核映象的解压缩。也 属于辅助程序一部分。
# #
系统引导-bootsect.S中部分代码的解释
这段代码将启动扇区代码由0x7C00移至 0x90000处。 Linux将地址为0x90000的代码段称为 INITSEG。然后跳转到go标志,准备一块堆 栈,栈底位于$INITSEG:0x4000-12
i386内核从实模式开始启动运行
首先看一下什么是实模式 实模式是为了兼容早期的CPU而设臵的 i386系统总是开始于实模式 实模式下
i386内核的启动
启动方式
BIOS 0x7c00: 0x90200: bootsect setup
LILO,Grub等boot loader
加载i386内核的内存布局图
zImage/Image的内核加载器所使用的经 典的内存布局(1M=0x100000)
软盘启动,bootsect.S
setup
32位启动代码 在init目录下
这是体系结构无关部分,i386体系结构相关部分的启动, 其目的就是进入main.c中的start_kernel处执行
Linux系统引导:
过程
定义:指计算机启动时,由系统BIOS以及操作系 统引导程序,将操作系统内核可执行代码逐级装 入内存并开始执行,直到系统控制台显示 “login:”登录提示符位为止的系统引导阶段。几 个阶段:
对于小内核:0x10000(即64K处),称为低装载 对于大内核:0x100000(即1M处),称为高装载
跳转到setup处运行,转入实模式下的系统初始化
系统引导
bootset.S将自身转移到0x90000处,然后跳转到 那里继续执行,并通过BIOS提供的“int 0x13”调 用从磁盘上读入setup.S和内核的映象,然后跳转 到setup.S的代码中,为执行内核映象做准备. bootsect.S中部分代码的解释如下所示:
由BIOS加载操作系统引导程序 由操作系统引导程序加载操作系统内核 内核代码解压缩 内核初始化 生成init进程 系统初始化,shell命令文本的执行 生成各终端进程。
下面根据在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
根据配臵,操作系统可以在软盘/硬盘/CD_ROM上
把对应设备的第一个扇区的内容(boot loader或 部分)拷贝到RAM(0000:0x7c00)处 跳转到0000:0x7c00处执行
BIOS启动
加电开机后,intel CPU在实模式下工作, 只能使用低端的640KB(即0XA0000以下)的 内存空间 由ROM BIOS或者LILO将启动盘的第一扇区 (引导扇区)的内容装入起始地址为0x7c00 的内存空间,然后跳转到0x7c00开始执行引 导扇区的代码 该引导扇区内的代码就是bootset.S汇编后 生成的二进制代码
Linux的Boot Loader
典型的有:LILO和Grub LILO(LInux LOader)
可以被安装在OS分区的第一个扇区(启动扇区) 也可以代替MBR中的引导程序
事实上,LILO的代码尺寸大于一个扇区,因此被分成两个 部分
MBR或启动扇区部分 剩余部分
第一部分也被BIOS装载到RAM中0x7c00的位臵 第一部分在运行时将自己完整的装载到RAM中
第2章 基于i386体系结构的 Linux启动代码分析 系统初始化所包括的内容
基础知识 系统引导 通过LILO进行引导 实模式下的系统初始化 保护模式下的系统初始化 启动核心 Init进程
本章引言
引导涉及到系统各个部分的数据结构,因此,只 有随着课程的深入,才会彻底弄清楚引导程序中 的初始化工作 不同OS的引导程序可能会不同,但是仍有一些普 遍的原理可以遵循 启动核心部分侧重对原理的理解,增强大家的感 性认识
i386的启动代码文件
在arch/i386/boot目录下
I386的体系结构相关部分的启动代码 都采用汇编码写的
启动扇区中的启动代码, 其目标码必然是512字节 I386初始化
在arch/i386/boot/compressed目录下
内核解压缩
在arch/i386/kernel目录下的.S文件
POST自检
POST是系统测试程序,它对系统进行比较全面的测 试,主要包括: 对CPU、定时器、DMA控制器、中断控制器、内存 中的RAM和ROM、键盘、磁盘驱动器、异步通信接 口、打印机配臵台数等十几项内容进行测试。 这个测试过程叫做POST(上电自检)操作。
BIOS启动
加电,RESET引脚 初始化寄存器;CS:IP = 0xfffffff0, in ROM(CPU 要执行的第一条指令) 该地址中有一条JMP指令,跳转地址通常是BIOS的入 口地址(进行POST)。 ROMBIOS BIOS启动内容 POST(上电自检) 初始化硬件设备 搜索一个操作系统来启动
Linux的Boot Loader
通常LILO或GRUB会显示一个已安装操作系统的列 表 按照用户的选择(或者按照缺省项)装载目标操 作系统运行
可能装载操作系统指定的启动代码运行 可能直接装载操作系统内核来运行
LILO的OS启动过程
显示“Loading…” 操作系统前512字节(一个扇区大小,bootsect) 的内容被装载到RAM的0x90000 紧接着的内容(setup)被装在到0x90200 其他操作系统内核被装载到
地址总线:20位 内存范围:0-1MB 逻辑地址 = 段地址 + 段内偏移
段地址 = 段寄存器中的值*16 (或左移4位) 段寄存器: cs/ds/es/fs/gs 段寄存器长度:16bit 段长:16位偏移64KB
实模式下的系统初始化
setup.S连同内核映象由bootsect.S装入。 setup.S从BIOS获取计算机系统的参数,放到内存 参数区,仍在实模式下运行 CPU在setup.S的执行过程中转入32位保护模式的 段式寻址方式 辅助程序setup.S为内核映象的执行做好准备,然 后跳转到0x100000开始内核本身的执行,此后就 是内核的初始化过程
ljmp …… 0x90200 go:…… ljmp ……
0x90000
sys
0x10000
0x7E00
0x7C00 0x4000 0x4000-12
ljmp …… go:…… ljmp ……
cs:ip cs:ip cs:ip cs:ip 低 ss sp
硬盘启动,两阶段引导
装载LILO(LInuxLOader)
系统引导-bootsect.S中的部分代码
movw $BOOTSEG, %ax movw %ax, %ds # %ds = BOOTSEG,将ds段寄存器设为 0x7c00 movw $INITSEG, %ax movw %ax, %es # %ax = %es = INITSEG,将es段寄存器设 为0x9000 movw $256, %cx #移动计数值=256 subw %si, %si #源地址ds:si=0x07c0:0x0000 subw %di, %di #目标地es:di=0x9000:0x0000 cld #清方向标志位 rep #重复执行直到cx=0 movsw #移动1个字 ljmp $INITSEG, $go #间接跳转,INITSEG指出跳转到的段地址 … go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >= # length of bootsect + length of setup + room for stack; 12 is disk parm size. movw %ax, %ds
高 cs:ip cs:ip cs:ip cs:ip
0x7c000x90000 0x7c00, BIOS 0x90000, lilo 堆栈,0x3ff4(0x4000-12), 向下增长 磁盘参数表,12Bytes,0x3ff4~0x4000 显示“Loading” Setup.S0x90200 操作系统内核 小内核,0x10000(64KB处),低装载 大内核,0x100000(1MB处),高装载 setup
内核可执行代码在内存中的首地址是否可随意选 择?为什么?
实模式下的系统初始化-setup.S
版本检查和参数设臵 检查签名“55AA5A5A”,此签名位于setup.S代码段的末尾, 判断安装程序是否完全安装进来 判断内核(kernel)是否为BIG_KERNEL 设臵参数 为进入保护模式做准备,主要包括 关中断 检查自身(setup.S)是否在SETUPSEG处 臵idt(中断描述符表)为空,设臵gdt(全局描述符表) 真正进入保护模式
Linux的Boot Loader
通常LILO或GRUB会显示一个已安装操作系统的列 表 按照用户的选择(或者按照缺省项)装载目标操 作系统运行
可能装载操作系统指定的启动代码运行 可能直接装载操作系统内核来运行
Lilo将用户在启动时输入的命令和参数存储在 empty_zero_page(0x5000)的后半页,供 arch/i386/kernel/setup.c文件的setup_arch() 函数使用
arch/i386/kernel:下的head.S用于启动内
核.
考虑arch为i386
在arch/i386下存在如下目录
I386的启动源代码文件目录 I386的核心源代码文件目录 I386的库源代码文件目录 I386的数学仿真源代码文件目录 I386的内存管理源代码文件目录 I386的配置文件 I386的体系相关部分的Makefile I386的Linux内核的链接描述文件
Boot loader(引导装载程序)
BIOS调用Boot loader来把操作系统的内核映像装载到RAM 中 考虑一般PC机的启动
软盘启动:BIOS拷贝第一个扇区的内容(bootsect)到RAM (0x7c000)中 硬盘启动:
硬盘的第一个扇区:主引导记录MBR, Master Boot Record, MBR存储该硬盘的分区表+ 一小段引导程序 这个引导程序用来装载OS所在分区的第一个扇区(boot loader)的内容到RAM中 这个引导程序也可以被替换
系统启动:相关文件分布
Linux操作系统内核经过编译,汇编和连接后就形 成三个部分:引导扇区的映象bootsetc.S,辅助程 序setup.S和内核映象本身。 大小不超过508KB的内核引导映象称为小映象 zImage;否则称为大内核bzImage(z代表压缩;b 代表大内核)
系统启动:相关文件分布
第一个扇区 … Bootsect.S0x90000 Setup.S0x90200 系统
装载LINUX
0x10000 0x100000
跳转到setup
启动第一步:小结
总之,在跳转到setup.s的时候,内存里面的代 码布局为
0x90000:bootsect.S 0x90200:setup.S 低装载:0x10000:带解压的mlinux 高装载:0x100000:带解压的bvmlinux
导过程中的屏幕显示 另外,子目录compressed中还有两个源代码文件 head.S,misc.c。用于内核映象的解压缩。也 属于辅助程序一部分。
# #
系统引导-bootsect.S中部分代码的解释
这段代码将启动扇区代码由0x7C00移至 0x90000处。 Linux将地址为0x90000的代码段称为 INITSEG。然后跳转到go标志,准备一块堆 栈,栈底位于$INITSEG:0x4000-12
i386内核从实模式开始启动运行
首先看一下什么是实模式 实模式是为了兼容早期的CPU而设臵的 i386系统总是开始于实模式 实模式下
i386内核的启动
启动方式
BIOS 0x7c00: 0x90200: bootsect setup
LILO,Grub等boot loader
加载i386内核的内存布局图
zImage/Image的内核加载器所使用的经 典的内存布局(1M=0x100000)
软盘启动,bootsect.S
setup
32位启动代码 在init目录下
这是体系结构无关部分,i386体系结构相关部分的启动, 其目的就是进入main.c中的start_kernel处执行
Linux系统引导:
过程
定义:指计算机启动时,由系统BIOS以及操作系 统引导程序,将操作系统内核可执行代码逐级装 入内存并开始执行,直到系统控制台显示 “login:”登录提示符位为止的系统引导阶段。几 个阶段:
对于小内核:0x10000(即64K处),称为低装载 对于大内核:0x100000(即1M处),称为高装载
跳转到setup处运行,转入实模式下的系统初始化
系统引导
bootset.S将自身转移到0x90000处,然后跳转到 那里继续执行,并通过BIOS提供的“int 0x13”调 用从磁盘上读入setup.S和内核的映象,然后跳转 到setup.S的代码中,为执行内核映象做准备. bootsect.S中部分代码的解释如下所示:
由BIOS加载操作系统引导程序 由操作系统引导程序加载操作系统内核 内核代码解压缩 内核初始化 生成init进程 系统初始化,shell命令文本的执行 生成各终端进程。
下面根据在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
根据配臵,操作系统可以在软盘/硬盘/CD_ROM上
把对应设备的第一个扇区的内容(boot loader或 部分)拷贝到RAM(0000:0x7c00)处 跳转到0000:0x7c00处执行
BIOS启动
加电开机后,intel CPU在实模式下工作, 只能使用低端的640KB(即0XA0000以下)的 内存空间 由ROM BIOS或者LILO将启动盘的第一扇区 (引导扇区)的内容装入起始地址为0x7c00 的内存空间,然后跳转到0x7c00开始执行引 导扇区的代码 该引导扇区内的代码就是bootset.S汇编后 生成的二进制代码
Linux的Boot Loader
典型的有:LILO和Grub LILO(LInux LOader)
可以被安装在OS分区的第一个扇区(启动扇区) 也可以代替MBR中的引导程序
事实上,LILO的代码尺寸大于一个扇区,因此被分成两个 部分
MBR或启动扇区部分 剩余部分
第一部分也被BIOS装载到RAM中0x7c00的位臵 第一部分在运行时将自己完整的装载到RAM中
第2章 基于i386体系结构的 Linux启动代码分析 系统初始化所包括的内容
基础知识 系统引导 通过LILO进行引导 实模式下的系统初始化 保护模式下的系统初始化 启动核心 Init进程
本章引言
引导涉及到系统各个部分的数据结构,因此,只 有随着课程的深入,才会彻底弄清楚引导程序中 的初始化工作 不同OS的引导程序可能会不同,但是仍有一些普 遍的原理可以遵循 启动核心部分侧重对原理的理解,增强大家的感 性认识
i386的启动代码文件
在arch/i386/boot目录下
I386的体系结构相关部分的启动代码 都采用汇编码写的
启动扇区中的启动代码, 其目标码必然是512字节 I386初始化
在arch/i386/boot/compressed目录下
内核解压缩
在arch/i386/kernel目录下的.S文件
POST自检
POST是系统测试程序,它对系统进行比较全面的测 试,主要包括: 对CPU、定时器、DMA控制器、中断控制器、内存 中的RAM和ROM、键盘、磁盘驱动器、异步通信接 口、打印机配臵台数等十几项内容进行测试。 这个测试过程叫做POST(上电自检)操作。
BIOS启动
加电,RESET引脚 初始化寄存器;CS:IP = 0xfffffff0, in ROM(CPU 要执行的第一条指令) 该地址中有一条JMP指令,跳转地址通常是BIOS的入 口地址(进行POST)。 ROMBIOS BIOS启动内容 POST(上电自检) 初始化硬件设备 搜索一个操作系统来启动
Linux的Boot Loader
通常LILO或GRUB会显示一个已安装操作系统的列 表 按照用户的选择(或者按照缺省项)装载目标操 作系统运行
可能装载操作系统指定的启动代码运行 可能直接装载操作系统内核来运行
LILO的OS启动过程
显示“Loading…” 操作系统前512字节(一个扇区大小,bootsect) 的内容被装载到RAM的0x90000 紧接着的内容(setup)被装在到0x90200 其他操作系统内核被装载到
地址总线:20位 内存范围:0-1MB 逻辑地址 = 段地址 + 段内偏移
段地址 = 段寄存器中的值*16 (或左移4位) 段寄存器: cs/ds/es/fs/gs 段寄存器长度:16bit 段长:16位偏移64KB
实模式下的系统初始化
setup.S连同内核映象由bootsect.S装入。 setup.S从BIOS获取计算机系统的参数,放到内存 参数区,仍在实模式下运行 CPU在setup.S的执行过程中转入32位保护模式的 段式寻址方式 辅助程序setup.S为内核映象的执行做好准备,然 后跳转到0x100000开始内核本身的执行,此后就 是内核的初始化过程
ljmp …… 0x90200 go:…… ljmp ……
0x90000
sys
0x10000
0x7E00
0x7C00 0x4000 0x4000-12
ljmp …… go:…… ljmp ……
cs:ip cs:ip cs:ip cs:ip 低 ss sp
硬盘启动,两阶段引导
装载LILO(LInuxLOader)
系统引导-bootsect.S中的部分代码
movw $BOOTSEG, %ax movw %ax, %ds # %ds = BOOTSEG,将ds段寄存器设为 0x7c00 movw $INITSEG, %ax movw %ax, %es # %ax = %es = INITSEG,将es段寄存器设 为0x9000 movw $256, %cx #移动计数值=256 subw %si, %si #源地址ds:si=0x07c0:0x0000 subw %di, %di #目标地es:di=0x9000:0x0000 cld #清方向标志位 rep #重复执行直到cx=0 movsw #移动1个字 ljmp $INITSEG, $go #间接跳转,INITSEG指出跳转到的段地址 … go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >= # length of bootsect + length of setup + room for stack; 12 is disk parm size. movw %ax, %ds
高 cs:ip cs:ip cs:ip cs:ip
0x7c000x90000 0x7c00, BIOS 0x90000, lilo 堆栈,0x3ff4(0x4000-12), 向下增长 磁盘参数表,12Bytes,0x3ff4~0x4000 显示“Loading” Setup.S0x90200 操作系统内核 小内核,0x10000(64KB处),低装载 大内核,0x100000(1MB处),高装载 setup
内核可执行代码在内存中的首地址是否可随意选 择?为什么?
实模式下的系统初始化-setup.S
版本检查和参数设臵 检查签名“55AA5A5A”,此签名位于setup.S代码段的末尾, 判断安装程序是否完全安装进来 判断内核(kernel)是否为BIG_KERNEL 设臵参数 为进入保护模式做准备,主要包括 关中断 检查自身(setup.S)是否在SETUPSEG处 臵idt(中断描述符表)为空,设臵gdt(全局描述符表) 真正进入保护模式
Linux的Boot Loader
通常LILO或GRUB会显示一个已安装操作系统的列 表 按照用户的选择(或者按照缺省项)装载目标操 作系统运行
可能装载操作系统指定的启动代码运行 可能直接装载操作系统内核来运行
Lilo将用户在启动时输入的命令和参数存储在 empty_zero_page(0x5000)的后半页,供 arch/i386/kernel/setup.c文件的setup_arch() 函数使用
arch/i386/kernel:下的head.S用于启动内
核.
考虑arch为i386
在arch/i386下存在如下目录
I386的启动源代码文件目录 I386的核心源代码文件目录 I386的库源代码文件目录 I386的数学仿真源代码文件目录 I386的内存管理源代码文件目录 I386的配置文件 I386的体系相关部分的Makefile I386的Linux内核的链接描述文件
Boot loader(引导装载程序)
BIOS调用Boot loader来把操作系统的内核映像装载到RAM 中 考虑一般PC机的启动
软盘启动:BIOS拷贝第一个扇区的内容(bootsect)到RAM (0x7c000)中 硬盘启动:
硬盘的第一个扇区:主引导记录MBR, Master Boot Record, MBR存储该硬盘的分区表+ 一小段引导程序 这个引导程序用来装载OS所在分区的第一个扇区(boot loader)的内容到RAM中 这个引导程序也可以被替换
系统启动:相关文件分布
Linux操作系统内核经过编译,汇编和连接后就形 成三个部分:引导扇区的映象bootsetc.S,辅助程 序setup.S和内核映象本身。 大小不超过508KB的内核引导映象称为小映象 zImage;否则称为大内核bzImage(z代表压缩;b 代表大内核)
系统启动:相关文件分布
第一个扇区 … Bootsect.S0x90000 Setup.S0x90200 系统
装载LINUX
0x10000 0x100000
跳转到setup
启动第一步:小结
总之,在跳转到setup.s的时候,内存里面的代 码布局为
0x90000:bootsect.S 0x90200:setup.S 低装载:0x10000:带解压的mlinux 高装载:0x100000:带解压的bvmlinux