前言
本文是本系列文章的最后一篇,主要介绍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 Da
的是NTLDR。
Boot Configuration Da
可以使用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-on
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手册。
六、写在最后
文章的整理颇费时间,回顾整个系列,自感对存储相关的知识作了一次较为全面的梳理,从技术
到物理设备,再到逻辑结构,操作系统,每个知识点都有极为深层的内容。相信大多数人只停留在
皮毛,而这个系列已不在是皮毛,已接触到了皮层。
联系客服