磁碟相關概念以及知識

weixin_34344677發表於2013-06-27

http://code.riaos.com/?p=5011676

硬碟按照儲存介質分為機械硬碟(HDD)和固硬碟(SSD)

硬碟的資料介面主要分為以下幾種 :

ATA(IDE):從ATA1 到ATA7, 相容性比較好,採用40pin並口資料線

SATA:A他的繼任者,序列的ATA介面,採用4pin的資料線,支援熱插拔

SCSI:小型機系統介面,支援高轉速的硬碟,傳輸時佔用CPU資源較低,有50pin,68pin,80pin多種規格

SAS:序列 SCSI,是由SCSI演化過來的,比SCSI更快並且配置更簡單。
相容SATA裝置,可以使用相同的電纜。SA他的硬碟可以接在SAS介面上使用

硬碟的電源介面

主要和資料匯流排有關,ATA介面的配備的電源介面為D形4針電源介面(大4pin介面),
而與SATA配合的則是5pin的L 型介面, 行動硬碟也可以通過USB介面供電。

硬碟的內部構造

磁頭以及機械臂

由於有多張碟片,現代硬碟一般都有多個磁頭,磁頭也是硬碟中最貴的東西。
早期讀寫磁頭是同一個,而新式的磁阻磁頭(Magnetoresistive heads)將讀寫磁頭分開
(感應寫,磁阻讀,通過阻值變化而不是電流變化去感應訊號幅度),以達到更好的讀寫效能。

控制電機

令碟片高速轉動起來,所有的碟片都固定在主軸上。碟片的轉速甚至可以達到每分鐘上萬轉。
硬碟的轉速也是硬碟的一個重要引數。電器元件:包括一些控制電路以及硬碟的cache。

碟片

碟片一般是用用鋁合金或者玻璃製成的,上面平鋪一層磁性物質。為了節省空間,加大硬碟的容量,
碟片的正反兩面都會被利用起來(但也有隻用1面的)。邏輯上我們會從上到下給每個盤面一個編號,
從0開始。由於每一個盤面都會對應一個磁頭,所以經常也會說0號磁頭,1號磁頭用來表示對應的盤面。

  • 磁軌(TRACK):試想一下,電機開動,磁碟碟片開始狂轉,將磁頭固定好不動,磁頭會劃出一個圓形的軌跡,這個軌跡我們稱之為磁軌。
    有一點需要知道,磁軌並不是緊挨著的。為啥?挨的太緊雖然可能增加碟片磁軌的個數,但是會導致磁化單元間相互干擾影響,
    還有磁頭讀寫定位也比較困難。磁軌從外到內,依次從0開始編號,現代硬碟碟片上有成千上萬的磁軌。

  • 柱面(Cylinder):硬碟有多個盤面, 柱面實際上是多個相同半徑的磁軌集合。
    柱面也和磁軌一樣,由外圈向內,從0開始編號。
    0號柱面是指 0號盤面的0號磁軌 + 1號盤面的0號磁軌 + 2號盤面的0號磁軌 。。。
    磁軌是個平面的概念,柱面是個立體的概念。如果一個磁軌寫滿了之後,接著寫下一個盤面上的相同磁軌
    記住這個規則,硬碟都是先寫完一個柱面再接著寫下一個柱面。

  • 物理扇區(Sector):為了和後面的邏輯扇區做區分,這裡稱之為物理扇區。扇區是磁碟讀寫的最小單位。
    所謂扇區,就是磁軌上的一小段圓弧,扇區上儲存著512位元組的資料塊。

    大家有沒有思考過一個問題,在前面的那些描述中為什麼每磁軌的扇區個數都是一樣的?

    按理說,外圈的圓弧長度大於內圈的,應該能儲存更多的資料才對。最早的PC磁碟,每個磁軌擁有17個扇區,
    由於技術的限制,內圈和外圈扇區個數相同,造成了外圈比較大的空間浪費。
    後來的 zone bit recording 技術解決了這個問題,可以令外圈的磁軌擁有更多的扇區。
    而如今每個磁軌可有有上千個扇區。換句話說,當今的磁碟, 每個磁軌的扇區數是不一樣的。(這句很重要)

    還有一點,扇區是從1開始,而不是0 (邏輯扇區是從0開始的,記住,我們這裡說的是物理扇區!)
    關於為什麼 不從0開始,我查了半天資料也沒找出來,我個人猜想,
    0扇區會不會存放了一些磁軌以及硬碟引數等資訊,硬碟內部使用而不公開呢?

    關於扇區的組成,很多人會認為扇區的大小就是512位元組,其實物理介質上儲存的資料要比512大。 扇區大致由以下3部分組成:

    • 扇區頭:一般含有扇區的地址資訊(後面定址會將到),扇區屬於哪個柱面,哪個磁頭以及扇區的序號。
      硬碟讀取這個扇區資料時,首先比對一個扇區頭的地址和想要讀的地址是否相同。
      另外就是一個標誌,如扇區是否不可用,或者有損壞(寫入或者讀取出錯),
      還有sync標誌(讀取某扇區時,先要看此扇區是否已經寫入完畢)以及
      重定向標誌(標明這個扇區已經損壞,並給出另一個可用的扇區)。
    • 資料區:真正的資料。
    • 糾錯碼(ECC error-correcting code):ECC具體可以參看WIKI。
      硬碟讀取扇區時,首先比對扇區頭的地址資訊,接著讀取資料,計算出ECC,
      比對是否和此處的ECC碼一致,不一致說明資料已經損壞。
      寫的計算好ECC碼,寫入資料,接著將ECC寫入扇區。

    根據上面的描述,大家應該知道,讀寫資料的有可能出現壞道(或者說扇區讀寫錯誤)有兩種原因造成:

    • 邏輯壞道:讀寫資料與ECC碼不一致。(解決方法試著再讀寫幾次)
    • 物理壞道:扇區磁性介質物理損傷。 (無解。一些所謂的修復就是就是在扇區頭加一個重定位標準,讀寫這個扇區時讓磁頭去讀其他扇區)

    這些過程對於磁碟外部來說都是透明的,IDE控制器控制,關於扇區的確切的結構,這與不同的硬碟廠商相關,
    對於很多人來說,明白一個扇區是512位元組就夠了。(你這不是承認自己說了半天廢話,
    看看我硬碟的ECC碼的大小,50位元組呀,也有ECC為40位元組的)

    OK,完了。等下等下。。。既然扇區的結構各家廠商不太一致,那麼,碟片造好的後,
    他們做了什麼操作使磁碟扇區變成他們想要的結構? 對了,低階格式化,
    用低階格式化來劃分磁軌以及扇區結構(請參見本文後半部分).

    等等,前面說了那麼多,

    扇區的大小為什麼是512位元組呢? 這有一些歷史原因,一般物理扇區的大小為512位元組,
    但也有一些不相容IBM PC的硬碟裝置扇區大小為520位元組。現在也有1024位元組,2048位元組,以及4096(4K)位元組一扇區的硬碟。
    2009年12月後,硬碟廠商開始釋出4K扇區的硬碟,他們已經為這事醞釀十多年年了,4K扇區以後應該是主流。

    為什麼會出現4K扇區的硬碟呢?由於人類太過貪婪,要求硬碟容量越來越大。硬碟廠商苦惱著不斷想各種方法提升容量。
    從前面硬碟組成結構可知,提升容量可從下面三個方面入手:

    • 增加盤面的數量 => (親,硬碟就那麼厚,現在連正反面都用上了!)
    • 每個盤面劃分更多的磁軌 => ( 磁軌已經密密麻麻的了,磁軌再多的話,磁頭就不好定址了)
    • 提升磁性物質的密度,以及扇區間的空隙,劃分出更多的扇區。 (現在又有垂直讀寫技術了!)

    我們來看第三點,儲存密度越來越大,新的問題出現了!各個磁性物質間相互影響,造成磁頭讀取時的訊雜比(SNR)不斷下滑,
    換句話說,讀一次,出現錯誤機率增大了。我們知道,ECC就是用來糾錯的,每512位元組的扇區,至少需要40位元組的ECC碼來進行糾錯。
    如果。。。如果每4K的扇區,只需要100位元組呀! 親,趕緊算算: 512 * 8 = 4K => 40 * 8 = 320

    512的扇區4K需要320位元組的ECC,而4K的扇區只需要100位元組,一下子節省了220位元組,好多呀!
    等等,還有更多的驚喜呢!扇區之間還有空隙,沒有利用,使用4K扇區,這些空隙也可以被利用起來!
    請看下圖的對比 !(圖片可恥的copy自西數的某白皮書)

    再問一個問題,為毛是4K,而不是2K,8K? 4K,一個x86系統上神奇的數字。
    從檔案系統層面上來說,磁碟的最小邏輯管理單位,簇 (NTFS)和塊(EXT3) 都是以4K,剛好對映一個物理的扇區。
    而記憶體分頁的大小也是4K,磁碟中一個扇區剛好能讀進一個 記憶體分頁中,非常完美。
    4K扇區,看起來很好,但同樣也引入了一些麻煩。
    *首先產生了相容性問題,因為BIOS,載入程式以及很多作業系統以及應用都認為硬碟物理扇區的大小為512位元組,
    如果以4K為物理扇區,這些東西都要改,這也是為什麼硬碟廠商醞釀了10年多才開始釋出這種硬碟。
    目前為了解決這個問題,硬碟廠商採用了一種模擬的過渡方案,硬碟必須做一些額外的工作。
    以4K物理扇區為例,如果要修改512位元組,硬碟需要先移動磁頭到指定扇區,讀取4K的資料到快取中,
    修改4K中指定的512位元組,然後再寫回去。這種硬碟內部的轉換過程稱之為 “4K with 512-byte emulation”,簡稱512e。
    雖然解決了相容性問題,但又產生了資料不一致以及效能等問題。隨著4K扇區硬碟的推廣,
    目前MS等作業系統廠商已經在作業系統層面開始解決這個問題,硬碟以4K作為讀寫顆粒,作業系統負責處理解決上層問題,
    並使作業系統的引導程式碼能直接使用4K扇區。(參看[這裡](http://http://support.microsoft.com/kb/982018/zh-cn))

    * 再看另一個問題,即使上層以4K進行扇區操作,依然存在一個分割槽對齊的問題,未對齊的分割槽依然會對磁碟的效能產生重大影響。
    假設系統想要讀取硬碟的上4K資料,而這4K前2K在一個扇區的後半部分,後2K在下一個扇區的前半部分。
    如果是讀操作,影響不大,因為磁頭幾乎會連續通過這兩個扇區,直接讀2扇區,然後在快取中丟棄掉沒用的資料即可。
    但是對於寫操作,就需要修改兩個扇區,需要時間較多,造成應能下降。 所以說硬碟技術實際上一直在挖坑,
    512扇區一個大坑,CHS定址一個坑,MBR又是一個坑,總是為了相容折騰。
    (其實我覺得BIOS是個更大的坑,幾十年來一直沒啥變化,一些東西已經影響到了計算機的發展,MS等公司正 折騰著用EFI替換掉它)
    (下圖展示了磁軌扇區以及柱面的相關概念,copy自網際網路)


硬碟的邏輯結構

邏輯扇區

是由系統劃分的,大小為物理扇區的倍數,一般為512位元組。等等,提問!為啥我還聽過簇(cluster)和塊(block)這兩個概念呢?為啥沒講?

其實,簇就是一系列相鄰邏輯扇區的集合,是微軟系檔案系統的概念,如FAT,FAT32,NTFS。
而塊(block)是UNIX系檔案系統的概念,和簇類似,一般是1024位元組。這倆東西后面將具體 檔案系統時再說。

硬碟的定址

對於計算機來說,硬碟就是個黑盒,什麼控制電機了,內部怎麼旋轉了,怎麼定位了,都不想知道。
計算機只希望我給你電源介面供電,給資料介面傳送指令,簡化一下,大概分為2種操作:

  • 讀操作:給資料介面傳送讀訊號,並且給出想要讀取資料塊的位置以及大小。
  • 寫操作:給資料介面傳送寫訊號,給出想要寫入的位置以及寫入的資料,等待硬碟寫入完畢。

好了,問題來了,這個位置如何表示?也就是硬碟的定址問題.
根據定址方式的不同,硬碟也出現了兩種抽象。

  • CHS定址: CHS定址又叫3D定址,比較好理解,對硬碟做簡單的抽象,利用三個數字來定位資料。

    C (Cylinder)代表柱面號, H(Head)代表磁頭號, S代表扇區號(Sector)。
    根據我們前面對磁碟結構的描述, 柱面從0開始,由外向內依次編號。
    磁頭由上到下,從0開始依次編號。
    扇區從1開始編號。
    將硬碟想象成幾個圓形碟片疊落在一起,H可以定位是那個碟片的那一面,
    C可以定位是磁軌,S可以定位是哪一段圓弧。

    CHS三個數字即可完成定址操作。

  • LBA定址:LBA(Logical block addressing)是一種線性定址方式,把硬碟想象成一種線性裝置。
    LBA是比CHS更加高階的一種抽象。大家可以將硬碟想象成一條很長很長的紙帶或者乾脆將硬碟當成一個巨大的檔案,
    每512位元組是一個邏輯扇區。LBA0 代表0扇區,LBA 8765代表第8765個扇區。
    LBA可以理解為是按扇區號進行編碼的,磁碟的0柱面,0磁頭,1扇區編號為0, 2扇區編號為1,以此類推。
    只需要一個LBA號即可完成定位。怎麼樣,相對於CHS更好理解,更簡單吧?
    (注意: 在CHS定址中扇區都是從1開始,而LBA有LBA0,也就是0扇區。)

硬碟的定址的三種模式

在BIOS裡硬碟定址分為三種模式:CHS (NORMAL),LARGE 和LBA。

早期的ATA(IDE)介面的硬碟,是採用22bit的LBA進行定址的,接著1994年,
ATA-1標準定義了2種 硬碟定址方式,28bit的LBA 和 CHS。
CHS採用 16bit表示柱面序號, 4bit表示磁頭序號, 8bit表示 扇區序號

IBM PC開始普及。IBM PC早期是使用軟盤作為儲存裝置的,定址方式是CHS,24bit。
10bit柱面, 8bit 磁頭, 6bit扇區
IBM PC的BIOS中有個很著名的int 13中斷(或者稱之為 系統呼叫吧,可以想象成一個低階函式),
負責讀取寫入和校驗磁碟。int 13中斷就是按照 CHS 24bit這種方式來進行定址的,而且實現還早於ATA-1標準。

當ATA介面的硬碟遭遇IBM PC的時候,問題就來了,不相容,怎麼辦? 只能做對映了。
想一下, A他的 28bit(16:4:8) 怎麼對映成 (10:8:6) ? 最簡單的方式就是將C 和 S的高位捨棄,將H的高位補0。
好了,問題解決。 等等,A他的磁頭當時定標準時為啥用4bit來表示,就不能多點嗎?
親呀, 當時的技術,4bit能表示16個磁頭,相當於16個碟片放在一起,多厚呀(當時 還沒雙面的技術),
8bit 256個磁頭你不覺得有點變態嗎?

讓我們想想現在又出現了什麼問題,A他的CHS 24bit(16:4:8)理論硬碟最大 支援到:

65536 * 16 * 255 * 512 = 127 GB

(注意:512指扇區大小為512位元組, 255是由於扇區都是從1開始,而非0)

大約是127GB,我這裡算的時候1M = 1024KB,和硬碟商的1M = 1000KB略微不同.

再看看IBM的CHS 24bit(10:8:6)的理論值: 1024 * 256 * 63 * 512 = 8GB(8064MB)

當ATA遇見IBM PC的時候,ATA限定了磁頭最多為16個,所以真正的CHS 24bit 理論大小變成了:
1024 * 16 * 63 * 512 = 504MB

啊,就變成這麼點了?我們稱這個模式為Normal(或者None,或者CHS)模式,這個模式下,
最多訪問504MB 的硬碟空間,C,H,S分別表示真正的物理柱面,磁頭和扇區序號。

Normal模式下,有多於的柱面沒有利用上,該怎麼辦呢? 對了,A他的磁頭太少了,我們虛擬一些磁頭即可。
BIOS中引入了Large (或稱為 Bit Shift Translation模式 ),當柱面多於1024的時候,
就進入Large模式,Large模式會對柱面和磁頭做如下轉換:

如果柱面大於1024,就除以2,並且對磁頭數乘以2.

舉個例子:2048柱面,6號磁頭,1號扇區處的資料,直接拿來用(2048,6,1)在BIOS會認為是非法的
(因為柱面數大於1024)在large模式下會對映到 (1024,12, 1),合法!
多餘的柱面對映完成! Large模式下定址空間變成了IBM CHS 24bit的理論值 8GB。

在large模式中,我們已經虛擬了一些不存在的磁頭,這裡的CHS已經不完對應物理裝置了。
(這也是 Normal模式稱之為CHS定址,而Large模式不那麼稱呼的原因了。)

插播一段小八卦,這裡計算容量的時候,磁頭最多有256個(0 – 255),由於MS 的DOS系統所有版本
都有一個bug,如果磁頭有256個,就會引起系統crash….所以磁頭一般序號最大為254, 實際可用的空間 再次減小,MS萬歲!

8G貌似還不夠,而且CHS模式目前遇見了問題,畢竟CHS也無法表述其他的儲存裝置,
如磁帶,網路儲存裝置,SSD, 外加多塊硬碟,磁頭柱面之類的這些裝置根本就不存在,於是引入

LBA定址模式

ATA(IDE)控制器將LBA的地址轉換成具體的實體地址。IDE標準可以使用22bit的LBA, ATA-1擴充套件到28bit, ATA-6再次擴充套件到48bit
2003年,ATA-6已經支援48bit的LBA定址,硬碟最大支援到128PB,已經夠大了。

實際上INT 13H Extensions支援64bit的LBA定址,支援的硬碟大小已經達到目前的天文數字
(MBR最大支援2TB硬碟,所以也要被GPT替換了,後面我們詳細再說吧,技術日新月異呀)。
不過現代的作業系統很多都不使用BIOS中的int 13中斷了(除了在boot loader時),而是直接訪問硬碟。

一般情況BIOS使用的是C/H/S(柱面,磁頭,扇區) 定址,由於硬碟容量增長太快了,由於分割槽表等
一些歷史原因,C/H/S已經無法滿足大分割槽的定址了,現代作業系統都採用的是LBA定址法。

大家明白我前面為啥說CHS又是一個坑了吧?

格式化

  • 低階格式化:如我前面所說,物理扇區是有一定格式組成的,每一塊硬碟出廠前,需要進行“低階格式化”。
    所謂低階格式化,就是將硬碟劃分出磁軌,劃分出物理扇區,使磁碟具有讀寫的能力。
    早期的硬碟,低格是一種物理操作,會影響硬碟的壽命,而現在的硬碟低格已經不再是物理操作,但建議還是不要亂進行低格。
    當你的硬碟的某些扇區因為一些原因丟失了扇區資訊,可以嘗試用低格來重新劃分扇區。
    低格是針對整塊硬碟的,重新劃分磁軌意味著原來的資料將要全部丟失,無法再恢復。
    如果你有塊硬碟要送人又擔心自己的隱私問題,建議對整塊硬碟進行寫0操作而非低格,
    因為據說低格很耗時間,320G的硬碟要20小時。。。(恐怖)

  • 高階格式化:高階格式化是針對某個分割槽進行了,按照你選定的檔案系統格式(如FAT、NTFS 、EXT、HFS+),
    給特定區域寫入特定資訊,將分割槽按照檔案系統定義的格式進行組織。

分割槽

分割槽就是將硬碟劃分成幾個邏輯部分,每一部分稱之為一個分割槽。

為什麼要有分割槽?,原因很多。一個熊孩子的電腦只有一個分割槽,格式化成一種檔案系統,
結果有一天他說教練我還想再安裝一個其他檔案系統,怎麼辦?

分割槽的好處是可以在一個硬碟上安裝多個檔案系統。

  • 每個分割槽存放不同種類的資料,方便邏輯上管理。
  • 一個分割槽如果損壞,不會影響其他分割槽。
  • 作業系統一般都需要安裝在獨立分割槽內,多個分割槽可以安裝多個作業系統。
  • 。。。。。

分割槽的型別:
分割槽分為主分割槽,擴充套件分割槽和邏輯分割槽。 怕大家搞混,我們慢慢來說。
硬碟的0柱面,0磁頭,1扇區稱之為主引導扇區(MBR),系統啟動後,首先讀取的就是這個扇區,
關於MBR的詳細內容,後面有篇幅描述,大家現在只要知道,MBR中含有一個分割槽表,記錄著硬碟上的分割槽。
由於一些歷史原因,分割槽表中的分割槽最多隻能有4個。換句話說,一塊硬碟最多能分4個分割槽。

好像有點少呀,貪婪的人類不滿足了,想要更多的分割槽,最簡單的方法就是擴大MBR的分割槽表!
不行,MBR也是一個坑, 更改了MBR的格式,會引起很多相容性問題。所以人們在不改變MBR結構的前提下,
把分割槽表中的最後一個分割槽加以特殊化,從而擴充套件出更多的分割槽。

分割槽表中的分割槽我們稱之為主分割槽,主分割槽中那個特殊的分割槽,我們稱之為擴充套件分割槽
主分割槽最多有4個,擴充套件分割槽最多有一個。

對於一個磁碟,我們可以這麼分:

  • 1個或 2 個或 3個或4個主分割槽。 <= 不要擴充套件分割槽
  • 1個擴充套件分割槽 <= 不要主分割槽 (沒有主分割槽的硬碟只能當資料盤,是無法引導作業系統的)
  • 1個或2個或3個主分割槽 外加一個擴充套件分割槽

那麼邏輯分割槽又是什麼東西呢? 剛才我們說了,分割槽表中有個特殊的分割槽,稱之為擴充套件分割槽,
我們可以把擴充套件分割槽當成一個容器,再劃分成N個分割槽,這些分割槽,對於MBR來說,不存在,
但對於我們來說,是存在的,這就是邏輯分割槽

簡單的理解就是:

硬碟 = 主分割槽(最多有4個,可以不存在) + 擴充套件分割槽(最多有1個,可以不存在) + 未分配的空間(可以不存在)

擴充套件分割槽 = 邏輯分割槽1 + 邏輯分割槽2 。。。。。

關於主分割槽、擴充套件分割槽和邏輯分割槽我們就先說這麼多,具體的結構在MBR和GPT部分詳細解釋。
下圖展示了 包含2個主分割槽以及1個擴充套件分割槽還有3個邏輯分割槽的硬碟佈局圖:

(空白部分代表間隙。 另外,MBR只佔512位元組,沒有圖中畫的那麼大。。。)

MBR

MBR前面已經提過幾次了(三個坑之一),到底是什麼東西?

MBR,全稱 Master Boot Record,中文一般翻譯為主引導扇區(或者主開機記錄),
MBR位於CHS 0/0/1處,也就是0號柱面0號磁頭的第一個扇區。
MBR是硬碟中首先會被讀入到記憶體中的部分,包含了引導程式碼以及分割槽表,非常非常重要。
MBR與具體的作業系統沒有關係,可以和BIOS配合可以引導硬碟上作業系統。
MBR要是損壞了,只能通過探測式試探來修復。不過MBR存在一些限制,如最大支援2TB的硬碟,
主分割槽不能超過4個,再加上合它一起合作的是30多年也沒什麼變化的BIOS,
MS等廠商早對其不爽,吵著鬧著要用GPT+ EFI 來替換掉它們(下節描述GPT)。

我們先來看看MBR的結構:

  • 446位元組的引導程式碼
  • 64位元組的分割槽表(包含4個專案,每項16位元組)
  • 2位元組的結束標誌(55 AA)

總計512位元組,剛好一個扇區。注意:MBR中的資料都是以小尾(Little-Endian)格式存放的。

虛擬出來的Disk 2的mbr 這是典型的MBR,不過現在的MBR 會在 446位元組的引導程式碼中動一點手腳,
有的是218自己的引導程式碼,外加一些時間資訊,還有的將擴充套件分割槽表寫在了這裡,
不管怎麼樣,64位元組分割槽表的偏移沒有改變。

在詳細研究MBR之前,我們先簡單看看BIOS + MBR系統開機的啟動過程:

  1. 主機板加電,從ROM中讀取BIOS程式碼到記憶體中,並執行BIOS程式,將控制權交給BIOS。

  2. BIOS執行記憶體FFFF:0000H處的跳轉指令,跳轉到BIOS的自檢程式處。

  3. BIOS執行自檢程式,進行自檢(POST:Power On Self Test)。

  4. BIOS列舉裝置,檢查裝置,初始化。

  5. BIOS按照CMOS(可以理解為主機板中的一個儲存區域,使用者可通過BIOS改寫此區域的內容)中設定的引導順序
    搜尋引導裝置(如先搜光碟,再搜第一塊硬碟,第二塊,U盤,網路裝置。這取決於你boot loader的設定)。

  6. BIOS讀取MBR(CHS 0/0/1) 到記憶體0000:7C00H中,執行MBR中的引導程式碼,將控制權交給MBR中的引導程式碼。

  7. BIOS POST程式從記憶體中被清理掉。(但並不是完全被清理,留下了一部分系統呼叫,一直存在服務於系統)。

  8. MBR中的載入程式(簡稱載入程式) 首先會檢查MBR的最後部分是不是55 AA。
    接著掃描分割槽表,看分割槽表是否損壞,然後尋找分割槽表中的活動分割槽,確保活動分割槽只有1個。

  9. MBR載入程式讀取活動分割槽,並執行活動分割槽的程式碼,並將控制權交給VBR中的程式碼,這部分程式碼就是作業系統的引導程式碼。
    這部分與具體的檔案系統有關了,比如FAT在此處讀取VBR,跳過BPB,然後引導系統

是不是腦袋暈暈的? 沒關係,我們對照著MBR的三個部分,來仔細研究下這個過程:

  • 第一部分:446位元組的載入程式

大體上這段引導程式碼進行了如下操作:

  1. 重定位自己,MBR此時已經被載入到記憶體的0000:7C00H,等會這個地方還有其他程式載入。
    所以載入程式首先將自身copy到0000:0600 處。接著跳轉到哪裡繼續執行。

  2. 查詢活動分割槽(具體是檢查分割槽表中活躍標誌位,後面講分割槽表會提到。
    此處就理解檢查MBR偏移0x1be, 0x1ce, 0x1de, 0x1ee的值)。
    沒有活動分割槽或者有多個活動分割槽的直接列印錯誤資訊,並且當機。

  3. 根據分割槽表中的CHS資訊,讀取活動分割槽的第一扇區到0000:7c00H處。

  4. 跳轉到0000:7C00H處,將控制權交給活動分割槽載入程式。

OK,看完此處你一定有些疑問,為毛一個硬碟只能有一個活動分割槽?
作業系統必須裝在活動分割槽上,我要是想裝2個作業系統怎麼辦?
我前面說的那套東西都是標準的MBR載入程式,
你當然可以換成支援多作業系統的MBR,甚至是自己寫程式碼替換MBR中的載入程式,都行。

好了,不糾結了親,我們繼續看下一部分。

  • 第二部分:64位元組分割槽表

這部分為了便於理解,我們對著winhex來看。

我將4個分割槽(最後一個是擴充套件分割槽)分別用顏色標記出來了(開頭的黃色部分是mbr的引導程式碼,
最後面的55 AA是MBR結束標誌,大家請無視)

用DiskGenius檢視一下:

 

分割槽表總大小64位元組,一共4項,每項大家16位元組。這就是為什麼MBR最多隻支援4個主分割槽的原因。

以下是分割槽表每項的結構(我們以第一個分割槽為例,紅色部分):

分割槽狀態(1位元組) => 00表示非活動分割槽, 80表示活動分割槽,其他數字沒什麼意義
(現在明白載入程式怎麼探測活動分割槽了吧?)。我這個硬碟有4個分割槽 全都是非活動分割槽,所以每種顏色開頭都是 00

起始CHS(3位元組) => (02 03 00 ) 3位元組表示分割槽的起始柱面,磁頭以及扇區。

第一個位元組表示磁頭 => 02磁頭 (對照正確!)
第二個位元組的低6位表示扇區 => 03扇區 (對照正確!)
第二位元組的高2位作為高位,第三位元組作為低8位,一個10位表示其實柱面 => 00 柱面(對照正確!)
檔案系統標誌(1位元組) => (0B) 表示分割槽檔案系統的型別。

結束CHS(3位元組) => (A3 3C 01) 結束扇區標示的描述和起始扇區相同

第一位元組表示中止磁頭 => A3 (163) 磁頭 正確!
第二位元組低6位表示扇區 => 3C (00111100) 低6位為 111100 => 60 扇區 正確!
第二位元組高2位作為高位,第三位元組作為低8位 => 01 柱面,正確!
起始LBA (4位元組) => (80 00 00 00) 起始LBA和起始CHS都描述的是扇區的起始地址,只不過起始LBA是以LBA定址模式描述。

此分割槽的起始扇區LBA為0×80 (128),使用winhex的Ctrl + G跳轉到128號邏輯分割槽


winhex順便將LBA轉換成CHS(0,2,3,正確呀,有木有!) 此處已經是FAT檔案系統的VBR。

插嘴一句,關於LBA和CHS之間的轉換,我前面一直沒有提,我覺得沒啥意思,
一是因為CHS定址太過有限,現在基本都是LBA定址,LBA到CHS轉換屬於硬碟和BIOS內部的事情。
有興趣的同學可以google一下。

只看MBR,我們是無法轉換LBA到CHS,因為我們不知道每道扇區數之類的引數。winhex此處之所以能轉換是因為讀取了VBR中的BPB才完成的,後面講FAT檔案系統中VBR的結構會講。但對於BIOS來說,知道CHS就OK了,它只要傳遞給硬碟就能讀出對應扇區的資料。這裡有一個LBA 轉換為CHS的演算法:

LBA 2 CHS

Temp = LBA / (Sectors per Track)

Sector = (LBA % (Sectors per Track)) + 1

Head = Temp % (Number of Heads)

Cylinder = Temp / (Number of Heads)

這裡面需要獲得Sector per Track 和 Number of Heads,也就是每道扇區數。
如何獲得?如果你的檔案系統碰巧是FAT系,在VBR的BPB中正好有這個值,不過可惜的是,
FAT中的這個值基本上都是錯的。對於現代磁碟來說,每個磁軌的扇區數根本就不一樣。
你非要獲得這個值,可以呼叫int13中斷來獲取一個可計算CHS的邏輯值。

int 0×13

引數: AH 0×8

引數: DL driver index <= 第一塊硬碟的id為0×80

結果:DH <= 最後一個磁頭號,換句話說CH內的值 + 1就是磁頭的個數

CX <= 第5位為每道最後一個扇區號,換句話說CX的低5位即為每道扇區數(扇區從1開始)
CH的高5 – 15位(即剩下的部分) 為最後一個柱面號,換句話說此值 + 1就為柱面的個數

PS:這裡所說的都是邏輯上的磁頭個數,扇區個數以及柱面個數,只是為了方便CHS定址,物理上並不對應。
因為每磁軌扇區的個數都不相同。如何根據LBA讀取扇區,CHS讀取扇區,請參看此處

  • 分割槽總扇區數 (4位元組) => (9A 66 00 00) 表示分割槽是由多少個扇區構成 => 0x669A (26266) 個扇區,
    分割槽的大小為(每扇區512(0×200)位元組):
  • 26266 * 0x200byte = 13448192byte = 12.8M 正確!

好了,分割槽表講述完畢,非常簡單吧。我們來思考以下幾個問題。

  1. MBR中分割槽表只佔有4項,所以造成系統最多有4個主分割槽。
  2. 起始和結束的CHS都用3位元組表示,其中10位表示柱面,8位表示磁頭,6位表示扇區,
    所以CHS定址最大為8.4G(前面已經詳細描述過了)
  3. 對於超過8.7G的硬碟,MBR中的CHS已經無法表示了,一般使用 FE FF FF 填充
    (如我disk0的這個分割槽),BIOS會認為這個無效地址,在normal和large模式下無視這個分割槽,
    而在lba模式下讀取分割槽表中的LBA地址從而找到這個分割槽。
    現代一個分割槽,超過8G很正常,所以現代作業系統基本上都使用的是分割槽表中的起始LBA而非起始CHS。

由於起始LBA和分割槽扇區數都使用的4位元組整數來表示,那麼MBR格式一個分割槽最大為
2^32 * 512byte = 2TB 而且每個分割槽的起始地址都應小於2T。

舉個例子,假設你有一個4T的硬碟,第一分割槽的起始LBA為0,大小為2TB,
那麼第二個分割槽起始地址應在2T之後,用4位元組已經無法表示了,所以第二個分割槽將看不見。

不過如果你有3TB的硬碟,第一分割槽如果為1TB,第二個分割槽為2TB,
那麼OK(因為第二個分割槽起始位置小於2T,可以用4位元組表示)
但如果第一個分割槽為2T,那麼第二個分割槽就看不見了。

  • 第三部分:MBR結束標示(2位元組)

原本沒啥說的,但估計你肯定想問為什麼是 55 AA ?其實我也不知道為什麼,我查了挺多資料的,都沒找到原因。
但55 AA絕對不是亂選的,55 二進位制位 0101 0101 , AA二進位制位 1010 1010。
這裡有位和我們一樣疑惑的哥們在stackoverflow上提問,但答案個人覺得有點牽強。

補充,關於MBR的最後一個問題,擴充套件分割槽和邏輯分割槽到底如何表示?

MBR中的分割槽表已經可以描述最多4個主分割槽了,其中一個主分割槽可以作為容器,稱之為擴充套件分割槽,繼續被劃分成N個邏輯分割槽。

MBR中分割槽表已經包含了擴充套件分割槽的LBA,以及總扇區數,根據LBA可以找到擴充套件分割槽的起始扇區,
而這個起始扇區存放了EBR(Extend Boot Record)描述了擴充套件分割槽中的各個邏輯分割槽。

我們可以這麼理解,將擴充套件分割槽當成一塊新的硬碟。這個硬碟的第一個扇區也存在一個MBR類似的的東西。
如果我們依然選擇MBR當這個新硬碟的引導扇區,那麼意味這這個新硬碟還是最多隻能有4個分割槽,
我們想讓新硬碟中的分割槽數無限,MBR中陣列結構的分割槽表已經無法滿足要求,必須要一個連結串列結構的分割槽表。
怎麼辦?我們對MBR中的分割槽表做一點修改,分割槽表表第一項不變,依然描述一個分割槽,
分割槽表的第二項如果如同MBR中的擴充套件分割槽一樣,描述下一個新硬碟。

(下圖展示了MBR,EBR之間的關係)

簡單一點描述就是:

  1. EBR和MBR結構完全相同,EBR中的引導程式碼一般是446位元組的0,EBR分割槽表中的第三項和第四項全為0,沒有使用。
  2. MBR的分割槽表中每項的LBA,要麼指向主分割槽的第一扇區,要麼指向擴充套件分割槽的EBR(EBR就在第一扇區)。
  3. EBR中分割槽表中的第一項指向一個邏輯分割槽的第一扇區,第二項指向下一個EBR (此處的LBA都是相對於EBR的LBA,不是絕對LBA)。
  4. EBR中的第二項為0的話,表明已經沒有下一個邏輯分割槽了。

為了加深理解,我們使用winhex手動定位一下邏輯分割槽.如圖所示,邏輯分割槽為F:I: J:

winhex開啟Disk 2, MBR中的分割槽表如圖:

 

擴充套件分割槽是最後一項,藍色部分,我們只關心擴充套件分割槽起始LBA:
0x967F8 (616440) 以及擴充套件分割槽扇區個數 0×31808。 由此可知擴充套件分割槽大小為:

0×31808 * 512byte = 0×6301000 byte = 99MB (驗證正確!)

使用Ctrl + G 跳轉到LBA 0x967F8 (616440) 處:

如圖所示,這是第一個EBR,我用紅色和綠色標出了分割槽表中的第一項和第二項。

第一項指向第一個邏輯分割槽,LBA 為0x3F(63),一共0xF000個扇區。

第一個邏輯分割槽的大小為: 0xF000 * 512byte = 0x1E00000 byte = 30MB

LBA為 0x3F(63),說明第一個邏輯分割槽的偏移相對於EBR為 0x3F * 512 = 0x7E00
(由於winhex ctrl + g 沒法跳轉到相對LBA,所以這裡我們使用alt + g 跳轉到相對偏移 0x 處)

 

已經看到FAT的VBR了,說明我們找到這個分割槽了! 接著我們再找下一個分割槽,
首先找下一個EBR,相對於第一個EBR的LBA為0xF03F,相對偏移應該為:

0xF03F * 0×200 = 0x1E07E00

alt + g 跳轉後,果然找到EBR!

OK,按照此方法,我們就能找到所有的邏輯分割槽了。

GPT 概要介紹

本來打算詳細介紹下GPT,卻發現此文寫的實在是太長了,只能簡單說說,
由於MBR 2TB以及最多4個主分割槽的的限制,GPT出現,GPT對分割槽數量沒有限制,想多少都行
(網上有個說法說GPT最多支援128個分割槽,這種說法不對。128是windows系統的限制),
GPT支援的磁碟大小為18EB。(目前來說屬於天文數字)關於GPT的更多描述請自行google(GPT我有時間再補完吧)。