小議計算機存儲之六.操作系統啓動過程

 小議計算機存儲之六.操作系統啓動過程
<本文主要來源 en.wikipedia.org 更多內容請參考 Wikipedia>

草木瓜

20080903

前言

本文是本系列文章的最後一篇,主要介紹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手冊。


六、寫在最後

 文章的整理頗費時間,回顧整個系列,自感對存儲相關的知識作了一次較爲全面的梳理,從技術
到物理設備,再到邏輯結構,操作系統,每個知識點都有極爲深層的內容。相信大多數人只停留在
皮毛,而這個系列已不在是皮毛,已接觸到了皮層。
 
 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章