Linux启动

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2.2 Linux 启动过程详解

在了解了Linux 的常见命令之后,下面来详细了解一下Linux 的启动过程。Linux 的启动过程包含了Linux工作原理的精髓,而且在嵌入式的开发过程也非常需要这方面知识的积累。

为了降低阅读的难度,在这部分作者尽量避免直接对大段的汇编代码进行分析,而主要阐述其原理及INIT进程。希望读者能认真耐心阅读,相信在真正掌握这一节的内容之后对Linux的认识会有一个质的飞跃。

本书假定读者对微机原理、操作系统、汇编和C 语言已有了一定的基础,因此对以上知识的基础概念不再做详细的说明。

2.2.1 概述

用户开机启动Linux 过程总体上是这样的:

1、首先当用户打开PC 的电源时,CPU 将自动进入实模式,并从地址0xFFFF0 开始自动执行程序代码,这个地址通常是ROM-BIOS 中的地址。这时BIOS 进行开机自检,并按BIOS 中设置的启动设备(通常是硬盘)进行启动,接着启动设备上安装的引导程序lilo 或grub 开始引导Linux(也就是启动设备的第一个扇区),这时,Linux 才获得了启动权。

2、接下来的第二阶段,Linux 首先进行内核的引导,主要完成磁盘引导、读取机器系统数据、实模式和保护模式的切换、加载数据段寄存器以及重置中断描述符表等。

3、第三阶段执行init程序(也就是系统初始化工作),init 程序调用了rc.sysinit 和rc等程序,而rc.sysinit和rc在完成系统初始化和运行服务的任务后,返回init。

4、之后的第四阶段,init启动mingetty,打开终端供用户登录系统,用户登录成功后进入了Shell,这样就完成了从开机到登录的整个启动过程。

Linux 启动总体流程图如图2.2所示,其中的4 个阶段分别由同步棒隔开。由于第一阶段不涉及Linux 自身的启动过程,因此,下面分别对第二和第三阶段进行详细讲解。

Linux启动流程

2.2.2 内核引导阶段

在grub或lilo等引导程序成功完成引导Linux系统的任务后,Linux就从它们手中接管了CPU的控制权。用户可以从上下载最新版本的源码进行阅读,其目录为:linux-2.6.*.*\arch\i386\boot。在这过程中主要用到该目录下的这几个文件:bootsect.S、setup.S以及compressed目录下的head.S等。

首先要介绍一下,Linux的内核通常是压缩过后的,包括如上述提到的那几个重要的汇编程序,它们都是在压缩内核vmlinuz中的。因为Linux中提供的内核包含了众多驱动和功能,因而比较大,所以在采用压缩内核可以节省大量的空间。

(1)bootsect阶段

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

bootsect.S完成加载动作后,grub 会跳过bootsect那512bytes 的程序段,然后直接(动作2)运行setup.S(程序入口0x90200)里的第一跳指令。就是说bzImage 里bootsect的程序没有再被执行了,而bootsect.S在完成了指令搬移以后就退出了。

之后执行权就转到了setup.S的程序中。

(2)setup阶段

setup.S的主要功能就是(动作1)利用ROM BIOS中断读取机器系统数据并将系统参数(包括内存、磁盘等,由BIOS返回)拷贝到0x90000-0x901FF内存中,这个地方正是bootsect.S存放的地方,这时它将被系统参数覆盖。以后这些参数将由保护模式下的代码来读取。

除此之外,setup.S还将video.S中的代码包含进来,检测和设置显示器和显示模式。最后,它还会(动作2)设置CPU的控制寄存器CR0(也称机器状态字),进入32位保护模式运行,并跳到绝对地址为0x100000(虚拟地址0xC0000000+0x100000)处。当CPU跳到0x10000时,将执行“arch/i386/kernel/head.S”中的startup_32,Bootloader过程结束。

(3)head.S阶段

当运行到head.S时,系统已经运行在保护模式,而head.S完成的一个重要任务就是将内核解压。就如本节前面提到的,内核是通过压缩的方式放在内存中的,(动作1)head.S通过调用misc.c中定义的decompress_kernel()函数,将内核vmlinuz 解压到0x100000的。

接下来head.S 程序(动作2)完成寄存器、分页表的初始化工作,但要注意的是,这个head.S程序与完成解压缩工作的head.S程序是不同的,它在源代码中的位置是arch/i386/kernel/head.S。

在完成了初始化之后,head.S就跳转到start_kernel()函数中去了。

(4)main.c阶段

start_kernel()是“init/main.c”中的定义的函数,(动作1)start kernel()调用了一系列初始化函数,进行内核的初始化工作。要注意的是,在初始化之前系统中断仍然是被屏蔽的,另外内核也处于被锁定状态,以保证只有一个CPU用于Linux系统的启动。

在start_kernel()的最后,(动作2)调用了init()函数,也就是下面要讲述的INIT 阶段。

2.2.3 init阶段

在加载了内核之后,由内核执行引导的第一个进程就是init进程,该进程号

相关文档
最新文档