分享

操作系统启动过程

 异界 2014-09-11

前言

本文是本系列文章的最后一篇,主要介绍MS-DOS,各类Windows和Linux操作系统的启动过
程,用了这么久的操作系统是该系统地了解一下启动的完整过程。

一、MS-DOS 启动过程

 当PC启动时,读取启动盘第一个扇区并执行其中的引导代码。如果发现了DOS 引导扇区,
会将IO.SYS的前三个扇区加载到内存中,并将PC控制权交由IO.SYS(输入输出模块)。
 
 IO.SYS接管计算机控制权执行如下操作:
 
  首先将IO.SYS其他部分内容加载到内存,依此初始化每个缺省设备
  接着加载处理MS-DOS内核文件MSDOS.SYS,不过在MS-DOS 7.0中,MSDOS.SYS改
 为启动配置文件
  再者处理 CONFIG.SYS文件,CONFIG.SYS是重要的配置文件,是可以进行编辑的文本
 文件
  
   内容示例:
  
   DEVICE=C:\DOS71\ECHO.SYS w/e/l/c/o/m/e ..
   DEVICE=C:\DOS71\ECHO.SYS c/o/p/y/r/i/g/h/t ..
   DEVICE=C:\DOS71\HIMEM.SYS
   ...
   SHELL=COMMAND.COM /P /E:640
   ...
   SET PATH=C:\DOS71; ..;
 
   注:SHELL行表示SHELL环境使用command.com,启动的工作路径为C:\DOS71,环境
   大小是640字节,/p表示这个是父进程,不能够关闭或使用exit退出。更多详细内容请参
   考wiki。
  
  根据CONFIG.SYS配置加载相应的SHELL,MS-DOS一般为COMMAND.COM
  处理COMMAND.COM时,会调用AUTOEXEC.BAT批处理脚本
  
   AUTOEXEC.BAT里面的命令都是可以SHELL环境下执行的,主要作用是设置一些环境变
   量。如键盘,声卡等等。同时也会初始一些低级的系统工具,如磁盘缓存,鼠标驱动,
   键盘驱动等。最后显示命令提示符。

  
二、基于MS-DOS的Windows启动过程 

 Windows 3.x/95/98/Me 前期引导的由MS-DOS负责。在启动阶段,处理config.sys和执行autoexec.bat
同时会读取配置文件WIN.INI和SYSTEM.INI,并加载相应的虚拟设备驱动(从SYSTEM.INI或者
HKLM\System\CurrentControlSet\Services\VxD)。所有系统配置文件和设备驱动都被加载后,32
位vxd消息服务(Msgsrv32)会启动mprexe.exe,准备用户登录和网络登陆,当用户登陆到Windows
后,系统加载Explorer.exe,进入Windows。

 基于MS-DOS的Windows,可以在启动到DOS的命令提示符下,键入win,手工启动Windows。
此时实际上是调用win.com文件。
 详细的启动过程见转载的《Win 98系统启动过程全揭密》一文。
 http://blog.csdn.net/liwei_cmg/archive/2008/09/15/2931385.aspx
 
三、基于Win NT 操作系统的启动过程

 WIN NT与基于DOS的Windows有显著的不同,其操作系统引导程序为 NTLDR。引导启动过程
如下:

 x86或x64平台下,计算机以实模式启动并加载NTLDR。NTLDR是一个二进制文件,有两部分
组成,StartUp module 和 OS loader 。StartUp module 的主要任务就是将计算机切换到保护模式。
 OS loader 主要包括识别访问IDE硬盘的分区文件系统(如FAT, NTFS等等)的基本功能,如果是
SCSI硬盘,还需要加载Ntbootdd.sys文件,获取相应的SCSI驱动。
 引导程序接着读取boot.ini配置文件,并显示用户选择操作系统菜单。如果boot.ini丢失,系统会
缺省选择C:\Windows目录。
 这个时候,Windows 2000以及后续版本的ntldr,会去查找hiberfil.sys(休眠文件,与内存等同大
小,是上次操作系统休眠时的内存镜象),将此文件读取并加载内存。

 boot.ini文件内容示例:
 
 [boot loader]
 timeout=30
 default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
 [operating systems]
 multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
 
 multi(a)disk(b)rdisk(c)partition(d)这部分内容是关键,是采用ARC命名规则。ARC第一部分用
于标识硬件适配卡(磁盘控制器),即为multi或者scsi选项,这里使用的是multi。multi表示一个非
scsi硬盘或一个由scsi bios访问的scsi硬盘,而scsi则表示一个scsi bios禁止的scsi硬盘。
 (a)表示磁盘控制器的序号,从0开始。
 disk(b),仅对multi项有意义,表示磁盘控制器的硬盘序号,从0开如。
 rdisk(c),仅对scsi项有意义,表示磁盘控制器的硬盘序号,从0开始。
 partition(d),表示对应硬盘分区号,从1开始。

 注意,当只有一个操作系统选择项时,启动菜单不会显示。用户选择操作系统,如果不是基
于NT的操作系统,NTLDR会读取bootsect.dos,并交付计算机的控制权。如果选择的是基于NT
的操作系统,接下来NTLDR会执行ntdetect.com,收集硬件信息。此时,NTLDR清屏并显示
Windows启动进度条,这时如果按下F8,会显示高级启动菜单,包括安全模式选项。
 
 收集完所有相关硬件信息后,接着启动NToskrnl.exe(NT 操作系统内核文件), 并读取加载硬
件抽象层文件(hal.dll)。如果有文件丢失,系统会提示 "Windows could not start because the following file
was missing or corrupt",并终止启动。这时系统控制权交由内核,显示Windows Logo。

 加载内核时,启动的硬件设备信息保存在 HKLM\SYSTEM,可以看到一系列键值组成Control Set,
如ControlSet001,ControlSet003,ControlSet004,CurrentControlSet等。Windows使用CurrentControlSet
读取存取当前信息。Windows在启动过程中使用HKLM\SYSTEM\Select确定对应的键值。
 Default NTLDR的默认选择,Failed 值如果等于 Default值,NTLDR会显示错误信息,并提示
菜单是否以最后一次正确配置信息启动(LastKnownGood),如果用户选择LastKnownGood,Default
值也被修改为LastKnownGood的值。

 内核启动过程:
 ntoskrnl.exe 内核
 hal.dll 硬件抽象层
 kdcom.dll 内核调试扩展dll
 bootvid.dll  windows logo 以及进度条显示
 配置信息注册表位置
  HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute
 以相应顺序 HKLM\SYSTEM\CurrentControlSet\Control\ServiceGroupOrder 启动服务,这
时会显示进度条,Windows 2000以前版本进度条能反映服务加载,Server 2003和XP则是意
思一下,服务加载是异步的。
 
 所有的设备驱动加载好了以后,NToskrnl.exe启动Session Manager Subsystem (smss.exe)。
 在所有文件打开之前,smss.exe启动Autochk。Autochk 挂载(mount)所有的驱动,检查是否正常,
上一次关闭是否彻底,否则会启动chkdsk进行扫描修复,即我们常见的Check Disk。Session Manager Subsystem
配置信息位置:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager。
 
 启动时,smss.exe处理过程:
 创建环境变量 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
 启动内核态Win32子系统(win32k.sys),允许windows切换到图形化
 启动用户态Win32子系统Client/Server Runtime Server Subsystem (csrss.exe)
 创建虚拟内存页 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
 启动winlogon.exe, 加裁 Graphical Identification And Authentication (GINA) ,提供用户登录支持
 
 Winlogon启动过程:
 Winlogon 调用 GINA ,出现登录提示框,用户输入用户名密码
 Winlogon 启动 Local Security Authority Subsystem Service (lsass.exe) 验证登录
 Winlogon 启动 Service Control Manager (SCM) ,SCM依此启动设置为自动启动的服务
 
 Winlogon之后的阶段就是用户登录阶段了。
 
 用户登录阶段:
 更新Control Sets的LastKnownGood
 用户计算机的组策略被应用
 启动如下位置的应用
 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer\Run
 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
 HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Run
 HKCU\Software\Microsoft\Windows\CurrentVersion\Run
 HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
 All Users ProfilePath\Start Menu\Programs\Startup\
 Current User ProfilePath\Start Menu\Programs\Startup\
 
 
 Windows NT format 命令会将 Volume Boot Record 写入磁盘,主要是为了运行 NTLDR 程序。
 在 Windows Vista 和 Windows Server 2008,NTLDR 不在使用,其被 winload.exe 和 Windows
Boot Manager 所替代。
 
四、Windows Vista 启动过程

 Wiki 关于 Vista 的启动预览:
 Bios > Master Boot Record > Boot Sector > Windows Boot Manager > Read from BCD >
 Search for hibernation file > Start winload.exe > Start ntoskrnl.exe > Start smss.exe >
 Start winlogon.exe > start services and login interface

 Vista 启动过程与 NT 内核的操作系统稍有区别。Boot Sector 加载的是 Windows Boot Manager
(Bootmgr.) ,然后读取 Boot Configuration Data 启动操作系统。在NT 内核Boot Sector 加载
的是NTLDR。

 Boot Configuration Data 存储在数据文件中,位置一般存放于系统卷的/boot/bcd下。Boot Configuration Data
可以使用bcdedit.exe进行编辑。
 
 winload.exe是操作系统的引导程序,由Windows Boot Manager调用,与NT下NTLDR功能是等
同的。

五、Linux 启动过程

 很容易发现,计算机启动的控制权都是如下变化,BIOS->Boot Loader->Kernel。Linux也不例外。
之前的文章《Linux手机DIY.内核初探.系统后台启动简单介绍》http://blog.csdn.net/liwei_cmg/archive/2006/11/28/1418109.aspx
也曾对Linux启动作过介绍,不过偏重于手机嵌入式的实际代码,这里我想只就理论体系去简单说明。
 要理解内核启动的具体详细过程,就需要对内核源码有全面的认识,目前自感缺乏这方面的知识。
 
 启动概览:
 机器加电启动 BIOS
 引导阶段 Boot loader stage 1 (MBR) Boot loader stage 2 (LILO, GRUB ...)
 启动内核 (linux)
 初始化 INIT (用户)
 
 Boot loader 阶段:
 系统实模式下执行引导扇区代码,部分加载引导程序(Boot loader)后,将控制权交给引导程序。
Linux引导程序通常为lilo和grub。接着引导程序将剩余的内容加载到内存,并准备选择待引导的操
作系统。

  <GRUB>
  Boot loader stage 1,BIOS 读取执行 MBR,然后继续引导 Boot loader stage 2。
  Boot loader stage 2,控制权已经在GRUB手中,如果这部分的代码在一个大磁盘驱动器上,还
 需要加载Boot loader stage 1.5,其中包括对超过1024柱面和LBA驱动器的支持。Boot loader stage 1.5
 可以存放在MBR,也可以存放在分区上。Boot loader stage 2 执行并显示 GRUB 操作系统选择
 菜单,也允许修改操作系统环境和参数。GRUB支持访问文件系统,本身的配置文件就是存放在
 分区文件系统下,便于调整修改。/boot/grub 目录中包含了 stage1、stage1.5 和 stage2 GRUB
 引导加载程序等。

  注:《服务器配置实例(一).HP Prolient ML570 服务器》http://blog.csdn.net/liwei_cmg/archive/2007/05/20/1618174.aspx
 一文中就介绍了GRUB不能引导的处理方法。
 
  GRUB配置文件/etc/grub.conf,内容示例:
  # grub.conf generated by anaconda
  #
  # Note that you do not have to rerun grub after making changes to this file
  # NOTICE:  You do not have a /boot partition.  This means that
  #          all kernel and initrd paths are relative to /, eg.
  #          root (hd0,0)
  #          kernel /boot/vmlinuz-version ro root=/dev/sda1
  #          initrd /boot/initrd-version.img
  #boot=/dev/sda
  default=0
  timeout=10
  splashimage=(hd0,0)/boot/grub/splash.xpm.gz
  title Red Hat Linux (2.4.20-8)
          root (hd0,0)
          kernel /boot/vmlinuz-2.4.20-8 ro root=LABEL=/
          initrd /boot/initrd-2.4.20-8.img
 
 
  <LILO>
  LILO方式是比较古老的方式,不支持文件系统,其引导代码直接存放在MBR区。系统一旦引导
 失败后,只能通过软盘启动盘之类的方式加以修复。LILO直接使用裸设备方式读取数据,显示菜单
 以便用户选择操作系统,并加以引导。
 
  LILO启动配置文件为/etc/lilo.conf,内容示例:
  prompt
  timeout=50
  default=linux
  boot=/dev/sda
  map=/boot/map
  install=/boot/boot.b
  message=/boot/message
  linear
 
  image=/boot/vmlinuz-2.4.20-8
          label=linux
          initrd=/boot/initrd-2.4.20-8.img
          read-only
          append="root=LABEL=/"
 
 Kernel 内核阶段:
 
 引导程序将Linux内核映象加载到内存中,这个内核映象并不是可执行的内核,是经过压缩
后的内核,通常是一个zImage(小于512K)或者bzImage(大于512K) ,需要调用zlib进行解压缩。
内核加载时会处理一些硬件上的设置,并将内核映象完全解压缩到高位内存区,加载RAM disk,
然后启动内核。
 
  <x86 系列的执行过程>
  《Linux手机DIY.内核初探.系统后台启动简单介绍》http://blog.csdn.net/liwei_cmg/archive/2006/11/28/1418109.aspx 
 一文中虽然介绍的是arm系列的CPU,但从过程来讲是相似的,简单列下调用过程。
 
        arch/i386/boot/head.S                  start()
        arch/i386/boot/compress/head.S   startup_32()
        arch/i386/boot/compress/misc.c    decompress_kernel()
 
        arch/i386/kernel/head.S                startup_32()
        init/main.c                                    start_kernel()
        init/main.c                                    cpu_idle()
                                                          pivot_root ()
       
  完成解压缩后的 startup_32 () 函数(也称为清除程序或进程 0),会进行内存管理(页表初
始化,内存分页)。然后检测 CPU 的类型以及可选的浮点单元(FPU),最后调用 start_kernel
函数,进入体系结构无关的 Linux 内核部分。其实可以理解为 Linux 内核的 main 函数。

 start_kernel () 完成大部分的初始化任务,设置IRQs,内存配置,启动init进程(第一个用户进程),
最后启动空任务cpu_idle()。这时进程调度接管了计算机的控制权,通过启用中断,可以提供多
任务处理能力。
 
 内核启动过程中同时也挂载了 initial RAM disk ("initrd") ,先前已加载,用户系统启动的临时root
文件目录。这使得加载驱动模块时不必要使用物理磁盘或者其他磁盘驱动,减小了内核体积。
 内核启动会调用 pivot_root () ,卸载RAM disk,代替它的是真正的磁盘文件系统。RAM disk
使用的内存同时也被回收。
 上述工作完成后,启动init进程(通常为/sbin/init)。init是所有进程的父进程,主要任务就是根据
/etc/inittab配置文件创建相应进程。init,inittab相关知识相参考man手册。


六、写在最后

 文章的整理颇费时间,回顾整个系列,自感对存储相关的知识作了一次较为全面的梳理,从技术
到物理设备,再到逻辑结构,操作系统,每个知识点都有极为深层的内容。相信大多数人只停留在
皮毛,而这个系列已不在是皮毛,已接触到了皮层。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多