基于x86体系结构分析linux-2.6.26的启动过程

来源:互联网 发布:京东双十一实时数据 编辑:程序博客网 时间:2024/05/20 09:10

要求1:分析流程按照开机-->BIOS-->grub-->Linux的顺序进行,到start_kernel结束

1.首先开机,启动电源,CPU加电后,将会初始化程序指针到某个约定好的地址上去指令运行,这个地址处,往往安排启动相关的代码,如BIOS。然后进入BIOS加载过程。BIOS要完成的工作有:

1)POST(上电自检)

2)初始化硬件设备

3)搜索一个操作系统来启动。根据配置,操作系统可以在软盘/硬盘/CD_ROM上

4)把对应设备的第一个扇区的内容(bootloader或部分)拷贝到RAM(0x7c00)处。

5)跳转到0x7c00处执行。

 

2. BIOS调用bootloader把操作系统的内核镜像装载到RAM中。linux2.6.26不支持软盘启动,支持硬盘启动。Grub引导装入程序会被分成两部分,第一部分用来代替MBR中的引导程序或者安装在OS分区的启动扇区,这一部分会被BIOS装载到RAM的0x7c00处。而第二部分在运行时将自己完整的装载到RAM中。第二部分还会依次从磁盘读取可用操作系统的映射表,并提供一个提示符供用户选择。启动过程如下:

1)显示“Load……”信息

2)header内容被装载到RAM的0x90000处

3)操作系统的其他部分被装载到:

    对于小内核:0x10000出,称为低装载

    对于大内核:0x100000出,称为高装载

4)跳转到0x90200处运行

 

3.跳转到arc/x86/boot/header.S文件的_start处开始执行。Header.S内容被装载到RAM的0x9000处,而_start在0x90200处。而_start的主要作用是:

1)跳转到start_of_setup

2)检查setup的signature

3)清除BSS段

4)跳转到main执行

其中main用来初始化硬件设备并为内核程序的执行建立环境。主要工作有,内存检测、键盘、视频,go_to_protected_mode,即进入保护模式。

 

4.系统从实模式进入保护模式,会调用一个arc/x86/boot/compressed/header_32.S中的startup_32函数,其主要功能是:

1)      初始化段寄存器和一个临时堆栈

2)      初始化BSS段

3)      解压缩decompressed_kernel

4)      跳转到0x100000处。

解压缩后,vmlinux的地址在0x100000处。解压的内核镜像以包含在arch/x86/kernel/header_32.S中的另一个startup_32函数开始。这个startup_32函数为第一个linux进程建立执行环境。其主要操作有:

1)  初始化段寄存器

2)  设置页目录,页表和分页

3)  建立进程0的内核堆栈

4)  Setup_idt

5)  拷贝系统参数

6)  识别处理器

7)  GDT、IDT

8)  跳转到i386_start_kernel

进入start_kernel,该函数完成linux内核的初始化工作。

 

要求2:首先给出Linux映像的make过程分析,说明grub将跳转到哪个Linux源文件中的哪处开始执行

1.先找到入口点

         在makefile中有all:vmlinux

2.继续找到vmlinux目标

         vmlinux: $(vmlinux-lds) $(vmlinux-init)$(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE

3.寻找变量的定义

vmlinux-init  := $(head-y) $(init-y)

         vmlinux-main := $(core-y) $(libs-y)$(drivers-y) $(net-y)

vmlinux-all   := $(vmlinux-init) $(vmlinux-main)

vmlinux-lds  :=arch/$(SRCARCH)/kernel/vmlinux.lds

生成的vmlinux.lds目标文件是链接生成vmlinux映像的链接描述文件ldscript

         4.继续寻找vmlinux-init包含的变量

                   init-y     := init/

init-y     := $(patsubst %/,%/built-in.o, $(init-y))

经过处理,最终init-y== init/built-in.o,init/built-in.o目标在init目录下生成,其中包含start_kernel函数,这个函数是从启动代码进入linux kernel的点。

head-y在/arch/x86/Makefile中,定义为:

head-y  :=arch/x86/kernel/head_$(BITS).o

head-y  +=arch/x86/kernel/head$(BITS).o # head32.o

head-y  +=arch/x86/kernel/init_task.o

         综上所述,vmlinux的生成过程即为

all --> vmlinux --> $(vmlinux-lds) $(vmlinux-init) -->$(head-y) $(init-y) --

-->built-in.o head32.o head_32.o init_task.o --> *.c *.S

 

Grub将跳转到Linux的arc/x86/boot/header.S文件的_start处开始执行。

 

要求3:从make过程,给出Linux中的启动相关的几个关键源文件的执行顺序

1.      arc/x86/boot/header.S

2.      arc/x86/boot/compressed/header_32.S

3.      arch/x86/kernel/header_32.S

4.      init/main.c