Linux系统启动过程详解

本文发布时间: 2019-Mar-22
Linux系统启动linux系统启动是一个非常复杂的过程,主要包括以下几个部分:载入BIOS的硬件信息并进行自检,并依据设定取得第一个可开机的设备;读取第一个开机装置内的MBR的boot Loader依据boot Loader的设定载入kernel,kernel会开始侦测并载入驱动程序;在硬件驱动成功之后会执行init脚本,也就是第一个用户进程。BIOS在按下电源按钮后,系统首先会执行BIOS,BIOS会检测硬件的信息(硬件的启动顺序等),然后去读取MBR的内容。但是系统在执行之前是如何执行BIOS的呢?在电源启动之后,CPU中的寄存器都已经有一个默认的初始值,其中EIP(32位的系统的指令寄存器)和基址寄存器的地址相加之后)的值是0xFFFFFFF0H,尽管CPU启动时处于实模式(实模式最多只能访问1M的内存空间,该模式下任何程序可以向内存中的任何地址中读取或者写入内容,该模式下没有保护和特权的概念,例如DOS)中,最多只能访问1M的内存空间,但是通过hack技术,CPU还是能执行处于0xFFFFFFF0H的指令。当CPU Reset(开机或者重新启动)后,根据X86架构的特性,(386以后)CPU会从4G地址的最顶端FFFFFFF0处获得第一条指令来执行,而这一地址被定位在BIOS里。由于FFFFFFF0到FFFFFFFF只有短短的16字节,根本不可能放下一段程序,所以这里会放一条跳转(Jump)指令让BIOS跳到更低的地址去执行。(CPU开始执行的程序时BIOS程序)。(复位向量 reset vector)复位向量存放的是内部处理在cpu充值之后执行的第一条指令的默认位置,复位向量可以是一个指针或者是地址。8086处理器的复位向量是在物理地址FFFF0h处(16 bytes below 1 MB),cs 寄存器在重置时的值是FFFFh,IP寄存器的值是0000h,形成的段地址是FFFFh:0000h,映射到FFFF0h。80286处理器的复位向量是在物理地址00FFFF0h处(16 bytes below 1 MB),cs 寄存器在重置时的值是F000h,IP寄存器的值是FFF0h,形成的段地址是F000h:FFF0h,映射到00FFFF0h。80386和之后的x86处理器的复位向量是在物理地址FFFFFFF0h处,cs 寄存器在重置时的值是F000h,cs寄存器的基址是FFFF0000h,IP寄存器的值是FFF0h,形成的段地址是FFFFF000h:FFF0h(FFFFF000h*4+FFF0h),映射到FFFFFFF0h。((FFFF0000h+F000h)*4:FFF0h)下图是系统的内存布局图:注:BIOS的大小一般是64KBMBRBIOS执行完自检操作之后,将MBR的内容复制到内存地址0x7C00H处,然后执行一条跳转指令,执行MBR的操作。那个BIOS何时将MBR加载到内存中的呢?其实BIOS是通过硬件的INT 13中断指令来读取MBR的,也就是说只要BIOS能检测到你的磁盘,它就会通过INT 13中断指令去读取第一个磁盘区内的MBR。MBR包括两个重要的部分:1.微型的和操作系统相关的启动程序2.分区表MBR将系统启动程序载入内存继续执行。boot LoaderMBR载入之后就会开始执行MBR中的boot Loader。boot Loader的最主要功能就是要认识作业系统的档案格式并载入核心到内存中去执行。但是不同的系统具有不同的boot Loader,同时只有一个MBR,那我们如何决定该载入多系统中那个boot Loader呢?其实每个文件系统或者分区都会保留一块开机磁区(boot sector)提供作为作业系统存放boot Loader,通常作业系统都会预装一份loader到它根目录所在的文件系统(文件系统的挂载)的boot sector上。如果我们在一个电脑上同时安装了Linux和Windows,该boot sector,boot Loader于MBR的关系有点像下图:其中蓝色方块表示boot loader,红色方块表示内核文件。boot Loader的功能如下:提供选项列表:使用者可以选择不同的开机项目,这个是多重开机系统的重要功能转入核心档案:直接将核心档案载入内存运行内核转交个其他Loader:将开机管理功能交给其他的Loader负责 由于具有选项列表的功能,我们可以选择不同的核心载入,由于具有转交功能,我们能够将Loader权限交给其他的Loader,所以实现了多重启动。但是windows的Loader不具有转交功能,所以在装双系统的时候必须先装windows然后再装linux,因为windows的loader默认会写入MBR和自身文件系统的boot sector。下图是多系统的启动方式: 核心的执行 当我们使用boot Loader将核心载入到内存后,此时核心开始接管BIOS的工作了。核心一般会进行硬件的检测,不会使用BIOS的检测信息。 那么核心文件在哪里呢?一般核心文件会在/boot下,并且取名为/boot/vmlinuz。如下图所示:该核心文件被boot Loader动态的载入内存,核心也是作为模块module动态载入的,模块文件存在于/lib/modules目录下。如下图所示: 由于模块组是存放在根目录所在的文件系统下的(根目录/与/lib不能存放在不同的文件系统中),所以在开机过程中核心必须挂载根目录才能在动驱动程序的功能。 一般来说非必要的同时可以编译成模块的功能都会编译成模块动态载入,例如USB,SATA,SCSI等磁盘驱动程序也是以模块的方式存在的。一般情况下,BIOS通过INT 13中断去的boot Loader与kernel文档来启动系统,然后核心会开始接管系统并且尝试挂载根目录来取得额外的驱动程序。但是问题出现了?在没有取得磁盘的驱动程序之前,核心根本无法然是SATA等磁盘,所以在挂载根目录之前必须取得磁盘的驱动程序,但是磁盘的驱动程序在/lib/modules目录下,你根本无法挂载根目录又怎么读取/lib/modules下面的驱动程序模块文件?linux使用虚拟档案系统来处理这个问题。虚拟档案系统 虚拟档案系统一般的文件名为/boot/initrd,这个文件能够通过boot Loader来载入到内存中,然后这个文件会被解压并且在内存中模拟生成一个根目录(文件系统),initrd文件包含必备的一小部分目录和可执行文件用来载入实际开机过程中所需要的核心模块,通常这些模块就是USB,RAID,LVM,SCSI等文件和磁盘的驱动程序等。比如insmod工具可以将核心模块载入虚拟的内核。 等载入完成之后,会帮助核心重新呼叫/sbin/init来开始后续的正常开机程序。 下面是initrd的内部结构图: cpio是一个文档管理器,用来将标准输入写入文件或者目录。整个系统启动的过程如下图所示: 从上图可以看出,boot Loader可以载入kernel和initrd,然后在内存中解压initrd为根目录,kernel就能够借此载入适当的驱动程序,最终释放虚拟的文件系统并挂载事假的根目录文件系统就能够开始正常的开机过程了。


(以上内容不代表本站观点。)
---------------------------------
本网站以及域名有仲裁协议。
本網站以及域名有仲裁協議。

2024-Mar-04 02:09pm
栏目列表