Linux 開機流程(x86版) --上

(一)

Linux開機流程?這有什麼好說的?啊不就是按poweron的按鈕,然後就會在螢幕上出現一堆黑黑白白花花綠綠的訊息和圖示,最後出現要求登入的畫面,只要把usernamepassword都打對就可以登入linux了,之後就可以為所欲為啦

不是啦,各位有沒有想過在以上所描述的整過程當中,您的電腦和Linux作業系統做了什麼壞事,喔不,是做了哪些事情讓您可以進入一個可供作業的系統之中呢?而筆者今天所要介紹的就是在這整個從系統供電開始一直到使用者登入時,電腦和Linux作業系統做了哪些事情,讓對於了解系統有興趣的網友可以稍微了解一下這一個完整的程序為何。
   
然而這個課題可以很粗淺,也可以很深入。所以我打算分兩個部份來說明,先是初淺地交待整個流程,再來才比較深入地了解這整個流程中比較細部的程序為何。



在開始進入正題以前,我習慣讓大家先思考一下,既然主題是系統開機流程,不妨先思考一下,系統開機,需要做哪些事情,才能讓我們這些使用者有一個可供作業的操作環境。

  • 首先,電腦一定是好的啊,也就是說電腦硬體沒有問題,否則不是做白工了嗎?所以希望我們的電腦自已就能先幫笨笨的我檢查一下系統是否可以工作。
  • 嗯,好,電腦硬體沒有問題。那麼再來就是軟體了。什麼?還沒到軟體出場喔?        因為啊,雖然硬體沒有問題,但既然是開機嘛,還要初始化 (Initialization)一下…
  • 再來就該是軟體初始化了,我這麼聰明可以舉一反三。什麼?又錯了…當然啦,沒有找到軟體,是要怎樣叫軟體初始化啊 Orz  找到了他(軟體),還要叫他來做事情啊(他不可以是soho族嗎?)
  • 軟體的初始化,軟體自己要知道初始化的順序和部份有哪些,如果由使用者來指定,就太麻煩啦…想像一下開機開一半,作業系統還要求您選擇要做初始化的軟體有哪些…這就太白目了
  • 建立一個完整的操作環境
  • 等待使用者登入
  • 檢查使用者是否合法(偷渡客與狗禁止入內)

   好了,現在對於大至上對於系統開機,需要做哪些事情,才能讓我們這些使用者有一個可供作業的操作環境已經有個譜了。再來就可以開始介紹這些過程之中做了哪些事情。慢著,先想像一下,當一個企業要開一個新專案時會怎麼做?首先大老板會找總經理,叫到他的office開始劈哩叭啦地吹棒他的新計劃新理念有多麼地棒,然後交待經理確實執行,並在什麼時候要看到產品上市。這…跟開機流程有關係嗎?難不成開不了機可以去找大老板還是總經理嗎?當然有關係啦…什麼關係呢?就請看下去就對了唄O(≧▽≦)O


()



如果我們開機開一半才發現這個不能用,那個壞掉了,心裡一定很,所以我們會希望電腦開機在最開始時可以幫忙做個初步的檢查,例如吸屁優有沒有壞掉,煮雞板是不是因為電壓不穩,早就燒掉了,還有DIMM有沒有確實插入啊(這不是黃色小說,不要亂想)…等等…

所以系統供電以後,確定煮雞板(mainboard,又稱motherboard)各部件電壓沒問題後,由於記憶體已被自動清零,CPU此時是無法獲得指令的,在這個momentCPU這個大老板只要知道找他的總經理就對了。老板不必知道完成這個專案需要找誰來負責當專案經理,找哪些團隊來負責產品設計等等比較細部的事情,他只知道找經理就對了啦…所以在我們的電腦系統,CPU在一開始誰也不認識,但他知道經理是誰,在哪。為什麼他會知道呢?因為內定啊!!

在我們的電腦系統中扮演總經理角色的就是BIOS。所以其全名就是『基本上(Basically)決定員工進來(getIn)還是滾蛋(getOut)Supervisor 不是啦(雖然有時算是),這裡的BIOS指的是BasicInput OutputSystem,他在最初始的任務是提供CPU所需的啟動指令,還記得剛才說的,怎麼找到BIOS?沒錯,就是內定。電腦開發者預先編好了供系統啟動使用的啟動程式,把它們存放在ROM中,並安排它到一個固定的位置,即FFFF:0000CPU就從BIOS中獲得了啟動所需的指令集。



()



BIOS
中啟動程式的第一個任務就是系統給電後的自檢(POSTPower-On Self Test),它是一個專門的程式,BIOS被執行以後會先執行它,而POST會做哪些事情,讀者可參考:http://www.ns-bbs.com/teach/list.asp?id=75
然後是對系統內的硬體設備進行檢查和連接,並把測試後取得的資料存放到BIOS資料區,以便作業系統在啟動時或啟動後使用。此外,BIOS還提供一組中斷讓硬體能夠被存取使用。

再來呢,BIOS會根據使用者設定的開機順序寻找開機磁區(bootsector)。同樣地,BIOS怎麼知道開機磁區位於哪裡呢?答案也是內定的。在我們的儲存媒介例如硬碟或者早期在用的軟碟,有個專門放置開機資訊的地方,叫做MBR(Master BootRecord),而這裡放置的往往就是所謂的開機引導程式(BootLoader)。事實上,BIOS無法幫我們決定要從哪開機,要專入哪些軟體。所以就根據使用者設定的開機順序去找該磁碟的MBR,這個MBR一般就位置磁碟的第一個Sector,也只有一個sector,所以大小是512B,這時將執行權交給MBR裡的bootloader。若是可開機(bootable)軟碟(Floopy)一般只會有一個作業系統,MBR所以裡面放的就是/usr/src/linux/arch/i386/boot/bootsect.S(新版應把i386改成x86),由這支程式決定要載入後續哪些程式;後續的這些程式包括要做初式化以及載入核心的Assemblycodes

在開機期間有幾個很重要的Assemblycodes,包括/usr/src/linux/arch/i386/boot/bootsect.S/usr/src/linux/arch/i386/boot/setup.S/usr/src/linux/arch/i386/boot/compressed/head.S。請注意,不同版本的kernel,其路徑可能稍有不同。以下分別介紹這幾支程式的工作。



()


如前文所說的,bootsect.S這支程式往往擺在MBR裡頭。往往,那就是說也有例外囉…沒錯,您真聰明,由於一顆硬碟裡可以安裝不只一個作業系統,例如最常見的windowsLinux共存,一般我們都會在安裝Linux的同時安裝Lilo或者GRUB,所以BIOS完成自檢以後,去MBR找的程式可能不是bootsect.S而是GRUB,由GRUB完成bootsect.S的工作或者由GRUB去執行bootsect.S。這就是LinuxBootLoader。它的主要作用就是將系統啟動程式讀入記憶體中並把控制權交給它。

當我們完成Linuxkernel的編譯後,就獲得一個新的核心映射,BootLoader就放在核心映射檔的開始處。當BIOSBootSector找到BootLoader後,將BootLoader讀入至記憶體中物理位址0x07c00處,而後將控制權轉給BootLoaderBootLoader再把自己從地址0x07c00移到0x90000

其後還會處理一系列工作以後,再載入Setup.S。然後程式的執行權也轉交給Setup.S,而它的主要工作是把剛才BIOS檢查完系統後保存的系統參數,放在0x90000~0x901FF這個記憶體區間。然而它會執行Vedio.S,檢查並設定一些有關於螢幕的設定和設定模式。此外還包括像鍵盤,PS/2滑鼠等。最後它要讓系統進入保護模式,以實現多工的能力。

之後跳轉到0x100000的位置,執行head.Sstartup_32head.S的主要任務是要解壓縮kernelimage。由於現在kernel的功能越來越強大,所以檔案大小也相對大了許多,所以一般會經過壓縮,當開機待載入核心時,再透過解壓縮程式把它還原回原來的大小。如果kernel是放在0x00001000處,在decompress時會直接解壓縮到0x00100000。如果kernel是放在0x00100000處,在decompress時會先解壓縮到暫時的buffer空間,即目前compressedkernel image後的(0x00100000+ bzImage size),再將之移動到0x00100000


()

完成以後,再跳轉到main.cstart_kernel()中。呼,總算開始進入C語言函式了,但也別高興得太早,因為這部份也很複雜。這時候的主要任務是要對核心做一系列的初始化。我們先不介紹這部份,待下一個階段再來介紹這部份初始化了哪些程序。

初始化結束以後,就進入我們比較熟悉的INIT階段。好,讓我們喘口氣,喝口茶…基本上,把前面介紹的都忘了也沒關係,因為後面的部份跟使用者比較有直接的關係。直到這個階段,基本的Linux核心環境已經建立起來了。在start_kernel()的最後,通過呼叫init()函數,系統創建第一個核心線程,啟動了init過程。init()主要進行了一些外部設備初始化的工作的,包括呼叫do_basic_setup()完成外部設備及其驅動程式的載入和初始化。再來是完成檔案系統初始化和root檔案系統的安裝。之後,init()使用execve()系統呼叫載入執行init程式。到此init()函數結束,Kernel的引導部分也到此結束了。

Ini
的行程號碼是1,它是系統所有行程的起點,然後它還需要讀取配置檔/etc/inittabinittab是一個不可執行的文字檔案,等等…什麼我騙人?你在ubuntu找不到/etc/inittab?哈,真是誤會一場。原來,在ubuntu是找不到/etc/inittab的,那ubuntu要怎麼設定runlevel之類的東東呢?答案是,它把inittab分散在/etc/event.d裡。

Inittab
主要設定了runlevelaction運行方式,process等。這裡暫不細談inittab的內容,留待之後說明。然後它會呼叫/etc/rc.d/rc.sysinit,而rc.sysinit是一個bashshellscript,它主要是完成一些系統初始化的工作,它主要完成的工作包括:啟動交換分區,檢查磁碟,載入硬體
模組以及其他一些需要優先執行的任務等。同樣的,細部的內容留待之後才說明。這裡先有個概念就好。

 



0 意見:

張貼留言

 
Copyright 2009 Linux學習誌
BloggerTheme by BloggerThemes | Design by 9thsphere