RSS
热门关键字:
当前位置 :| 主页>新手入门>

Linux系统基础知识(十九)Linux启动过程综述

来源:水木 作者:杨沙洲 时间:2008-09-27 Tag:基础知识   linux启动过程   点击:

Linux启动过程综述

  内容:
  一. Bootloader
  二.Kernel引导入口
  三.核心数据结构初始化--内核引导第一部分
  四.外设初始化--内核引导第二部分
  五.init进程和inittab引导指令
  六.rc启动脚本
  七.getty和login
  八.bash
  附:XDM方式登录 作者:杨沙洲
  本文以Redhat 6.0 Linux 2.2.19 for Alpha/AXP为平台,描述了从开机到登录的
Linux 启动全过程。该文对i386平台同样适用。
  一. Bootloader
在Alpha/AXP平台上引导Linux通常有两种方法,一种是由MILO及其他类似的引导程序引 导,另一种是由Firmware直接引导。MILO功能与i386平台的LILO相近,但内置有基本的磁盘
驱动程序(如IDE、SCSI等),以及常见的文件系统驱动程序(如ext2,iso9660等), firmware有ARC、SRM两种形式,ARC具有类BIOS界面,甚至还有多重引导的设置;而SRM则具
有功能强大的命令行界面,用户可以在控制台上使用boot等命令引导系统。ARC有分区 (Partition)的概念,因此可以访问到分区的首扇区;而SRM只能将控制转给磁盘的首扇区。
两种firmware都可以通过引导MILO来引导Linux,也可以直接引导Linux的引导代码。
“arch/alpha/boot”下就是制作Linux Bootloader的文件。“head.S”文件提供了对
OSF PAL/1的调用入口,它将被编译后置于引导扇区(ARC的分区首扇区或SRM的磁盘0扇区), 得到控制后初始化一些数据结构,再将控制转给“main.c”中的start_kernel(),
start_kernel()向控制台输出一些提示,调用pal_init()初始化PAL代码,调用openboot() 打开引导设备(通过读取Firmware环境),调用load()将核心代码加载到START_ADDR(见
“include/asm-alpha/system.h”),再将Firmware中的核心引导参数加载到ZERO_PAGE(0) 中,最后调用runkernel()将控制转给0x100000的kernel,bootloader部分结束。

“arch/alpha/boot/bootp.c”以“main.c”为基础,可代替“main.c”与“head.S”
生成用于BOOTP协议网络引导的Bootloader。
Bootloader中使用的所有“srm_”函数在“arch/alpha/lib/”中定义。


以上这种Boot方式是一种最简单的方式,即不需其他工具就能引导Kernel,前提是按照 Makefile的指导,生成bootimage文件,内含以上提到的bootloader以及vmlinux,然后将
bootimage写入自磁盘引导扇区始的位置中。


当采用MILO这样的引导程序来引导Linux时,不需要上面所说的Bootloader,而只需要 vmlinux或vmlinux.gz,引导程序会主动解压加载内核到0x1000(小内核)或0x100000(大
内核),并直接进入内核引导部分,即本文的第二节。
对于I386平台
i386系统中一般都有BIOS做最初的引导工作,那就是将四个主分区表中的第一个可引导 分区的第一个扇区加载到实模式地址0x7c00上,然后将控制转交给它。



在“arch/i386/boot”目录下,bootsect.S是生成引导扇区的汇编源码,它首先将自己 拷贝到0x90000上,然后将紧接其后的setup部分(第二扇区)拷贝到0x90200,将真正的内核
代码拷贝到0x100000。以上这些拷贝动作都是以bootsect.S、setup.S以及vmlinux在磁盘上 连续存放为前提的,也就是说,我们的bzImage文件或者zImage文件是按照bootsect,setup,
vmlinux这样的顺序组织,并存放于始于引导分区的首扇区的连续磁盘扇区之中。


bootsect.S完成加载动作后,就直接跳转到0x90200,这里正是setup.S的程序入口。 setup.S的主要功能就是将系统参数(包括内存、磁盘等,由BIOS返回)拷贝到
0x90000-0x901FF内存中,这个地方正是bootsect.S存放的地方,这时它将被系统参数覆盖。 以后这些参数将由保护模式下的代码来读取。



除此之外,setup.S还将video.S中的代码包含进来,检测和设置显示器和显示模式。最 后,setup.S将系统转换到保护模式,并跳转到0x100000(对于bzImage格式的大内核是
0x100000,对于zImage格式的是0x1000)的内核引导代码,Bootloader过程结束。
对于2.4.x版内核
没有什么变化。
  二.Kernel引导入口


在arch/alpha/vmlinux.lds的链接脚本控制下,链接程序将vmlinux的入口置于 \"arch/alpha/kernel/head.S\"中的__start上,因此当Bootloader跳转到0x100000时,
__start处的代码开始执行。__start的代码很简单,只需要设置一下全局变量,然后就跳转 到start_kernel去了。start_kernel()是\"init/main.c\"中的asmlinkage函数,至此,启
动过程转入体系结构无关的通用C代码中。
对于I386平台
在i386体系结构中,因为i386本身的问题,在\"arch/alpha/kernel/head.S\"中需要更多的设置,但最终也是通过call
SYMBOL_NAME(start_kernel)转到start_kernel()这个体系结构无关的函数中去执行了。


所不同的是,在i386系统中,当内核以bzImage的形式压缩,即大内核方式 (__BIG_KERNEL__)压缩时就需要预先处理bootsect.S和setup.S,按照大核模式使用$(CPP)
处理生成bbootsect.S和bsetup.S,然后再编译生成相应的.o文件,并使用 \"arch/i386/boot/compressed/build.c\"生成的build工具,将实际的内核(未压缩的,含
kernel中的head.S代码)与\"arch/i386/boot/compressed\"下的head.S和misc.c合成到一起,其中的head.S代替了\"arch/i386/kernel/head.S\"的位置,由Bootloader引导执行
(startup_32入口),然后它调用misc.c中定义的decompress_kernel()函数,使用 \"lib/inflate.c\"中定义的gunzip()将内核解压到0x100000,再转到其上执行
\"arch/i386/kernel/head.S\"中的startup_32代码。
对于2.4.x版内核
没有变化。
  三.核心数据结构初始化--内核引导第一部分

start_kernel()中调用了一系列初始化函数,以完成kernel本身的设置。 这些动作有的是公共的,有的则是需要配置的才会执行的。

最新评论共有 1 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册

_×
嵌入式linux中文站
QQ群讨论 微博订阅

微信扫一扫关注我们
随时获取最新开源资讯