Linux引导过程概述

    Linux 的启动流程目前比较流行的方式主要是以下步骤:
    1、引导器(例如 GRUB)启动;
    2、内核启动;
    3、系统进程启动与配置。

    本文以 GRUB 为研究对象,对 GRUB 启动与内核启动两个部分进行描述,关于系统进程的进一步启动与配置将用另一篇文章来说明。

常见的目录结构 (以 CentOS 5.3 为例):

                      /boot
                       
|-- System.map-2.6.18-128.el5
                        |-- System.map-2.6.18-128.el5xen
                        |-- config-2.6.18-128.el5
                        |-- config-2.6.18-128.el5xen
                        |-- initrd-2.6.18-128.el5.img
                        |-- initrd-2.6.18-128.el5xen.img
                        |-- lost+found
                        |-- memtest86+-1.65
                        |-- message
                        |-- symvers-2.6.18-128.el5.gz
                        |-- symvers-2.6.18-128.el5xen.gz
                        |-- vmlinuz-2.6.18-128.el5
                        |-- vmlinuz-2.6.18-128.el5xen
                        |-- xen-syms-2.6.18-128.el5
                        |-- xen.gz-2.6.18-128.el5
                        `-- grub
                            |-- device.map
                            |-- e2fs_stage1_5
                            |-- fat_stage1_5
                            |-- ffs_stage1_5
                            |-- grub.conf
                            |-- iso9660_stage1_5
                            |-- jfs_stage1_5
                            |-- menu.lst -> ./grub.conf
                            |- - minix_stage1_5
                            |-- reiserfs_stage1_5
                            |-- splash.xpm.gz
                            |-- stage1
                            |-- stage2
                            |-- ufs2_stage1_5
                            |-- vstafs_stage1_5
                            `-- xfs_stage1_5

               图一: CentOS 5.3 的 /boot 目录

         目录分作两大部分,一个是 /boot 目录下除 grub 目录以外的所有文件,这些是 Linux 的内核以及内核启动相关的一些文件;另一个就是 grub 下的所有文件, GRUB 引导器启动所需要的所有文件都在 grub 目录下。

 



核心文件组成:

                      /boot
                       
|-- System.map-2.6.18-128.el5
                        |-- initrd-2.6.18-128.el5.img
                        |-- vmlinuz-2.6.18-128.el5
                        `-- grub
                            |-- grub.conf
                            |-- menu.lst -> ./grub.conf
                            |-- stage1
                            |-- stage2

               图二: 核心文件说明

        图二是一个简化了的目录结构,在大多数Linux实现中,这些是 Linux 启动最核心的几个文件,下面我们对这个结构中的文件加以说明。

 



内核文件说明:

        Linux 内核启动相关文件:

        vmlinuz  ---  Linux 内核
                这个就是 Linux 可引导的、压缩的内核文件。
                此文件通常后面带有内核版本号,但不是必需的,但有利于系统中存在多个不同的内核时加以区分。
                vmlinuz 通常在 2.4 版内核时有两种方法建立,一个是通过编译时使用 make zimage 命令,这个方法是老的 2.4 版内核所支持的方式,用于生成较小的内核(512K 以下), 同时,在 2.4 版内核编译时使用 make bzimage 则可以生成一个大内核,其中 bz 的意思是 big zimage。 二者的主要区别在于小内核(zimage 形势)可以很小(4K),放在磁盘的前八个引导扇区,在装载时,先装载到
0x1000:0000 高端内存,然后再移动到 0x0200:0000 位置的低端内存,然后启动CPU,所以可以不需要单独的引导器; 而 bzimage 形式较大,在 512K 以上 ,只能加载到 0x1000:0000 高端内存,然后启动CPU,需要有独立的引导器进行引导。
                vmlinuz 在 2.6 版内核中并不直接支持 zimage 小内核方式,2.6版内核的编译过程不需要 make zimage 或 make bzimage 这一步 。
      
                vmlinuz 虽然采用了 gzip 进行压缩 , 但由于其头部中添加了精简过的代码,所以不能直接用 gunzip 直接解压,我们通过观察一般的 gzip缩文件,发现有一个特征码 "1f8b" 。于是分析 vmlinuz 这个文件:


                # xxd vmlinuz-2.6.18-128.el5 |egrep "/b1f8b"  |head -n5
                0002080: 1b00 1f8b 0800 e642 7749 0203 ec3b 6d78  .......BwI...;mx
                00315f0: ebe4 177f 065d 6e19 434a 4a5a 1f8b 111e  .....]n.CJJZ....
                0058390: d1ad 1e11 0683 9f1f a857 1f8b a542 cb27  .........W...B.'
                0073cb0: 9b51 e43c 482b 3685 1f8b 05f5 32fd b758  .Q.
                0086a50: ed06 0bb5 1f8b 6d67 930c d7d0 2c6c 6c18  ......mg....,ll.

                发现该特征码在 0x2082 处,由以下命令可以摘除这个部分:

                # dd if=
vmlinuz-2.6.18-128.el5  of=vmlinuztest.gz  bs=1  skip=$((0x2082))

                然后解压 vmlinuz
test.gz 即可得到二进制的内核。      

                值得一提的是,2.4 以后版本的内核,不再提供无需引导器引导的机制 。                       

        initrd  ---  initialized  ram disk  初始化 RAM 磁盘
                启动器(boot loader 即本文的 GRUB)会在内核启动前把 initrd 装入内存,该文件的作用是生成一个 RAM 磁盘,并在其上形成根文件系统,内核启动时会在访问真实的磁盘根文件系统前访问这个 RAM 磁盘中的根文件系统。2.6 版内核中,当内核执行完 initrd 中的内容后,对于 cpio 类型的 initrd ,会由 initrd 负责执行switchroot 来切换根文析系统到真实的文件系统中去,并开始真正的 init 进程;对于 image-initrd 这个类型来说,内核执行完 initrd 这个阶段以后,会返回到内核,继续内核初始化,然后由内核去调用真实文件系统中的 init 。本文的主要内容是介绍 Linux 2.6 版引导的过程,对于initrd 的更多细节不再赘述,有兴趣的读者,可以查阅相关的链接 。 关于 initrd 的动手实验,则可以在本站中找到

                此文件通常后面带有内核版本号,但不是必需的,但有利于系统中存在多个不同的内核时加以区分。

                关于 initrd 的另一个重点,是为什么要使用它,initrd 最重要的作用在于使引导过程更加灵活。为了在各种硬件平台上启动,将所有的硬件驱动都放到内核中显然不现实,initrd 的作用之一就是加载硬件驱动模块,从而可以在内核中只包含最基本的硬件驱动即可,将加载不同硬件驱动的任务交给 initrd ;关于 initrd 的另一个作用是支持 usb 启动,由于 usb 从驱动加载到真正可用的过程较慢,可能需要几秒钟的时间比较慢,在内核访问usb时,USB 设备可能还没初始化完成,将该过程放入到 initrd 中可以进行延时,完成正确加载和引导。

                在某些情况下,我们可以使用 noinitrd 参数,使启动过程不使用 initrd 文件是可能的。        

 

        System.map  ---  内核符号映射表
               
在弄清楚 System.map 的作用以前,首先要先了解两个名词,其中一个叫做 symbol(符号),另一个叫做 Oops 。

         Symbol : 符号,学过程序设计的话应该知道,一个符号是一个程序的创建块,它是一个变量名或一个函数名。 这里为什么要提到这个名词呢? 因为 Linux 内核并不使用符号来调用函数,而是直接使用函数的地址(指针), 这似乎造成了一个矛盾,因为编程的人并不喜欢使用地址的方式,于是符号表产生了,它允许在编程的过程中,使用符号,但是在编译时使用地址,”符号映射表 “由此产生了,它就是 System.map .

         用 more 命令查看 System.map 文件可以看到类似下面的段:

         64位的系统:

         ffffffff81000000 A _text
         ffffffff81000000 T startup_64
         ffffffff810000b7 t ident_complete
         ffffffff81000100 T secondary_startup_64

         32位的系统:

         c0100000 A _text
         c0100000 T startup_32
         c01000c6 t checkCPUtype
         c0100147 t is486

                Oops : 当内核引用了一个无效指针时,通常被称为 Oops ,说明内核存在一个Bug。 内核在出现此错误时,会由 klogd 这个服务将此错误记载到日志中,如果该日志指出一个地址错误,显然还需要我们花些时间来找该地址对应的符号,klogd 通过检视 System.map 直接将符号取出,并记载该符号引发了一个 Oops 。

                通过以上的描述,我们得到一个结论:System.map 是一个静态的内核符号映射表!

                既然说到静态,那么就说明如果是在运行期间动态加载的某些模块,可能不在其中,如何得到它们呢? 系统中的 proc 文件系统中存在一个动态的映射表, 在 2.6 Kernel 中通常是 /proc/kallsyms 。

                另外,类似 lsof 和 ps 等命令,是需要这个映射表的存在的,但既使没有这个文件,系统的启动依然可以进行。

 

 



GRUB 文件说明:


        stage1  ---  磁盘引导第一阶段
                当 BIOS 加电自检完成以后,假设系统是从硬盘启动,则 BIOS 的最后一件事情就是读取该硬盘的 0 道 0 面 1 扇区,即我们常用说的 MBR ,它只有 512 个字节大小,它与 stage1 具有什么样的关系呢? 我们先来看一下关于 MBR 的构成:


图三:MBR 的组成(摘自 IBM 官方网站)


                MBR 共由三个部分组成:1、Bootloader 就是引导代码,其作用主要是加载第二阶段启动(即stage2),2、Partition table 分区表, 3、Magic Number 魔数,就是那个 55AA 标志,用以检验该 MBR 的有效性。

                我们可以用如下命令导出该扇区到文件(假设该硬盘为 hda):

                      dd  if=/dev/hda  of=mbr.bin  bs=512  count=1

                然后我们用

                     xxd  mbr.bin

                     xxd  /boot/grub/stage1

               仔细对比发现,该扇区的 Bootloader 部分与 MagicNumber部分与 stage1 文件完全一样,原来,在使用 grub 的安装命令进行引导器安装时,grub 会用 stage1 文件的前 446 字节覆盖 MBR的前446 字节。在这里我们得到另一个启示,那就是不能简单的认为 MBR 等价于 stage1 ,为了保护 MBR ,我们还是应该对 MBR 做备份。

 

        stage1_5  ---  关于文件系统格式的“魔术师”
                应该注意到,所有带有 stage1_5 字样的文件,全部都和文件系统名字有关:

                            |-- e2fs_stage1_5
                            |-- fat_stage1_5
                            |-- ffs_stage1_5
                            |-- iso9660_stage1_5
                            |-- jfs_stage1_5
                             |- - minix_stage1_5
                            |-- reiserfs_stage1_5
                             |-- ufs2_stage1_5
                            |-- vstafs_stage1_5
                            `-- xfs_stage1_5

                顾名思义,其实 stage1_5d 确实是在 stage1 和 stage2 之间运行的,它包括了一些常见的文件系统的识别能力,这些文件的存在,意味着 grub 可以从多种文件系统中读取并加载 Linux 内核。

                这个特性使得 grub 更加灵活的处理不同的文件系统格式。

                虽然有 e2fs_stage1_5 这个文件的存在,但经过实验,我们发现在默认情况下编译的内核如果装载在 ext3 文件系统上,是不需要 stage1_5这个过程的。

 

       stage2  ---  真正的 grub 就在这里
                注意到 stage2 的文件尺寸,超过了 512 字节的大小,所以 grub 本身并不能放到 mbr 中去,mbr  那446字节的作用,主要就是找到这个 stage2,它读取 menu.list 文件显示系统引导菜单,识别不同的引导指令,并完成 vmlinuz 和 initrd 的加载,其实,这个就是真正的 grub 了!

                menu.list 文件就是 grub 的引导菜单, grub 会执行菜单里的命令,完成引导,因为红帽这个系列的系统进行了一些特别的设置,所以存在一个叫做 grub.conf 的软链接,指向 menu.list 。

 

 



结论:

                启动中最重要的东西:mbr/stage1 、grub/stage2 、kernel/vmlinuz ,三者是最最核心的。stage1_5 的作用是使 grub 有处理更多文件系统的灵活能力,而 initrd 使内核启动更加灵活,在不同的平台上,对不同的硬件,使用不同的驱动,从而减小静态内核的尺寸。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值