天天看點

《Linux核心設計的藝術:圖解Linux作業系統架構設計與實作原理》——1.1 啟動BIOS,準備實模式下的中斷向量表和中斷服務程式

相信大家都知道一台計算機必須要安裝一個所謂“作業系統”的軟體,才能讓我們使用計算機,否則計算機将是一堆毫無生命力的冰冷的硬家夥。在為計算機安裝了作業系統後,當你按下計算機電源按鈕的那一刻,計算機機箱傳來了嗡嗡的聲音。這時你感覺到,計算機開始啟動工作了。然而,在計算機的啟動過程中,作業系統底層與計算機硬體之間究竟做了哪些複雜的互動動作?下面我們将根據作業系統實際的啟動和運作過程對此進行逐漸的剖析和講解。

計算機的運作是離不開程式的。然而,加電的一瞬間,計算機的記憶體中,準确地說是ram中,空空如也,什麼程式也沒有。軟碟裡雖然有作業系統程式,但cpu的邏輯電路被設計為隻能運作記憶體中的程式,沒有能力直接從軟碟運作作業系統。如果要運作軟碟中的作業系統,必須将軟碟中的作業系統程式加載到記憶體(ram)中。

特别注意

我們假定本書所用的計算機是基于ia—32系列cpu,安裝了标準單色顯示器、标準鍵盤、一個軟驅、一塊硬碟、16 mb記憶體,在記憶體中開辟了2 mb記憶體作為虛拟盤,并在bios中設定軟驅為啟動裝置。後續所有的講解都以此為基礎。

小貼士

ram(random access memory):随機存取存儲器,常見的記憶體條就是一類ram,其特點是加電狀态下可任意讀、寫,斷電後資訊消失。

問題:在ram中什麼程式也沒有的時候,誰來完成加載軟碟中作業系統的任務呢?

答案是:bios。

1.1.1 bios的啟動原理

在了解bios是如何将作業系統程式加載到記憶體中之前,我們先來了解一下bios程式自身是如何啟動的。從我們使用計算機的經驗得知:要想執行一個程式,必須在視窗中輕按兩下它,或者在指令行界面中輸入相應的執行指令。從計算機底層機制上講,其實是在一個已經運作起來的作業系統的可視化界面或指令行界面中執行一個程式。但是,在開機加電的一瞬間,記憶體中什麼程式也沒有,沒有任何程式在運作,不可能有作業系統,更不可能有作業系統的使用者界面。我們無法人為地執行bios程式,那麼bios程式又是由誰來執行的呢?

秘訣是:0xffff0 !!!

從體系的角度看,不難得出這樣的結論:既然用軟體方法不可能執行bios,就隻能靠硬體方法完成了。

從硬體角度看,intel 80x86系列的cpu可以分别在16位實模式和32位保護模式下運作。為了相容,也為了解決最開始的啟動問題,intel 将所有80x86系列的cpu,包括最新型号的cpu的硬體都設計為加電即進入16位實模式狀态運作。同時,還有一點非常關鍵的是,将cpu硬體邏輯設計為加電瞬間強行将cs的值置為0xf000、ip的值置為0xfff0,這樣cs:ip就指向0xffff0這個位址位置,如圖1-1所示。從圖1-1中可以清楚地看到,0xffff0指向了bios的位址範圍。

ip/eip(instruction pointer):指令指針寄存器,存在于cpu中,記錄将要執行的指令在代碼段内的偏移位址,和cs組合即為将要執行的指令的記憶體位址。實模式為絕對位址,指令指針為16位,即ip;保護模式下為線性位址,指令指針為32位,即eip。

《Linux核心設計的藝術:圖解Linux作業系統架構設計與實作原理》——1.1 啟動BIOS,準備實模式下的中斷向量表和中斷服務程式

cs(code segment register):代碼段寄存器,存在于cpu中,指向cpu目前執行代碼在記憶體中的區域(定義了存放代碼的存儲器的起始位址)。

注意,這是一個純硬體完成的動作!如果此時這個位置沒有可執行代碼,那麼就什麼也不用說了,計算機就此當機。反之,如果這個位置有可執行代碼,計算機将從這裡的代碼開始,沿着後續程式一直執行下去。

bios程式的入口位址恰恰就是0xffff0 ! 也就是說,bios程式的第一條指令就設計在這個位置。

1.1.2 bios 在記憶體中加載中斷向量表和中斷服務程式

bios程式的代碼量并不大,卻非常精深,需要對整個計算機硬體體系結構非常熟悉才能看得明白。要想把bios是如何運作的講清楚,也得寫很厚的一本書,這顯然超出了本書的主題和範圍。我們的主題是作業系統,是以隻把與啟動作業系統有直接關系的部分簡單地講解一下。

bios程式被固化在計算機主機闆上的一塊很小的rom晶片裡。通常不同的主機闆所用的bios也有所不同。就啟動部分而言,各種類型的bios的基本原理大緻相似。為了便于大家了解,我們選用的bios程式隻有8 kb,所占位址段為0xfe000~0xfffff,如圖1-1所示。現在cs:ip已經指向0xffff0這個位置了,這意味着bios開始啟動了。随着bios程式的執行,螢幕上會顯示顯示卡的資訊、記憶體的資訊……說明bios程式在檢測顯示卡、記憶體……這期間,有一項對啟動(boot)作業系統至關重要的工作,那就是bios在記憶體中建立中斷向量表和中斷服務程式。

rom(read only memory):隻讀存儲器。現在通常用閃存晶片做rom。雖然閃存晶片在特定的條件下是可寫的,但在談到主機闆上存儲bios的閃存晶片時,業内人士把它看做rom。rom有一個特性,就是斷電之後仍能儲存資訊,這一點和硬碟類似。

bios程式在記憶體最開始的位置(0x00000)用1 kb的記憶體空間(0x00000~0x003ff)建構中斷向量表,在緊挨着它的位置用256位元組的記憶體空間建構bios資料區(0x00400~0x004ff),并在大約57 kb以後的位置(0x0e05b)加載了8 kb左右的與中斷向量表相應的若幹中斷服務程式。圖1-2中精确地标注了這些位置。

一個容易計算的方法:0x00100是256位元組,0x00400就是4×256位元組 =1024位元組,也就是1 kb。因為是從0x00000開始計算,是以1 kb的高位址端不是0x00400,而是0x00400−1,也就是0x003ff。

《Linux核心設計的藝術:圖解Linux作業系統架構設計與實作原理》——1.1 啟動BIOS,準備實模式下的中斷向量表和中斷服務程式

中斷向量表中有256個中斷向量,每個中斷向量占4位元組,其中兩個位元組是cs的值,兩個位元組是ip的值。每個中斷向量都指向一個具體的中斷服務程式。

下面将詳細講解後續程式是如何利用這些中斷服務程式把系統核心程式從軟碟加載至記憶體的。

int(interrupt):中斷,顧名思義,中途打斷一件正在進行中的事。其最初的意思是:外在的事件打斷正在執行的程式,轉而執行處理這個事件的特定程式,處理結束後,回到被打斷的程式繼續執行。現在,可以先将中斷了解為一種技術手段,在這一點上與c語言的函數調用有些類似。

中斷對作業系統來說是一個意義重大的概念,後面我們還會深入讨論。

繼續閱讀