1. 程式人生 > >第五章:Mac OS X核心故事之從32位到64位

第五章:Mac OS X核心故事之從32位到64位

第五章:Mac OS X核心故事之從32位到64位
      自從標配4G記憶體的筆記本面市以來,我就非常關心預裝作業系統是32位還是64位的,因為雖然理論上32位Win可以用到4G記憶體,但由於一部分記憶體要給系統和其他硬體裝置預留,使用者可見的記憶體並沒有4G,大概只有2-3.5G的樣子,而64位的windows可以用到3.8G以上(還有一部分應該是集顯佔用了)。不過後來我瞭解到,在目前windows的生態環境下,為了大記憶體而選擇64位系統可能並不明智,因為大量為Win開發的軟體都還停留在32位模式階段,雖然64位win為32位應用程式建立了一個從檔案系統到執行時環境的完全、徹底、獨立的32位模式以達到相容的目的,但這是以犧牲效能為代價的,並且不能徹底解決問題。從檔案系統來說,64位win有兩個Program Files資料夾,一個不帶字尾,就像我們在32位win上看到的一模一樣,用來存放原生的64位APP;另一個帶x86字尾,用來存放32位APP。這個倒還好,根據字尾一目瞭然,詭異的是在C:\Windows資料夾下的三個system資料夾,一個不帶任何字尾(C:\Windows\System)是用來相容更古老的16位APP,這沒問題。第二個是存放64位APP的執行時支援檔案,可資料夾卻被命名為C:\Windows\System32,第三個是存放32位APP的執行時支援檔案,資料夾竟然名為C:\Windows\SysWoW64。在為32位軟體搭建的虛擬執行環境中,包括了虛擬的CPU(執行32位指令集)、虛擬登錄檔、虛擬檔案系統、虛擬記憶體空間,32位軟體完全不會知道自己是在一臺64位架構的電腦上執行(大家在PD模擬器裡跑的Win一樣不知道自己外面還有個Mac OS!),如果它呼叫Win的API來獲得系統資訊,則會被告知電腦的一切都是32位的。32位軟體和外部64位環境的一切聯絡都要先通過這個虛擬環境來中轉(參見這個簡短的英文說明
http://blogs.msdn.com/b/oldnewth ... /12/22/9244582.aspx
,或這個來自MSDN的更詳細的中文說明http://technet.microsoft.com/zh-tw/library/dd180732),從而造成執行效率的損失。在遍地是32位APP的當下,選擇64位Win並不能讓我們充分享受64位的好處。



      理論上來說,64位架構的電腦要比32位架構的電腦速度更快。這裡我不扯很多技術問題,就拿喬幫主當年的一個演示視訊來說明(好訊息,這個視訊youku上就有,不用翻GFW了)。在這個視訊裡,幫主分別用32位模式和64位模式載入一幅美國國會圖書館的照片。這張照片有4G之大,32000*32000約10億畫素。接下來,幫主開始調整兩張照片的亮度,於是CPU就要開始從記憶體讀照片資訊,調整亮度後再返回給記憶體。64位模式可以訪問最多16*1000000TB的記憶體,輕而易舉就可以把4G大小的照片全部讀入記憶體,因此調整亮度過程中發生的只有CPU和記憶體間的資料交換,CPU的佔用率基本保持恆定。而32位模式理論上最多訪問4G記憶體,實際還達不到,只能將圖片資訊分次從硬碟讀入記憶體,因此調整亮度過程中還要發生硬碟和記憶體的資料交換,此時CPU就處於閒置狀態,而當CPU和記憶體交換資料時,CPU又開始忙碌,這導致CPU佔用率持續波動,且渲染速度慢於64位模式。

      要充分利用64位技術的優勢,我們必須有64位的CPU、64位的作業系統和原生的64位APP(當然,還要有大於4G的記憶體,但在這裡記憶體是個很被動的部分,它本身不知道什麼32位、64位的,只是等著別的硬體來使用它。所以我就不提它了),缺一不可。儘管
IBM在1961年就造出了能處理64位二進位制指令的電腦
,但那只是用於超級電腦領域的“王謝堂前燕”,離個人電腦的“尋常百姓家”還有很長的路要飛。在這條路上,Intel錯失先機,他們忙著與HP合作搞64位的伺服器CPU,這個名為Itanium的CPU系列與Intel在PC上的x86CPU不相容,結果AMD搶先推出與x86架構相容的x86-64,後改稱AMD64(http://tech.sina.com.cn/h/2007-12-05/10581893688.shtml)。由於Wintel聯盟的存在,Intel不出PC用的64位CPU,廣大Wintel使用者就只能乾等。結果又被IBM-APPLE搶先發布世界上第一臺64位個人電腦——PowerMac G5。到了2004年,Intel開始在其Prescott系列CPU上使用x86-64技術(其實就是照抄AMD的),並在酷睿系列釋出後改名為Intel64,我們現在用的Intel CPU也都是基於它的(
http://tech.sina.com.cn/h/2007-12-05/10581893691.shtml
)。這裡順帶一提,x86-64是一個向下相容16位和32位APP的技術,並非真正的64位架構,這個相容貨的出現也是Wintel聯盟獨霸PC市場的必然結果,巨大的市場份額使得AMD和Intel不可能完全拋棄x86使用者另起爐灶。而完全不相容x86的Itanium是一個純粹的64位架構,只是相容性問題阻礙了它邁入PC的腳步。

這是2005年升級版的powermacg5機箱內部,可以搭載兩個PowerPC G5處理器


處理器64位化之後,作業系統和APP也要跟上。Win在這裡犯了難,因為它的市場實在太龐大了,無數的PC廠商和軟體開發者圍繞在它身邊,牽一髮而動全身。微軟做了兩件事。一是搞32、64兩種版本的windows,二是他們在64位Win中搞出了第一段中所描述的32位相容模式。但這32位相容模式也不是萬能的,比如64位win中的IE就還是32位的,因為Win不允許一個應用程式中同時出現32位和64位的程式碼,為IE開發的一些外掛仍然是32位的,沒法和64位IE混合執行。還有驅動程式,必須和底層硬體直接打交道,也沒法在32位相容模式中執行。不過,一般的APP在32位相容模式下是沒有什麼大問題的,有龐大的使用者群拖著,又這麼個32位相容模式慣著,Win平臺向64位的轉變肯定是一個漫長的過程。而蘋果的64位化之路較win來說就輕鬆多了。一是使用者少,震動小;二是產品線單一,一人吃飽全家不餓。三是蘋果採用了Universal Binary技術。第四章中我曾經提到過該技術,現在再來舉例子詳細說一下,這個例子參考了http://techsingular.net/?p=480

      假設一個APP由一個可執行檔案(二進位制程式碼組成,受32or64位體系的影響)和一個純文字格式的資料檔案(平臺無關,不受32or64位影響)構成。現在我們考慮將OS從32位遷移到64位。第一種辦法就是在64位OS中弄一個模擬器跑32位程式,就像64位win那樣。Mac OS X在向Intel平臺遷移過程中也用過一個模擬器叫Rosetta(見第四章)。模擬器的優點就是程式完全不用改動,完全沒有冗餘程式碼,代價就是執行起來速度慢。第二種辦法就是對32位和64位系統分別提供一套軟體,每套軟體都由兩個檔案組成(可執行檔案+資料)。這種辦法在APP執行上沒有效率損失,但軟體使用者要根據自己的電腦配置買不同版本的軟體,不夠傻瓜,如果他們同時擁有兩個平臺的電腦,那麼就要買2份軟體,其中的資料檔案部分完全相同,這就造成了重複。第三種辦法是隻針對不同平臺製作不同的可執行檔案,而共享同一份平臺無關的資料檔案。這種方式大大減少了冗餘,但是要求APP的安裝程式要智慧,根據不同平臺安裝不同版本的可執行檔案。對於使用者來說,由於不同APP實現智慧安裝的方式不同,每裝一個新軟體都要再去熟悉這個軟體的安裝特點,而且在不同平臺上裝的軟體版本仍然不同,無法互相copy,無法實現Mac OS經典的單檔案APP。在Mac OS X中,大多數應用程式呈現在使用者面前的都只有一個檔案。如果你在APP上點右鍵,選擇“顯示包內容”就可以看到其複雜的內部結構,這種方式類似於電腦科學中的“抽象”,它的目的是對無關人員隱藏具體的實現細節。

單檔案APP

顯示包內容


      第四種方式就是Universal Binary。它在任何平臺上都只安裝2個檔案,即可執行檔案+資料,但是在可執行檔案中同時包含32位和64位的程式碼,作業系統根據需要呼叫不同程式碼。這種方式既方便開發者也方便使用者。蘋果從Xcode2.1開始提供編譯成Universal Binary的功能,開發者可以參閱Universal Binary Programming Guidelines。當然,也不是所有程式用Xcode這麼輕鬆編譯一下就ok了。根據Universal Binary Programming Guidelines,如果一個程式利用的基本上是GUI層的功能,那麼編譯一下就差不多OK了。但如果程式大量利用了系統底層的功能,那麼對不起,你的麻煩大了。比如Office for mac直到2008年才支援Universal Binary。使用者就更輕鬆了,他們完全不用知道軟體內部發生了什麼變化,跟原來一樣買、一樣裝、一樣用就可以了。當然了,這種方式也有缺點,比如我用64位系統,但安裝好的軟體中依然包含32位程式碼,這對我來說是多餘的。同樣,一個32位系統的使用者會發現安裝好的軟體中有他不需要的64位程式碼。

      安撫了開發者和消費者,蘋果就要全力完成作業系統的64位化了,和轉向Intel平臺相比,這一步蘋果走得依然不痛苦,但卻漫長,它花了蘋果6年時間。

      Mac OS X64位化的第一步就是剛才提到過的PowerMac G5,隨同G5發售的Mac OS X Panther(10.3)核心開始支援64位運算,核心能夠訪問64位記憶體地址,但普通APP依然只能看到32位記憶體空間(參見:Mac OS X背後的故事 九(上))。

      2005年釋出的10.4 Tiger引入了64位指標,讓每一個APP執行的程序都可以訪問64位記憶體地址。同時,Tiger開啟了第一個64位的程式設計支援,這就是Unix層的libSystem庫的64位化,這個庫包含了檔案I/O、網路等基礎功能,基本上可以讓開發者編寫64位的非GUI程式了。但是GUI程式設計仍然只能在32位下進行(http://arstechnica.com/apple/2005/04/macosx-10-4/4/)。當然,對於當時的大多數程式來說,64位化的需求並不迫切,誰會沒事寫個64位的通訊錄程式呢,難道你認識全地球的人?但如果是Matlab、Maple這種科學計算程式,那就麻煩了,GUI介面是32位寫的,為了計算的速度和精度又必須去和底層的64位庫打交道。2005年也是蘋果宣佈轉向Intel的年份(參見第四章),幫助開發者和使用者平穩過渡的Universal Binary正式登場,並於2006年開始內置於執行在Intel CPU的Tiger中。Intel CPU的到來倒是給了Mac開發者投奔64位世界一個很好的理由。簡單來說,64位Intel CPU不但能處理64位指令,而且其中能處理64位指令的元器件數量也比32位CPU多(用專業術語來說,64位Intel CPU的暫存器是64位的,而且暫存器數量也比32位 CPU多)。

      2007年,姍姍來遲的10.5 Leopard將GUI APP帶入了64位。同時,非GUI層的全部程式設計庫也完成了64位遷移(Mac OS X背後的故事 九(上))。當然,對32位的支援仍然保留。隨著GUI層的64位化,蘋果也開始向另一個歷史遺留問題開刀,那就是為了向下相容Mac OS 9而建立的Carbon程式設計支援庫。HIToolBox是Carbon中為C語言寫的GUI庫,2006年WWDC大會上,蘋果指出HIToolBox將和Mac OS X原生的GUI庫Cocoa整合http://origin.arstechnica.com/re ... a/carbon-future.mp3,而在2007年的WWDC大會上蘋果宣佈Carbon的整個GUI部分都將不會進入64位時代,Carbon被徹底判了死刑,所以Leopard中只有Cocoa寫的GUI可以是64位的。一石激起千層浪,圍繞Carbon的存廢也有些故事,我會留待本系列的GUI篇和開發工具篇時再講。
      Leopard之後,Mac OS X離64位化只有一步之遙:核心的徹底64位化。這個任務由2009年釋出的10.6 Snow Leopard來完成,它也是我接觸的第一個Mac OS X版本。為了照顧那些還停留在32位時代的驅動程式,SL預設以32位模式的核心啟動,如果你想切換到64位模式,可以在電腦啟動時同時按住6和4兩個鍵。這個版本很有趣,它的前輩Leopard有300項新功能:


而它卻沒有任何新功能:


儘管如此,它肩負的使命卻十分重大。另外,SL還徹底與PowerPC決裂,只有執行在Intel CPU上的蘋果電腦才能裝它(我是說正常情況下,對Geek來說不是問題)


      10.7 Lion和10.8 Mountain Lion在32位到64位的轉變中就沒那麼重要了,他們只不過是在主要的第三方開發者都已經做好準備的情況下,對32位程式關上最後的大門。Lion的核心預設以64位啟動,而ML則在核心中徹底移除了對32位程式的支援(10.8的XNU程式碼還沒有放出來,我不知道ML的XNU版本號是多少),所以那些早期依然有32位驅動程式的蘋果電腦就被排斥在ML的支援升級範圍之列,不過這難不倒Geek們,他們仍然有辦法在老電腦上安裝ML。不知道有沒有童鞋嘗試過併成功了呢?不過,即使這種方法能裝好ML,估計也沒法執行,因為核心中已經沒有任何32位程式碼了。