当前位置:IT快活林→网上冲浪局域网技术

深入理解linux启动过程

作者:本站整理   发布时间:2008-8-31 18:08:01


linux操作操作系统的启动操作系统过程是由很多很多步骤组成的,但是,不管您是启动操作系统一个标准的x86电脑的桌面电脑,还是一个嵌入式PowerPC的目标板,大多数的流程是惊人得相似的.这篇文章,探索了linux从最初的启动操作系统准备到用户空间中某个程序(Procedures)(Procedures)被开启之间的启动操作系统过程,跟随这一个流程,您还能学到其他许多与启动操作系统有关的知识,比如说是,boot loaders,内核解压缩,初始化计算机内存盘,以及其他一些linux启动操作系统的部分. 在很早的时候,启动操作系统一个电脑意味着去喂那些包含启动操作系统程序(Procedures)(Procedures)的纸带,或者是通过手工使用前面板那密密麻麻的地址/数据(Data)/控制开关来加载启动操作系统程序(Procedures)(Procedures),但是,简化这一个流程并非必须的. 让我们最开始从一个较高的高度上来对linux的启动操作系统做一个全面的分析,然后,我们会回顾一下,在每一个独立的过程当中,发生了什么事情.在这途中的参考源代码将帮助您可以在内核树中不至于迷失方向,并能继续深入挖掘下去. 一, 概述 对启动操作系统过程的整体回顾: 当操作操作系统一开始被启动操作系统,或者是重新启动操作系统时,处理器将在众所周知的位置执行代码.在个人电脑上,这一个位置处于基本输入输出操作操作系统中,也就是我们所说的BIOS,他是被存储在主板上的闪存中的.在嵌入式操作操作系统中,中央处理器(CPU)则将复位区域激活,来开始执行flash或者是ROM中的已知的程序(Procedures)(Procedures).在其他情况中,最基本的过程是一样的.由于个人电脑提供了众多灵活的可选设备,BIOS必须确定,由哪一个设备来执行启动操作系统过程.在接下来的文章中我们将涉及这方面的更多的内容. 当找到启动操作系统设备时,第一阶段所用的boot loader被装载到RAM中并被执行.这里面的boot loader在大小上小于一个扇区的大小,也就是512字节,而不能是他的任务,就是加载第二阶段的boot loader. 当负责第二阶段的boot loader位于计算机内存中并被执行时,通常会显示一个一闪而不能是过的屏幕,然后linux以及可选的初始化计算机内存盘(一种临时的根文件操作操作系统,如果想得到具体的介绍,请访问http://likunarmstrong.bokee.com/550226VI.html)会被装载到存储器中.当操作操作系统镜像被加载时,第二阶段的boot loader将把控制权转交给内核镜像,与此同时,内核开始自解压并初始化.在这一个阶段,第二阶段的boot loader会认真仔细的检查操作操作系统的硬件,枚举那些附加的硬件设备,挂载根设备,之后加载需要的内核模块.完成之后,第一个用户空间程序(Procedures)(Procedures)(init)开始执行,更高层次的操作操作系统初始化开始. 这就是从表面上看,linux的启动操作系统过程.好了,现在,让我们更进一步,更深入地探索linux启动操作系统过程当中的一些细节. II. 操作操作系统的启动操作系统 操作操作系统启动操作系统的阶段,依赖于linux在哪个硬件设备上启动操作系统.在嵌入式操作操作系统中,当操作操作系统被打开或者是重新启动操作系统的时候,就要使用启动操作系统加载的环境.这方面的例子包括U-BOOT,RedBoot,和Lucent推出的MicroMonitor.嵌入式平台通常是绑定了启动操作系统监视器的.这些程序(Procedures)(Procedures)位于目标硬件上flash存储器的特定位置,提供了将linux内核镜像下载到flash存储器的方法,并在接下来的过程当中执行他.除了拥有存储和启动操作系统linux镜像的功能外,这些启动操作系统监视器还能进行一定程度上的操作操作系统检测和硬件初始化.在一个嵌入式的目标板中,这些启动操作系统监视器通常覆盖了第一阶段与第二阶段boot loader的功能.
小知识:如何查看您的MBR内容.如果您希望查看您MBR的具体内容,请用以下系统命令:复制内容到剪贴板代码:# dd if=/dev/hda of=mbr.bin bs=512 count=1
# od -xa mbr.bin 需要以root身份运行的dd系统命令,读取您的第一个集成电子驱动器或者是IDE驱动器的前512字节,并将他们写入mbr.bim文件.od系统命令则是以十六进制和ASCII码形式打印出这一个二进制文件
在个人电脑中,linux的启动操作系统是从0xFFFF0地址开始的.BIOS的第一步动作就是进行上电自检(POST).POST的工作(Work)是认真仔细的检查硬件设备.BIOS的第二步动作就是枚举本地设备并初始化. 由于BIOS功能使用上的不同,他由两个部分组成:POST码runtime服务.POST完成后,他将从存储器中被清除,但是BIOS runtime服务会被保留,用于目标操作操作操作系统. 为了启动操作系统操作操作操作系统,BIOS的runtime服务将搜索那些激活状态的或者是是可引导启动操作系统的设备,搜索的顺序则由CMOS设置决定(也就是我们平时所谓的在BIOS中设置的启动操作系统顺序).一个软驱,一台光驱,一个计算机硬盘(Hard)上的分区,网络上的设备还超级有可能一个usb 闪存盘都可以作为一个启动操作系统设备. 当然,linux通常是从计算机硬盘(Hard)启动操作系统的.计算机硬盘(Hard)上的MBR(主启动操作系统记录)包含有最基本的boot loader,他是一个512字节大小的扇区,位于磁盘的第一个扇区(0磁头0磁道1扇区).当MBR被装载到RAM中后,BIOS就会将控制权转交给MBR. III. 第一阶段boot loader 位于MBR中的主boot loader是一个512字节的镜像,当中不仅包含了程序(Procedures)(Procedures)代码,还包含了一个小的分区表,如图2所示.最初的446字节是主boot loader,他里面就包含有可执行代码以及错误消息文本.接下来的64字节是分区表,当中包含有四个分区的各自的记录(一个分区占16字节).MBR通过特殊数字0xAA55(译者注:在电子界中AA55确实是具有传奇色彩的数字,想知道为什么或者说怎么会么?将他展开成二进制形式,看看有什么规律(law))作为两个字节的结束标志.0x55AA同时也是MBR有效的校验确认. 主boot loader的工作(Work)是寻找并加载第二boot loader.他通过分析分区表,找出激活分区来完成这一个任务,当他找到一个激活分区时,他将继续扫描剩下的分区表中的分区,以便确认他们绝大部分的都是未激活的.确认完毕后,激活分区的启动操作系统记录从设备中被读到RAM,并被执行. IV. 第二阶段boot loader 当着次作用,或者是说是第二boot loader,可以更加形像得被称为内核加载程序(Procedures)(Procedures).这一个阶段的任务就是加载linux内核,以及可选的初始化计算机内存盘.
小知识:GRUB阶段的boot loaders
在/boot/grub目录中包含有stage1,stage2和stageI.5的boot loaders,同时还有不少可选的loaders(比如说是,CD-ROM使用的就是iso9660_stage_1_5)
把第一阶段和第二阶段的boot loaders联合起来,就是在x86个人电脑中,我们所说的linux loader(LILO)或者是GRand Unified Bootloader(GRUB).由于GRUB修正了一些LILO中存在的缺陷,所以我们可以得出结论下面就让我们来看看GRUB(如果您希望得到更多的关于GRUB,LILO和与之相关话题的讨论资源,请见文后的参考资料) 对于GRUB来说,一个比较好的方面就是他包含了linux文件操作操作系统的知识.与LILO使用裸扇区不相同的是,GRUB能够从ext2或者是ext3文件操作操作系统中加载linux内核.他是通过将本来两阶段的boot loader转换成三个阶段的boot loader.在第一阶段(MBR)中会启动操作系统stageI.5的boot loader来理解linux内核镜像中的特殊的文件操作操作系统格式,比如说是,reiserfs_stage1-5(用于从reiserf日志文件操作操作系统中进行加载)或者是e2fs+stage1_5(用于从wxt2或者是ext3文件操作操作系统进行加载).当stageI.5的boot loader被加载并运行时,stage2 的boot loader才能被加载. 当stage2被加载时,GRUB能根据请求的情况显示一个可选内核的清单(在 /etc/grub.conf 中进行定义,同时还有几个软符号链接 /etc/grub/menu.lst 和 /etc/grub.conf).您可以选择(Choose)一个内核,修改其附加的内核参数.同时,您可以选择(Choose)使用系统命令行的shell来对启动操作系统过程进行更深层次的手工控制. 在第二阶段boot loader存在与计算机内存中后,就可以对文件操作操作系统进行查询了,同时,默认的内核镜像以及初始化计算机内存盘镜像也被加载到计算机内存中.一切准备完毕之后,第二阶段的boot loader就会调用内核镜像. V. 内核 (译者注:在翻译本章的时候,译者发现IBM网站上已有译好的文章,所以我们可以得出结论从本章开始以官方网站上的内容为主).当内核映像被加载到计算机内存中,并且阶段 2 的引导加载程序(Procedures)(Procedures)释放控制权之后,内核阶段就开始了.内核映像并不可能是一个可执行的内核,而不能是是一个压缩过的内核映像.通常他是一个 zImage(压缩映像,小于 512KB)或者是一个 bzImage(较大的压缩映像,大于 512KB),他是提前使用 zlib 进行压缩过的.在这一个内核映像前面是一个例程,他实现少量硬件设置,并对内核映像中包含的内核进行解压,然后将其放入高端计算机内存中,如果有初始 RAM 磁盘映像,就会将他移动到计算机内存中,并标明以后使用.然后该例程会调用内核,并开始启动操作系统内核引导的过程. 当 bzImage(用于 i386 映像)被调用时,我们从 ./arch/i386/boot/head.S 的 start 汇编例程开始执行(主要流程图请参看图 3).这一个例程会执行一些最基本的硬件设置,并调用 ./arch/i386/boot/compressed/head.S 中的 startup_32 例程.此例程会设置一个最基本的环境(堆栈等),并清除 Block Started by Symbol(BSS).然后调用一个叫做 decompress_kernel 的 C 函数(在 ./arch/i386/boot/compressed/misc.c 中)来解压内核.当内核被解压到计算机内存中之后,就可以调用他了.这是另外一个 startup_32 函数,但是这一个函数在 ./arch/i386/kernel/head.S 中. 在这一个新的 startup_32 函数(也称为清除程序(Procedures)(Procedures)或者是进程 0)中,会对页表进行初始化,并启用计算机内存分页功能.然后会为任何可选的浮点单元(FPU)检测 CPU 的类型,并将其存储起来供以后使用.然后调用 start_kernel 函数(在 init/main.c 中),他会将您带入与体系结构无关的 Linux 内核部分.实际上,这就是 Linux 内核的 main 函数.

小知识:GRUB 中的手工引导
在 GRUB 系统命令行中,我们可以使用 initrd 映像引导一个特定的内核,方法如下:复制内容到剪贴板代码:grub> kernel /bzImage-II.VI.1IV.2
[Linux-bzImage, setup=0x1400, size=0x29672e]grub> initrd /initrd-II.VI.1IV.II.img
[Linux-initrd @ 0x5f13000, 0xcc199 bytes]grub> bootUncompressing Linux... Ok, booting the kernel. 如果您不知道要引导的内核的名称,只需使用斜线(/)然后按下 Tab 键就可以了.GRUB 会显示内核和 initrd 映像列表.
通过调用 start_kernel,会调用一系列初始化函数来设置中断,执行进一步的计算机内存配置,并加载初始 RAM 磁盘.最后,要调用 kernel_thread(在 arch/i386/kernel/process.c 中)来启动操作系统 init 函数,这是第一个用户空间进程(user-space process).最后,启动操作系统空任务,现在调度器就可以接管控制权了(在调用 cpu_idle 之后).通过启用中断,抢占式的调度器就可以周期性地接管控制权,从而不能是提供多任务处理能力. 在内核引导过程当中,初始 RAM 磁盘(initrd)是由阶段 2 引导加载程序(Procedures)(Procedures)加载到计算机内存中的,他会被复制到 RAM 中并挂载到操作操作系统上.这一个 initrd 会作为 RAM 中的临时根文件操作操作系统使用,并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导.由于与外围设备进行交互所需要的模块可能是 initrd 的一部分,所以我们可以得出结论内核可以非常小,但是仍然需要支持大量可能的硬件配置.在内核引导之后,就可以正式装备根文件操作操作系统了(通过 pivot_root):此时会将 initrd 根文件操作操作系统卸载掉,并挂载真正的根文件操作操作系统. initrd 函数让我们可以创建一个小型的 Linux 内核,当中包括作为可加载模块编译的驱动程序(Procedures)(Procedures).这些可加载的模块为内核提供了访问磁盘和磁盘上的文件操作操作系统的方法,并为其他硬件提供了驱动程序(Procedures)(Procedures).由于根文件操作操作系统是磁盘上的一个文件操作操作系统,所以我们可以得出结论 initrd 函数会提供一种启动操作系统方法来获得对磁盘的访问,并挂载真正的根文件操作操作系统.在一个没有计算机硬盘(Hard)的嵌入式环境中,initrd 可以是最终的根文件操作操作系统,或者是也可以通过网络文件操作操作系统(NFS)来挂载最终的根文件操作操作系统. VI. init的介绍与结束语 当内核被引导并进行初始化之后,内核就可以启动操作系统自己的第一个用户空间应用程序(Procedures)(Procedures)了.这是第一个调用的使用标准 C 库编译的程序(Procedures)(Procedures).在此之前,还没有执行任何标准的 C 应用程序(Procedures)(Procedures). 在电脑的桌面 Linux 操作操作系统上,第一个启动操作系统的程序(Procedures)(Procedures)通常是 /sbin/init.但是这不是一定的.很少有嵌入式操作操作系统会需要使用 init 所提供的丰富初始化功能(这是通过 /etc/inittab 进行配置的).在很多很多情况下,我们可以调用一个简单的 shell 脚本来启动操作系统必需的嵌入式应用程序(Procedures)(Procedures). 与Linux 本身非常类似,Linux 的引导过程也非常灵活,可以支持众多的处理器和硬件平台.最初,加载引导加载程序(Procedures)(Procedures)提供了一种简单的方法,不用任何花架子就可以引导 Linux.LILO 引导加载程序(Procedures)(Procedures)对引导能力进行了扩充,但是他却缺少文件操作操作系统的感知能力.最新一代的引导加载程序(Procedures)(Procedures),比如说是 GRUB,允许 Linux 从一些文件操作操作系统(从 Minix 到 Reise)上进行引导.-----
顶您
》热 点 关 注