要想對C語言有一個深入的了解,就不得不說它賴以生存的環境,這裡簡要介紹一下系統記憶體模型。記憶體模型,就不得不說業界知名的Wintel聯盟,到底是誰選擇了誰?又是誰成就了誰?反正已成事實鬼才知道!
關于IntelX86家族的發展曆史這裡不想贅述,無非就是:字長越來越大(4位 -> 8位 -> 32位 -> 64位);頻率越來越快(30MHz -> 600MHz -> 998MHz -> 2.2GHz);晶片制程越來越先進(900nm -> 600nm -> 300nm -> 90nm -> 32nm -> 28nm);核心越來越多(單核 -> 雙核 -> 四核 -> 八核);指令集越來越多(浮點運算、SSE等)架構越來越新(英文太怪,沒記住);性能越來越高(什麼百萬條指令每秒的)。
學過X86彙編的人,都應該對裡面講到的段位址和段内偏移印象深刻,有沒有想過為什麼Intel的工程師要弄這麼一個“變态”的設計,8086處理器本來就是16位的位址,按理說隻能訪64KB的記憶體,可是我們“聰明”的工程師一定要别出心裁,用兩個16位的位址,組成一個20位的位址,通路1MB的記憶體。因為處理器的設計要考慮向後相容,為老型号處理器設計的程式,要能在新型号處理器上運作才行。因為8085用的是16位位址通路64KB記憶體,為了改動最小,那8086就隻能這麼設計了。但是,這種設計暫時給Intel節省了成本,赢得了市場,可是長遠來看,Intel不得不一次次焦頭爛額的為這一次“聰明”買單。因為既然确立了這個基本的位址模型,後續的80x86處理器不得不延續這種做法,否則就會導緻不相容而失去市場,現實給技術創新帶上了鐐铐!
如果一切到此結束,對技術人員來說或許是最好的結局。但我們總是希望做到“更小、更快、更便宜”,幾十年來摩爾定律一直在指引着我們。我們對記憶體空間的需求越來越強烈,記憶體也越來越大,從80286起Intel提出了虛拟模式(virtual mode)的概念。在虛拟模式中,段寄存器中的值并不與偏移位址相加,而是指向一個存放實際段位址的表,該值是表中實際段位址的索引,這種16位的位址模式也被稱為保護模式(protected mode)。其實剛開始沒有實模式和保護模式的概念,隻是後來我們改變了位址模式的政策,又為了向下相容,就不得不差別對待這兩種模式,好讓兩種模式下的程式都能正常運作。如下圖所示(網絡截圖,懶得畫):

實模式:段寄存器中的16位資料左移4位,變成20位資料,但是低4位是0存儲顆粒度太大,需要加上偏移位址,共同構成有效的20位位址,這就實作了實模式下利用16位位址通路20位資料空間的構想。資料空間一下子由64KB擴大到了1MB,在當時來不得不說是個奇迹,回過頭來看連首歌都存不了呵呵。
實模式優缺點:實模式在當時有效的解決了存儲空間的問題,資源消耗最小,又達到了目的。但随着技術的發展,我們對空間的要求越來越高;而且在實模式下,使用者程序可以随意通路實體記憶體,風險極大,就需要要一個有效的手段來對使用者程序進行限制和監管,就需要有對應每個程序的“監管資訊”,這些資訊如何存儲?在實模式下遇到了困難。
保護模式:相對實模式而言,也是為解決實模式下問題而生。在保護模式下,“段寄存器”中存放的不再是段位址,而是“段選擇符”(是一個“段描述符”的偏移)。1、實模式下無法進行大空間通路(16位大小),那好在保護模式下通過“段描述符”(存在與記憶體中)來存放基位址,段描述符裡面的基位址就沒有16位大小的限制了,空間問題完美解決。2、實模式下無法進行程序監管,監管資訊無處存放,那好在保護模式下,“監管資訊”存放到段描述符中(記憶體中),而且還沒有資訊量大小的限制,當程序通路記憶體時,直接通過段選擇符找到段描述符,就能得出通路基位址(位數不限)和監管資訊(資訊量大小不限)。最後,基位址+偏移就是程序需要的實體記憶體位址。注意:GDT和LDT是全局/局部描述符基位址,這裡可以認為就是一個存儲基位址的寄存器。
保護模式優缺點:完美解決實模式下的空間限制和監管難題,實在想不出有什麼缺點,如果實在要說,那就是需要占用一部分記憶體空間存放這些資訊,而且通路實體記憶體需要多一層資料通路。但是這點性能損失跟它帶來的好處來比,是值得付出的。
思維邏輯探秘:
1、在分析這兩種模式下的差别和指導思想時,忽然發現我在做産品時不就是這麼做的嗎。本來隻負責一款“固定界面顯示”産品的實作,但是公司想要在這個基礎上實作多語言界面顯示,而且内部邏輯不變,隻修改顯示層。可是資料結構都已經做好,如果是一款固定界面,這些顯示層的屬性資訊隻存在于MCU的ROM中即可;如果是多語言界面,那麼這些屬性資訊就要支援動态修改,要存儲到外部Flash中,在ROM内部存儲非常少的各個屬性字段的偏移,初始化時根據偏移調取對應的屬性字段,來實作多語言界面的切換,類似于這裡的實模式和保護模式。
2、如果把整個存取過程比做“資訊鍊”的話,實模式的資訊鍊最短也最高效,但受限于處理器本身字長,擴充能力較弱;而保護模式人為的增加了一層“資訊鍊”,犧牲了一部分效率,卻實作了處理器字長的無關性,想要多少個位元組的位址,完全取決于段描述符的大小,擴充性極大。
3、對于“監管資訊”的存儲,也是同樣的道理,人為增長的“資訊鍊”可以把監管資訊放進來,來對程序權限進行限制。在實模式下,進行如果想操作實體記憶體,隻需要知道段位址和偏移,簡單運算就可以得到位址;在保護模式下,需要根據偏移找到描述符,系統根據描述符裡邊的屬性資訊,決定要不要讓程序得到實體位址,多了一層限制。生活中又何嘗不是如此,管理層的監管層次越多,效率就越低,限制就越嚴格!