在Intel x86系统上,Windows操作系统获得控制首先从硬盘的主引导记录(MBR)开始,Windows Setup程序在安装Windows时填充MBR(其他的磁盘管理器也可能填充MBR)。MBR包含代码和数据,其代码称为引导代码,在系统引导时首先获得控制;MBR中的数据时一张分区表,制定了每个分区在磁盘上的位置和大小,以及分区的类型。当MBR中的引导代码被执行时,它检查分区表中的每一个分区,若找到一个已被标记为可引导的分区(称为引导分区),则将该分区的第一个扇区(称为引导扇区)读到内存中。由于分区表包含了每一个分区的磁盘位置,所以,引导扇区的位置很容易被确定。然后MBR的代码将控制权交给引导扇区中的代码。
Windows Setup程序在确定了要将Windows系统安装到哪个分区中以后,除了可能会写入MBR以为,还会写入该分区的引导扇区。所以,严格意义上讲,Windows操作系统的正真入口点应该时引导扇区中的代码。引导分区必须被格式化为Windows所支持的文件系统,典型的文件系统格式时NTFS和FAT,其中NTFS时Windows NT的原生文件系统,而FAT则是从MS-DOS时代继承和发展过来的。
引导扇区中的代码随硬盘文件系统格式的不同而有所不通,其职责时,给Windows提供有关该硬盘上卷的结构和格式方面的信息,并且从该卷的根目录中读入Windows的加载程序,即ntldr文件;然后将控制权交给ntldr的入口函数。为了能够从根目录中读入加载程序,引导扇区包含了能理解文件系统结构和读取文件的代码,这通常知识文件系统极其简单的一部分功能,而并非完整的实现。尽管引导扇区的职责相对简单,但是单个扇区(512B)的代码和数据往往不足以完成其功能,为此,Windows的做法是,让引导扇区中的代码读入其他扇区的数据,然后跳转到下一个扇区的代码区。这样就可以不受单个引导扇区长度的限制,这种做法相当于将第一个引导扇区当做一个加载器(loader),而真正完成引导扇区功能的扇区随后被加载进来并执行。这一过程对于MBR是透明的,从而保持良好的兼容性。
Intel x86处理器支持实模式和保护模式,在实模式下,处理器的寄存器都是16位的,而且不支持虚拟地址转译,只能访问物理内存空间中最低的1MB内存。计算器系统的BIOS工作在实模式下,并且,当ntldr获得控制权时,处理器仍然在实模式下运行。Ntldr文件实际上是由两部分组成的;第一部分是实模式代码,即首先获得控制权的代码区;第二部分是一个标准的Windows可执行二进制文件(PE文件格式),在ntldr中这部分被称为os loader。
Ntldr的实模式代码首先获得控制,完成需要在16位模式下执行的初始化工作,然后为切换到保护模式做好环境准备,之后将处理器切换到保护模式下,这样它就可以访问整个32位地址空间了。最后它将控制权交给os loader。因此,ntldr中的os loader是Windows真正的32位入口程序。
os loader刚获得控制时,处理器虽然工作在保护模式下,但是虚拟地址转译机制尚未开启,所以,处理器仍然直接使用物理地址。os loader首先做的工作是把物理内存管起来,用一个内存描述符数组把每一段内存的大小和用户记录下来,然后构造页目录和页面,使得16MB以下的内存能够通过页面映射(paging)机制进行访问,再设置好页目录寄存器,并打开页面映射机制。之后,os loader继续执行其他的初始化工作,包含I/O设备的初始化等。如果它还需要调用BIOS中的服务,则必须保护好保护模式下的设置,并暂时切换回实模式,待服务完成以后再切换到保护模式,并恢复设置。
接下来,os loader从系统分区(引导分区)的根目录下读入boot.ini文件。注意,os loader包含了读取当前文件系统的代码,它能够读取NTFS文件系统的子目录。然后,os loader清除屏幕,并检查在系统分区的根目录下是否有一个有效的hiberfil.sys文件,如果存在的话,这一次引导过程转移到休眠系统的恢复过程。因此os loader将控制权交给一段能恢复休眠系统的内核代码。
如果当前这次引导不是休眠恢复,那么, os loader解析boot.ini文件,如果该文件中有多个引导选项,则os loader显示一个引导选择菜单;如果boot.ini文件中只包含一个引导选项,那么,此菜单不显示,而是立即应用该引导选项。
Windows的引导选项可以用来指示当前这次引导的各种参数,包括内核模块的文件名称、HAL的文件名称、CPU参数、各种内存参数、调试参数,等等。关与这些引导选项的全面列表和介绍,读者可参考【MSDN-BOOT】。接下来os loader加载并执行NTDETECT.COM程序,这是一个16位实模式程序,它利用系统的BIOS来查询系统的基本设备和配置信息,包括系统的日期和时间、总线的类型、磁盘的信息、输入/输出的接口信息等。这些信息被收集起来,在引导过程的后期被存放到注册表HKLM\HARDWARE\DESCRIPTION键的下面。
然后,os loader 加载内核模块映像文件,默认为ntoskrnl.exe,以及HAL映像文件,默认为hal.dll。再加载注册表的SYSTEM储槽中的设置信息,它可以知道哪些设备驱动必须被加载进来,即被标记为“引导-启动”(SERVICE_BOOT_START)的设备驱动程序。然后它加载所有这些设备驱动程序,以及访问系统目录所必需的文件系统驱动程序。在此之前os loader也可以访问系统分区,但并非通过文件系统驱动程序。
至此,引导系统所需的模块都已被加载到内存中。而且,在此过程中os loader也已经构造了一个参数块,记录下了这次引导过程中加载器所获得的各种参数信息。参数块的类型为LOADER_PARAMETER_BLOCK,Windows内核在初始化过程中将会用到这些参数信息。WRK中包含有它的定义,
由上述代码的注解可以看出,参数中包含了有关这次引导的各种参数信息和系统配置,这里ARC名称是指符号ARC命名规范的字符串,例如(multi(0)disk(0)rdisk(0)partition(1))是指0号磁盘控制器第一块硬盘上的第一个分区。注意,参数块中的绝大多数信息由os loader来填充,而在接下来的内核初始化过程中使用,但也有例外,比如有关线程和进程的信息需要在内核初始化过程中填充。
最后,os loader将控制权交给内核模块的入口函数,该函数将不再返回,所以,接下来的引导过程由内核模块继续进行,引导扇区和系统加载器(ntldr或os loader)的使命已经完成。下图显示以上的引导步骤。
————————————————
版权声明:本文为CSDN博主「forcj」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/forcj/article/details/103300490