相關閱讀 |
>>> 技術話題—商業文明的嶄新時代 >>> | 簡體 傳統 |
http://www.douban.com/group/topic/23658084/
我在國內的《程序員》雜誌上發表系列連載,介紹Mac OS X開發的過程。望各位持續關注。
往期:
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
http://www.programme
有任何感想和建議請去程序員網站留言。您的支持是我把這個長達三十六期連載寫完的動力:)
現在已寫完但並沒有公佈的8期有:
Mac OS X 背後的故事 (十六)﹣﹣向 Intel 遷移!(下)
他們改變了你的數字閱讀體驗 (兼 Mac OS X 背後的故事 (十七﹣二十二)﹣﹣ Charles Bigelow、Kris Holmes獨家採訪)
當公佈時,會給出鏈接。也希望大家多去《程序員》網站支持這個系列
作者王越,美國賓夕法尼亞大學計算機系研究生,中國著名 TeX 開發者,非著名 OpenFOAM 開發者。
Mac OS X 背后的故事(一)力挽狂瀾的Ellen Hancock
Mac OS X 背后的故事(二)Linus Torvalds的短視
Mac OS X 背后的故事(三)Mach之父Avie Tevanian
Mac OS X 背后的故事(四)政客的跨界
Mac OS X 背后的故事(五)Jean-Marie Hullot的Interface Builder神話
Mac OS X 背后的故事(六)上善若水
Mac OS X 背后的故事(七)上善若水下——Cordell Ratzlaff 引發的 Aqua 革命
Mac OS X 背后的故事(八)三好學生Chris Lattner的LLVM編譯工具鏈
Mac OS X 背后的故事(九)半導體的豐收
Mac OS X背后的故事(十)Mac OS X文件系統的來龍去脈
Ellen Hancock曾任蘋果公司技術總監
Mac OS X 背后的故事(一)力挽狂瀾的 Ellen Hancock
故事還得從 20 世紀 90 年代說起。Ellen Hancock 是本文的主人公,也是一位女英雄。她因在 IBM 的經歷而被人們所熟悉。1966-1995 年間,Ellen Hancock 在 IBM 共工作了 29 年。1985 年,她成為 IBM 的副主席。在 1986-1988 年間,Ellen Hancock 担任過 IBM 通信產品的主席,并在 1992 年被選為資深副總裁。1995 年 9 月,她被時任美國國家半導體(National Semiconductor)CEO的 Gil Amelio 忽悠,跳槽來到這個企業,做執行副總裁。她在這里帶領團隊完成了 CompactRISC 架構,這個架構事后成為 ARM7 系列的前身。很多人早已經把她忘了,也很少有人能夠在回憶時將她和 Mac OS X 聯系起來。但事實上,她是讓蘋果放棄 Copland 轉而購買 NeXT 的關鍵人物。
早在 1994 年,Gil Amelio 就找好了下家 Apple,成為 Apple 董事會的成員。1997 年 2 月,Gil Amelio 從 National Semiconductor 辭職,并成為 Apple 的 CEO。為了緊跟老板的召喚,Ellen Hancock 再次被忽悠,來到了當時危機四伏的 Apple。這時是 1996 年 5 月,為什么是危機四伏呢?還得從早先的事情說起。
20 世紀 80 年代,賣可樂的 John Sculley 成為 Apple 的 CEO,隨之 Steve Jobs 被轟出Apple。畢竟可樂和計算機不是一回事,因此不管是硬件還是 Mac OS,整個公司的開發項目越來越受阻。而且由于先天的不足,Mac OS 從誕生之初就不具有一個現代操作系統所應有的特性。所以,在 1987 年,開發下一代操作系統的計劃呼之欲出。具體的規劃是,把新的系統所需要的功能,寫在一堆卡片上。短期可實現的目標,比如增加顏色支持(當時計算機仍是黑白的),寫在藍色的卡片上;長期的目標,比如多任務功能,寫在粉色的卡片上;而在可預見的未來都無法實現的長期的目標,比如加一個純物件導向的文件系統,就寫在紅色的卡片上。在這樣的思路下,Mac OS 的開發團隊馬上就被分成兩個組,一個叫藍組,目標是在 1991 年,發布一個關于 Mac OS 的更新版本;另一個叫粉組,和藍組同時工作,計劃在 1993 年,發布一個全新的操作系統。
1991 年 5 月 13 日,藍組順利按時完成開發任務,發布了 Mac OS 7(一般被稱為 System 7),而粉組卻沒做出什么有實際用途的東西來,因此接連跳票。而且,由于 Mac OS 7 的發布缺乏人手,為了保持正常發布,常常需要從粉組抽調人員參加藍組的開發,再加上 Apple 當時把重心放在了和 IBM 等公司的合作上(Taligent 項目)而不是在粉組上,最終導致了粉組項目夭折。而本來 Apple 指望和 IBM 合作的Taligent 項目能開發出一個可用的新系統,但后來 IBM 不跟 Apple 繼續玩了,因而 Taligent 的果子又吃不到,Apple 相當郁悶。這時由于 Mac OS 有先天不足(單任務,沒有內存保護),再加上 Apple 以及第三方軟件的無限量增加(在這段時期,單 Apple 自己就已經加入了 QuickDraw、PowerTalk、QuickTime 等軟件和技術,每一個都比 Mac OS 本身來得大),Mac OS 的問題終于大爆發。上個世紀 90 年代,Mac OS 給人的印象就是很不穩定、經常崩潰,同 Windows 95 留給 PC 用戶的印象差不多,甚至更甚。
Taligent 項目掛掉后,Apple 自己嘗試過十多個不同的內部項目,但大多沒做多久就夭折了。而這時正是 Windows NT 走向成熟的關鍵時期。眼看著日子逐漸變得不好過了,Apple 開始重新開始考慮建立下一代操作系統的事情。1994年,Mac OS 7.5(Mozart)發布后,Apple 推出新規劃,建立一個全新的操作系統,以 Copland 命名(紀念 Aaron Copland,Mac OS 的發布以音樂家名字命名,和 Mac OS X 后使用貓科動物名字很不一樣),這個項目將有一個全新的內核,具有類似 Windows NT 內核的所有高級特性,而老的軟件都當作獨立的進程模擬運行。這個項目時間緊、任務重,1995 年 3 月公布計劃,預期 1996 年發布。而 Copland 后的版本 Gershwin(紀念 George Gershwin),預計 1997 年發布,將重寫 Mac 的所有系統主要部件,以適合新內核的各種特性。
Copland 將使用微內核技術,只做任務和內存分配。除此之外的所有功能,比如文件系統、硬件驅動等作為微內核上的服務運行。而 Mac OS 的所有用戶界面功能將成為一個獨立的框架,稱為藍盒(Blue Box,今后介紹 Mac OS X 時,我們還會遇到這個詞)。所有的任務相互獨立,占用獨立內存,也可以用 IPC 相互交流。學過操作系統的人都知道,微內核是當時的一個熱詞,一個系統只有被稱為微內核才可被看作是先進的,當時還有針對 Linux 系統的著名的 Tanenbaum-Torvalds 筆戰。但事實證明,所有本來想做成微內核系統的成功項目都放棄了原先的設計(包括 NeXTSTEP、Windows NT),因為這種類似 Mach 微內核的系統往往難產,GNU/Mach + Hurd 之類的項目做到現在經過了20年,仍未成事,一年內搞一個微內核系統談何容易。
微內核還沒搞成,Apple 幾乎所有開發組的成員都來添亂。大家都說自己做的東西很重要,一定要加入 Copland 開發組,所以 QuickDraw GX、OpenDoc 之類的開發組產品成為新系統的核心組件,甚至類似用戶界面皮膚之類的開發組都來湊熱鬧,馬上就使 Copland 成為一個無法維護的項目。開出的計劃越來越長,項目越來越多,但相關進展越來越少,完成速度越來越慢。即便做出了產品,連測試人手都不夠。1995 年就有工程師指出,在 1996 年發布 Copland 純粹是幻想,能 1997 年發布就不錯了。
1996年,Gil Amelio 已經掌權。在蘋果電腦全球研發者大會上他開心地宣布,傳說中的 Copland,也就是 System 8 的開發版會在當年夏天發布,而正式版在秋天就可以送到每位用戶手上。時任 TidBITs 編輯的 Matt Neuburg 有幸見到了這個傳說中的系統。令他大吃一驚的是,這個系統在當時只能打開或關閉文件,而無法對文本文件進行編輯,甚至所有用戶界面的文本框都不能輸字。哪怕什么都沒做,整個系統也會隨機崩潰,而崩潰甚至會造成文件系統損壞。參加演示的蘋果員工,則需要不斷守在旁邊,他們的工作是不斷地格式化已崩潰的計算機磁盤,然后重裝系統。那年夏天,第零個測試版送到一小簇不明真相的開發者手中,把那些脆弱的沒見過世面的人嚇得半死。就連 Apple 內部都開玩笑說 Copland 的正式發布日期可能得推遲到 2030 年。
Gil Amelio 心急如焚,希望 Copland 快點走到正道上來。作為 Gil Amelio 永遠的好朋友,Ellen Hancock 就在這個亂糟糟的時候來到了 Apple。她的職務,正是担任這個亂糟糟項目的負責人。她親自下訪各小組體察民情,了解情況。畢竟在 IBM 干了近三十年,她依靠自己過人的判斷力在 2~3 個月內便得出結論,Copland 這個項目是沒有指望的,就按目前 Apple 這樣的狀態,Copland 永遠都不可能發布,還不如早點取消了好。在短期內,先把 Copland 中的一些有用的成果一點點合并到老的 Mac OS 中,并且抓緊從外部購買一個全新系統來滿足 Apple 的需要。正是她的這個結論,結束了 Apple 長達五年的糾結,使公司重新走向正軌。整個 PC 的黃金時代已經過去,Apple 想要翻身,還有很長一段路要走。Gil Amelio 支持了 Ellen Hancock 的計劃。1996 年 8 月,Apple 取消 Copland 項目。開發預覽版的 CD 封套都已制完,每個郵包上的地址都已打印就續,而 CD 卻從未曾制出。
1996-1998 年是 Apple 最混亂的幾年。在商業上,有一陣曾傳出 Apple 要被 Sun 收購的消息。更有意思的是,《連線》雜志在 1997 年的六月還發表了一篇文章,名為《101 種拯救 Apple 的方法》,其中一條說最好的方式是 Apple 讓自己被 Motorola 買下,成為 Motorola 的一個部門,做 PowerPC 系列產品。以當時的眼光來看這些建議非常諷刺好笑,以今天的眼光看更為好笑。而 Ellen Hancock 在這段時間內的出色工作,成功地挽救了 Apple。
首先,Ellen Hancock 的對內政策是繼續 Mac OS 7.5 的開發工作,一步步把 Copland 中的技術并到 7.5 中。同時,也大量購買第三方的系統增強包,包括插件管理工具、層次化菜單等技術。Apple 把它們買過來,整合到現有的系統中。整個老系統在新系統尚未完成的時候不斷更新,至 2000 年已出到 9.0 版,盡可能地留住了老用戶。并且,前面提到的藍盒(Blue Box)也作為后來新 Mac OS X 系統的一部分,支持用戶運行經典 Mac OS 的程序。
而對外政策更是一個大手筆。Ellen Hancock 協助 Gil Amelio 在 Apple 之外找尋操作系統技術。在 IBM 和 Microsoft 合作 Big Blue 的經驗告訴她,購買一個操作系統的使用權問題多多,最好的計劃是整個一并買下來。因此,Gil Amelio 開始和當時看好的 Be 談,卻因價格問題沒有成功,最終轉而收購了 NeXT。而 Apple 合并 NeXT 后,NeXTSTEP 就演化為 Rhapsody,并最終成為 Mac OS X。這些事情我們今后會詳細再談。
買完 NeXT 后,Steve Jobs 執政,Gil Amelio 因任 CEO 期間 Apple 虧損嚴重而被炒。Steve Jobs 把信得過的人(很多是前 NeXT 員工)拉拢到周圍,開始新政,而同 Gil Amelio 有關的 Ellen Hancock 則在人事變動中被疏遠。Steve Jobs 甚至在很多場合稱她為“笨蛋”。Ellen Hancock 最終于 1998 年主動辭職。事后同 Gil Amelio 以及 Apple 的創始人之一 Steve Wozniak 一同創業,但始終不景氣,她的輝煌時代已經過去。
Gil Amelio 總結他在 Apple 時期的工作時說:“Apple 是一艘底部有洞漏水的船,而我的工作是把這船引向正道。”(Apple is like a ship with a hole in a bottom, leaking water, and my job is to get this ship pointed in the right direction. )Ellen Hancock 雖然同 Gil Amelio 一樣,不知如何去堵這個漏水的洞,但正是由于她在 Apple 的出色表現,不但把船引到了正道上,還找來了有能力堵這個洞的人。
Mac OS X 背后的故事(二)——Linus Torvalds的短視
本文主要的故事來源是 Linus Torvalds 的自傳《Just for Fun: The Story of an Accidental Revolutionary》。
Steve Jobs對Mac OS X的考慮
1997 年,Steve Jobs 回歸,開發下一代操作系統的工作被提上日程。此刻的時代背景是像 Linux 這樣的開源軟件大行其道。隨著網絡的發展,使得像 Red Hat、VA Linux 之類的企業成為爆發戶,把泡沫越吹越大。Steve Jobs 承認 Linux 的好處,甚至在若干年后介紹 Mac OS X 底層的 Darwin 時還不忘在幻燈片上寫道:Darwin 是類似 Linux 的系統。而當時精明的 Steve Jobs 在考慮下面幾個問題。
第一,NeXTSTEP 的內核和外圍工具中,BSD 代碼維護起來需要大量人力,而且各分支的 BSD 發展顯然不如 Linux 快。很多功能都沒有,需要 Apple 自己做。
第二,像 Apple 這樣的小公司,需要借力打力。Apple 的主要競爭對手是 Microsoft,而開源軟件的矛頭也是 Microsoft,如果聯合起來干革命,不但能讓自己得到一個好名聲(Apple 事后一直自稱是最大的開源軟件公司),也可以獲得可觀利益,從而對 Microsoft 造成壓力。
第三,也是最重要的,聯合各開源組織能夠推動 Mac OS 的發展。畢竟開源軟件中像 GCC 之類都是很成熟的項目,Apple 用起來省時省力,投點錢就有大效益,多好。
所以,把 Linux 內核作為 Mac OS X 的重要組成部分的想法被這位偉大的智者想了出來。Apple 之前也有開發 Linux 的經驗,比如在 Steve Jobs 回歸之前,Apple 就和 OSF 合作開始把 Mach 內核移植到 PowerPC 上(Apple 是最大的 PowerPC 玩家,而 OSF 是最大的 Mach 玩家),并把 Linux 作為服務跑在 Mach 上。這個系統就是 MkLinux,我們在后續的連載中還會提到這個系統,因為它不但對 Linux 的移植性作出了重要的貢獻,也對后來的 Mac OS X 的 XNU 內核技術起到了相當重要的作用。
如果可以采用 Linux 作為系統重要組成部分,并且這個構想能夠取得在開源軟件界呼風喚雨的 Linus Torvalds 的認同,就能靠他在社區鼓動一大群開發者皈依 Apple 麾下,這是 Apple 很想看到的給力結局。有了這個指導思想,他便讓秘書給 Linux 的開發者 Linus Torvalds 發了一個郵件,問他是不是有一到兩小時的時間和 Steve Jobs 會面。不明真相的 Linus Torvalds 收到郵件后相當高興,因為這是他第一次有機會去硅谷觀摩。
無果而終的會面
Apple 總部 Infinity Loop 終于迎來了這位稀客,Steve Jobs 親自接見,而先前任 NeXT 技術總監的 Avie Tevanian(這人的故事我們今后會提到)也參加了這次會談。不用多說,這次討論的內容自然是還處于未知狀態的 Mac OS X。討論算不上正式,但 Linus Torvalds 的憤青個性,卻讓談判陷入僵局。
Steve Jobs 自然搬出他 1997 年回歸之際在 MacWorld 講話時的那套理論,Apple 雖然很頹,但骨子里是個牛逼的公司。全世界桌面領域的真正玩家就兩個,一個是 Apple,另一個是 Microsoft,兩者加起來,構成百分之百的桌面用戶群。所以,Linus 同學,你就從了我們吧,如果你從了我們,讓我們把 Mac 架在 Linux 上,一大批桌面用戶就是 Linux 用戶啦,前景可是一片大好!
而 Linus Torvalds 那時候牛啊,諸多大公司如 IBM、Red Hat 都圍著他轉。他可是企業家中的大紅人,像 Apple 這樣的企業根本就不在他眼里。作為一個開源軟件的革命家,在他的想象中 Linux 的潛在用戶應該比 Apple 還多。他始終相信,按照目前開源軟件的發展態勢,自己很快就能在桌面領域分到一杯羹。而且這個命題在他這種古怪性格下的直接推論是,即使我能占領桌面領域,我也要擺出一副不在乎這個領域的態度來。所以實際上 Steve Jobs 的開場白一開始就失敗了。
接著,Avie Tevanian 向 Linus Torvalds 介紹了整個計劃。他們想把 Mach 和 Linux 內核合并起來作為 Mac OS X 的基礎,我估計 Linus Torvalds 是聽錯了(因為 Avie Tevanian 很早就意識到相比于微內核,混合內核有明顯優勢),他以為 Apple 想把 Linux 作為 Mach 的一個服務來跑(當然我個人認為,即使是合并 Mach 和 Linux 成為混合內核,依 Linus Torvalds 的憤青性格,依然是不可能接受的),這正讓他回想到先前和 Tanenbaum 教授的筆戰。并且,他也知道 Apple 和 IBM 合搞的失敗項目 Taligent 正是用 Mach 的。
Linus Torvalds 對于微內核有他自己的看法,之前也曾在不同的地方表述過。若把關于微內核的筆戰去掉限制級敏感詞的話可概括成兩方面。一方面,設計一個微內核和相關的服務,可能造成各種設計上的災難。GNU/Hurd 早在八十年代末就考慮嘗試在 Mach 上寫一系列 Unix 的服務層,結果他們始終無法搞明白到底是讓這些服務先發消息到另幾個服務呢,還是考慮其他方案。所以直到 2011 年我寫這篇文章時,Hurd 項目依然處于半死不活的狀態。而另一方面,微內核的效率無法和傳統內核相比,最簡單的系統調用會涉及一系列底層服務的互相通信。所以很多研究者著手研究如何把微內核的效率提上去,結果就導致微內核變得更加復雜。能提高微內核效率的很多研究成果都已在 Mach 項目中實現了。而在 Linus Torvalds 看來這恰使 Mach 成為了一個非常復雜的項目,并且效率也不怎么高。
會談時坐一旁的 Avie Tevanian 事實上是 Mach 最早的開發者之一,他熱情地給 Linus 講述 Mac OS X 系統藍圖。而 Linus 實際上早就不耐煩了。比如,Mac OS X 中,有一個模擬層,可讓用戶使用經典的 Mac OS 程序。這個技術極類似于現在跑在 Unix 系統上執行 Windows 程序的 Wine 。Apple 當時的考慮是這樣,因為老的 Mac OS 在設計 API 時,就沒有考慮到類似內存保護之類的問題,所以這層 API 必須廢掉,Mac OS X 中所有的新程序必須采用 NeXT 的那套更先進的 API(根據我的考證,當時還沒有 Carbon 這樣的想法,而且事實上 Carbon 不管在 API 還是 ABI 上都和經典 Mac OS 不兼容)。而短期內已有的軟件又不可能快速重寫遷移至 Mac OS X。所以,如果用戶需要使用老版 Mac OS 的第三方應用程序,就可以使用 Apple 提供的這個兼容層。但是由于剛才提到的原因,老版程序并不享受新版程序的待遇,因為模擬器本身運行多個老 Mac OS 任務時,和原先老版 Mac OS 一樣,實際上只有一個進程,沒有內存保護。這樣做的好處是明顯的,因為一方面老的程序在 Mac OS X 發布之初還能用,另一方面 Apple 又和老技術劃清了界限,逼著開發者使用新技術,技術方面的原因是最重要的。但這個看似很正確的技術在 Linus Torvalds 看來是古怪的,他想當然地認為,完全可以運行多個不同的模擬器進程,來執行不同的任務,使得每個任務都可以享受內存保護。這種浪漫主義情調讓他無比鄙視 Apple 員工的智商。而事后當筆者使用早期版本的 Mac OS X 時,發現 Linus Torvalds 的想法完全是不切實際的。因為這個模擬層本來就要占用不少的內存和 CPU,在處理器速度不及今日手機、內存無比精貴的 90 年代末,跑一堆模擬器進程無異于是和自己過不去。
Steve Jobs 考慮到 Linus Torvalds 是開源軟件的領軍人物,便繼續以開源為話題,動之以情,曉之以理。他告訴 Linus Torvalds,我們這個系統做出來后呢,所有的 Unix 層(非圖形界面層),都會開源,所以事實上你加入我們,也是在給開源做貢獻啊!而由于在開源圈子混久了,Linus Torvalds 對此絲亳不領情,他認為,有誰會想用一個底層是開源而圖形界面是不開源的系統呢?所以,像筆者這樣的用戶被“代表”了。
Mac OS X 與 Linux 分道揚鑣
總之,這次會面完全談崩,兩人站在不同的角度去看問題,加上 Steve Jobs 和 Linus Torvalds 都是個性鮮明、唯我獨尊的人,技術和商業上的考慮都不同,所以會談中雙方簡直就是雞同鴨講。這次討論也使得 Apple 放棄 Linux,轉而采用 FreeBSD 技術,并在 2001 年任命 FreeBSD 的發起者、領軍人物 Jordan Hubbard 為 BSD 技術小組的經理,并在后來升為 Unix 技術總監。至于 Apple 的內核技術后來走向何方,我們下期再講。
筆者認為,Apple 和 Linus Torvarlds 的商談破裂,以今天的眼光來看,是因 Linus Torvarlds 的自命清高和短視造成的。他不懂得尊重其他開發者的意見,并且不斷抬扛。包括后來關于 C++ 的論戰。Mac OS X 發布后,Linus Torvalds 又數次嘲笑 Mac 的技術落后,并說這些他在當年和 Steve Jobs 開會時就預料到了。直到最近,他終于有些成熟,對 Mac OS X 的觀點開始緩合,但還是不忘批評 Mac 的文件系統就是垃圾(事實上,Linux 的也沒好到哪去,至少 Apple 還搞過一陣 ZFS)。這種性格最終導致在 Mac OS X 和 iOS 大行其道的時候,Linus Torvalds 連兔子湯都不曾分到。
而事實上這對 Apple 也是件好事。Apple 重要的是利益而不是折騰,即使是開源也是利益驅動。像類似 Linux 開發組那樣自以為是但代碼又寫得差的開源項目,Apple 事后也遇到不少,比如 GCC 編譯器項目組。雖然大把鈔票扔進去,在先期能夠解決一些問題,但時間長了這群人總和 Apple 過不去,并以自己在開源世界的地位恫嚇之,最終 Apple 由于受不了這些項目組人員的態度、協議、代碼質量,覺得還不如自己造輪子來得方便,因此 Apple 推動了類似 LLVM 這樣宏偉的項目,并且在短短幾年內,使其成為最領先的開源軟件技術。這無異于扇了 Linux 小組、GCC 小組一記響亮的耳光。
Mac OS X 背后的故事(三)Mach 之父 Avie Tevanian
1975 年,美國羅徹斯特大學紐約分校,一組研究員正在做一個名為 RIG(Rochester’s Intelligent Gateway)的項目,它由 Jerry Feldman 主持設計。RIG 的目標是給所有本地以及遠端的計算設備(比如磁盤、列印機、磁帶、繪圖機等)提供一組統一的訪問方式,其作業系統稱為 Aleph。為了實現所需要的功能,Aleph 的內核主要構建了一個進程交互(Interprocess Communication,IPC)的機制。RIG 的各進程,只要設置了目標端口,就可以彼此間發送信息。RIG 項目沒過幾年就被判了死刑,主要是缺少很多有用的功能,比如端口沒有保護機制,一次最多只能發送 2KB 大小的信息(受硬件限制),也沒有很好的網絡支持等。不過在 20 世紀 70 年代,這個系統依然代表著當時作業系統設計的先進水平,比如除了進程交互外,每個進程還有內存保護的功能,這足以讓 20 世紀 90 年代末都沒有做出內存保護技術的 Apple 公司汗顏。
該項目后來失敗了,隨后在 1979 年,RIG 的 Richard Rashid 博士畢業到卡內基-梅隆大學當教授,開始做 Accent 項目。它是一個網絡作業系統,于 1981 年 4 月開始活躍開發。受 RIG 的影響,Accent 系統的亮點也在于可以使用 IPC,而且解決了很多 RIG 的不足。比如每個進程有 4GB 的虛擬內存空間,而且甚至連內核自已都可以被存入緩存頁面,內存有先進的更新前拷貝(Copy-on-Write)功能,可以實現進程間大信息的傳送等。讀者可以把 Accent 理解為支持虛擬內存技術,并且具有網絡透明 IPC 功能的 RIG 內核。
但過了幾年,開發者們越來越對 Accent 失去興趣。在 1980 年初,很多人覺得多核計算是計算機未來發展的潮流,但 Accent 內核在設計時并沒有考慮到這些問題。而且,隨著許多實驗室紛紛購置性能更強勁的計算機,這就意味著 Accent 需要移植到新的目標架構上。此外,Unix 正大行其道,不管是在作業系統理論上還是在用戶程序上,都成為最為流行的作業系統模式,而 Accent 并不是一個 Unix 系統,所以無法享受 Unix 世界的諸多美好。為了解決這個問題,研究人員決定把所有設計推翻重來,于是就有了一個全新的系統。
在匹茲堡的一個雨天,卡內基-梅隆大學的 Avie Tevanian,此系統的最主要開發者,正打著傘和同學們在去吃午飯的路上。他們一邊繞著無數的泥塘,一邊構思給這個新系統取什么名字好。靈感突來, Avadis Tevanian 建議把這個系統叫作 Muck,引得同學們哈哈大笑。后來,Richard Rashid 和一位意大利同事 Dario Giuse 說起這玩笑,結果這位同事不經意地把 Muck 發為 Mach,遂把 Richard Rashid 笑翻,偉大的 Mach 系統因此得名。
Mach 是一個受 Accent 啟發而搞出的Unix兼容系統。那年,Unix 已經十六歲,而且依然是作業系統理論與實踐開發的主要陣地。Unix 內核由于新加入的功能越來越多,變得越來越復雜。而 Mach 的一個主要目標就是盡量縮減 Unix 的各項服務,以使內核變得簡單可維護。此項目從 1984 年開始,目標主要是包含完整的多任務支援、良好的硬件移植性,并要把大量服務移出內核作為跑在內核上的服務,以及提供與 Unix 的兼容性。
Mach 使用純 C 編寫,所以在一定程度上保證了可移植性,這事實上為后面的 NeXT 向 PowerPC 移植以及 2005 年的向 Intel 移植提供了很重要的前提。而為了縮減內核該管的任務,Mach 做得很絕,只提供內存和處理器管理。類似于檔案系統、網絡、輸入輸出等功能都作為單個的系統進程,獨立執行于內核之上。Mach 的開發過程以 4.3 BSD 作為起點,以 RIG 的 Accent 作為參考,采納 DEC 的虛擬內存設計思路,逐步開發,以新寫的代碼代替 BSD 的代碼。兩年后的 1986 年,雖然沒能把系統服務完全分離于內核之外,但已頗見成效。Mach 第一版大功告成,組員發表會議論文,成為操作系統史上里程碑式的經典,引發操作系統業界的“微內核”學潮,如今學習作業系統設計的皆需學習此文,二十五年來被引用一千二百余次。
這篇文章主要講了兩方面內容:IPC 和虛擬內存。在 IPC 方面,Mach 把復雜的消息傳送機制分為四個獨立的清晰概念—任務、線程、端口、信息。任務是擁有一組系統資源的對象,允許線程在其中執行;線程是執行的基本單位,擁有一個任務的上下文,并且共享任務中的資源。
由于該論文的影響力,所以項目得到了 OSF(Open Software Foundation)在內的很多投資。當然了,學術和工程永遠存在差距,所以即使是最受歡迎的 Mach 2.5 其實仍然是一個包括大多數 BSD 服務層的單內核。但包括 NeXTSTEP、OSF/1 在內的很多操作系統都采用 Mach 作為其內核技術,原因是廣大研究人員依然相信微內核代表著未來。雖然 Mach 2.5 的效率比傳統的 Unix 系統稍低一些,但研究者們表示情緒淡定,因為 Mach 支持多處理器系統,可以利用多線程把任務處理得飛快,相比之下其他 Unix 內核并沒有多處理器的完善支援,因此 Mach 效率稍低完全可以接受。但隨著真正把 Mach 和 BSD 服務完全脫離的 Mach 3 微內核面世,研究人員們的情緒就再也淡定不起來了。因為服務和內核分離后,任務間的 IPC 數量暴漲,一個簡單的 Unix 系統調用要涉及到十多個開端口、設權限、發送、收取消息的操作,哪怕是使用數年后的 1997 年的硬件,跑一個系統調用密集的程序,Mach 的效率要比一般的 Unix 系統慢 50%,而且根本沒有什么好方法來解決這個問題。
所以 Mach 3 出來后,雖有少數微內核信徒繼續執著地改進 Mach,或者開始其他微內核比如 L4 的研究。但學術界對 Mach 的興趣大減,因而 Mach 3 也成為最后一版。項目解散后,Richard Rashid 去了微軟研究院。
再說我們的主角 Avie Tevanian,他 1987 年博士畢業去了 NeXT。這家公司剛剛由 Steve Jobs 成立兩年,這兩年 Steve Jobs 啥正經事都沒干,只是花了十萬美元雇 Paul Rand 設計了一個公司商標。直到 Avie Tevanian 加入后,這個公司才開始干實事。1987 年公司確認要開發一個面向研究人員使用的計算機工作站,于是軟硬件的開發工作緊鑼密鼓地展開。硬件組由領導過 Apple Lisa 的 Rich Page 原班人馬負責,而軟件則由 Avie Tevanian 負責,計劃開發一個有圖形界面的操作系統 NeXTSTEP。由于 Avie Tevanian 是 Mach 主要的開發者,自然 NeXTSTEP 就基于 Mach 了。1988 年 10 月 12 日,NeXT 發布預覽版(0.8版),并于 1989 年 9 月 18 日發布 1.0 版(注:http://en.wikipedia.org/wiki/NeXTSTEP)。
作為 NeXTSTEP 系統的內核,NeXT 分支的 Mach 經歷了不少變化。NeXTSTEP 0.8 主要使用 Mach 2.0 版,而稍后的 NeXTSTEP 1.0 版主要基于 Mach 2.5 版,包含一個自己定制的當時最新的 4.3 BSD 服務層。從 3.1 版開始,NeXT 分支的 Mach 還包括一個全新的設備驅動框架, 名為 Driver Kit,僅供 x86 系列的硬件使用。和 Mach 以及 BSD 代碼不同,Driver Kit 是使用 Objective-C 寫的。為什么是一個面向對象的語言呢?看 NeXTSTEP 3.3 的 DriverKit 文檔。讀者大概就會發現,NeXTSTEP 把所有硬件設備理解為對象,而我們知道,對象之間有繼承關系,比如,磁盤(IODisk物件)屬于輸入輸出設備(IODevice物件)的子物件,而磁盤(IODisk)本身又是邏輯磁盤(IOLogicalDisk)的父物件。硬件的初始化對應于每個物件的初始化(init方法),硬件又有讀、寫,所以可以用 getter/setter 的方法。因此,DriverKit 是一個非常有特色的實現。而且由于 Objective-C 的效率很高,依賴很少(Objective-C 程序可以直接被編譯器翻譯成等價的C語言程序并編譯,而 Objective-C 的運行庫 libobjc 也以高效著稱),所以也是編寫驅動的良好選擇。幾年后的 IOKit 其實就是個 DriverKit 的翻版。
這時,NeXTSTEP 操作系統大獲成功,風險投資商們紛紛購買,但硬件卻始終賣不出去(注:Aaron Hillegass《Cocoa Programming for Mac OS X》前言),所以 NeXT 砍掉了硬件部門專做軟件,更是使 NeXTSTEP 發展到了巔峰時期,同時支持 68K、x86、PA-RISC 和 SPARC 等硬件,但頗有意味的是它就是不支持 PowerPC 架構。它可以同時產生一個包含所有架構可執行碼的二進制文件,來使開發的程序在所有平臺上執行。這個功能也影響了后來 Mac OS X 的技術。Mac OS X 10.4 時代有兩件跨時代意義的事情,一件是 Apple 搞出了 64 位的 Power Mac,開發者可以發布一個包含64位和32位程序的單一可執行文件,而無需讓用戶去區分;另一件是和 Intel 合作。Apple 正式發表了 Universal Binary 技術,可以一個 Mach-O 文件同時包含 Intel 和 PowerPC 的指令。這非常貼心的設計(要知道,大多數電腦用戶根本不知道 Intel、PowerPC、64位、32位等技術)就是來自于 Mach 的技術。
NeXTSTEP 3.3 后,NeXTSTEP 因為 NeXT 和 Sun 的合作改名為 OPENSTEP,1996 年發布 4.0 版,到 1997 年 2 月 4 日,NeXT 被 Apple 收購之前,期間內核改進除源碼同步到 Mach 3.0 版外不明,而且出于不知道的原因,我手頭的 OPENSTEP 正式版光盤中,居然找不到 DriverKit 的發布說明和編程文檔,故不作詳述。不過這段時間,Apple 的活動值得好好一說。之前在《Linus Torvalds的短視》中,我們曾提到,1996 年,Apple 和 OSF 曾經合作,把 Mach 移到 PowerPC Mac 上,再把 Linux 作為單一的服務跑在 Mach 上,這個項目叫做 MkLinux。在 1996 年發布基于 Mach 3.0 和 Linux 1.3 的預覽版,并更新到 2002 年結束其歷史使命,對 Mach 在 PowerPC 的移植性上做出了重要貢獻。這個 PowerPC 版的 Mach 被叫作 osfmk 分支,也正是現在 Mac OS X 中用的分支。當然了,NeXT 被合并后做了大量修改。
Apple 收購 NeXT 后,Mach 被確定作為未來的操作系統核心。Avie Tevanian 被選為軟件開發部的總裁。合并所有項目的號角吹響后,上層的 OpenStep API 和老版 Mac OS 的部件開始合并,而 Mach 也經歷重大變化。主要是一方面,Mach 使用了 osfmk 分支,但依然包含 4.3 BSD 服務;另一方面,DriverKit 被 IOKit 取代。這是 Apple 走得很被動的一步。因為當時外界普遍對 Objective-C 不看好,逼著 Apple 走老版 Mac OS API 的老路。而 Apple 自己對 Objective-C 也很不自信,甚至想索性換用 Java 了事(我們以后會談及這段不自信的歷史)。所以 IOKit 是一個 C++ 的驅動架構,來符合大眾口味。這些改變最早在 Rhapsody 中出現(我們以后也會有一期 Rhapsody 的專題)。但由于 C++ 是門很恐怖的語言,所以 Apple 又把 C++ 給閹割了,去掉了多重繼承、模板、運行時動態以及異常,讓開發者使用這種對于 Objective-C 來說換湯不換藥的 Clean C++ 來做驅動。但公正地說,IOKit 對于 Driver Kit 是有不少改進的,比如 IOKit 可以寫在用戶空間跑的驅動(雖然大多仍是跑在內核空間上的),因而驅動掛了而系統不會掛。另外 IOKit 考慮到了計算機發展的趨勢,所以在電源管理、即插即用、動態加載上做得更好。
但各位也知道,C++ 程序得用專門的運行庫才能跑,所以 Mach 中又加入了一個叫作 libkern 的庫負責 C++ 相關的功能,同時,還有一個 libsa 的庫提供一些類似二分查找、排序等基本算法之類的功能。最后和硬件相關的還有一個叫作 pexpert(Platform Expert)的庫,負責收集硬件設備列表、檢測機器種類(比如處理器速度等)、解析啟動參數等雜活。
至此,Mac OS X 的內核完全形成,形成 BSD、IOKit、Mach osfmk 三足鼎立的態勢,并有 pexpert、libkern、libsa 作為基礎。Apple 稱它的內核杰作為 XNU。其代碼開源,請讀者移步http://www.opensource.apple.com/source/xnu/xnu-123.5/,每個部分的代碼都獨立存放在一個文件夾中,條理清晰,不妨一讀。
由于 4.3 BSD 已是過眼煙云,Apple 后來投入大量資源扶持 FreeBSD 開發。2001 年,Apple 將 FreeBSD 的發起者、領軍人物 Jordan Hubbard 收入麾下,并在 Mac OS X 10.3 時基本同步到 FreeBSD 5 的代碼(注:http://osxbook.com/book/bonus/ancient/whatismacosx/arch_xnu.html)。
另外,Apple 的開發也同時反饋到 FreeBSD 小組,包括 FreeBSD 6.2 內核引入的 AUDIT (man audit 或參見http://manpages.unixforum.co.uk/man-pages/unix/freebsd-6.2/4/audit-man-page.html),后來 FreeBSD 8引入的 libdispatch (http://wiki.freebsd.org/GCD, 在 Apple 這項技術叫 Grand Central Dispatch,是 Mac OS X 10.6 主推的新功能,FreeBSD 基本在 Mac OS X 10.6 上市的同時就擁有這項最新技術),以及 FreeBSD-CURRENT 中的 LLVM-Clang,全是 Apple 的手筆。從 1999 年開始,FreeBSD 源碼倉庫可以搜索到 Apple 提供的大量的補丁以及新功能。
Mac OS X 早期版本不太穩定,所以會內核崩潰。10.0 版本會直接像 Linux 或者 BSD 那樣打出回溯信息,很不美觀,所以 Apple 在 10.2 版本開始設計了一個多國語言的圖片告訴用戶你的內核崩潰了,以讓內核崩得看起來更優雅一點。由于包含四國語言,被國內用戶戲稱為“四國”(注:優雅的圖片見下圖,詳見 http://support.apple.com/kb/ht1392),這是 XNU 的 Mach osfmk 部分的功能。但從 10.3~10.4 版本開始,系統越發穩定,正常使用已很少見到內核崩潰。而且,內核提供的服務也越來越多,使得 Mac OS X 成為一個完善的系統。
21 世紀 XNU 架構方面的最重大改動是支持了 PPC64(10.4 版本時代)、x86 架構(其實本來也一直支持的,以后講 Apple 的 Intel 遷移時詳談)、x86_64(64位支持是蘋果長年努力逐步展開的。10.4 時代 32 位內核支持載入 64 位的用戶程序,10.5 系統提供 64 位的Cocoa框架,但系統大部分程序都是 32 位的,10.6 時代內核支持以 64 位模式啟動,但在不少硬件上這是非默認的方式,但系統大量程序已被改寫并編譯為 64 位的二進制程序,10.7 時代內核默認以 64 位模式啟動。)和 ARM 架構(iPhone 和 iPad 使用 XNU 內核)等多個新架構。
而其中 ARM 架構的支持別具意義。但 2006 年 5 月 31 日,功成名就的 Avie Tevanian 離開 Apple 另謀發展,此時,離 Apple 的 iPhone 奇跡發生,只有不到一年時間。
2000 年,美國總統大選,由于選票設計問題,時任美國副總統的 Al Gore 敗北。2000 年 12 月 13 日,在一番重新計票的大折騰不起作用后,曾經意氣風發的 Al Gore 拖著疲憊的身子,走上講臺,發表了認輸講話(參見 Al Gore《2000 Presidential Concession Speech》),從此退出政壇。一般國家領導人的退政生活其往往松愉快,出出日記,學用哲學,或者像多才多藝的李嵐清不但去各地推廣古典音樂,更是玩起了篆刻(參見《南方周末》2006 年 5 月 11 日《老常委的卸任生活》),克林頓先生都成立個基金會來幫助社會預防和治療愛滋。 Al Gore 也沒閑著,他找到了讓他感興趣的去處——Apple 總部,并成為董事之一。
Mac OS X 和 Al Gore 的雙贏
2003 年 5 月 19 日,Apple 的啟示中罕見性地登出了《前總統 Al Gore 加入 Apple 董事會》的快訊。文中提到,Al Gore 總統是一個正宗果粉,他一直用 Mac 計算機,而且還會用 Final Cut Pro 來編輯他的視頻。Al Gore 也不掩飾他對 Apple 技術的熱愛,他表示對 Mac OS X 的開發極感興趣,并且也對 Apple 在開放源代碼運動中的貢獻喜聞樂見。他虛心地說,想在這個讓 Apple 起死回生的董事會好好觀摩并學習。
Al Gore 的加盟讓 Apple 一躍成為電子產品的代言人
蘋果公司的 CEO Steve Jobs 表示 Al Gore 曾經管理過世界最大的組織——美國政府,期間顯示出的經驗和智慧對蘋果公司是筆巨大的財富。Al Gore 將成為出色的董事會主席,蘋果將以他把蘋果公司作為職業生涯的開始為榮。
這之后,Al Gore 在 Apple 內部的決策究竟起了什么作用,和 Mac OS X 的開發有何關聯,在正式的渠道很少有史料,但是他后來的各種公開活動,卻給 Mac OS X 的技術做足了廣告,而且很多證據表明,他正是使 Apple 從被綠色人士攻擊的眾矢之的的狀態,成為業界注重電子產品環保領頭羊的主要推手。
Al Gore 重新進入普通人的視野是在 2006 年,他推出了自己參與制作和演出的紀錄片《An Inconvenient Truth》(《難以忽視的真相》)和同名書籍。這部長達 94 分鐘的影片,在西方國家引起了廣大的回響,以 Al Gore 的一場演講和人生的回憶作為兩條主線,詳細、科普地向民眾介紹了全球變暖問題的科學證據及美國政府掩蓋問題的真相。該片以發人深省的立意、詳盡的科學數據、平實的講演風格,加上蘋果高超的技術,而獲得了廣泛的好評并一舉獲得年度奧斯卡最佳紀錄片獎,使得這位美國前副總統搖身一變,成為好萊塢明星。
為什么單單一場簡單的講話,就能做出一部電影,還能得到奧斯卡這樣學院藝術獎的親睞?是因為講話內容無懈可擊么?事后有很多科學家站出來表示,雖然影片內容有積極的意義,但其實也有很多被夸大的科學數據、假設和結論。試思索,該片之所以成功,甚至成為諸多演講培訓機構的重要分析案例,除了數據、觀點、論述外,還有以下幾個原因。
首先,這場演講由蘋果主導的技術和藝術的設計。Al Gore 向來以說不清想表達的內容而著稱。他經常因為講得過于專業或者缺乏好的表述方法以致于民眾完全不懂他在講些什么。他的早期講話用現在的眼光看就是個少將體,比如“互聯網…網…我…這個…那個…那個…怎么說呢…我想這個…這…這…這…我啊…我啊…就是說…互聯網是我發明的!”因此作為蘋果展現公司軟實力的重要機會,蘋果非常重視這場講話,請公司的圖形設計小組帶領完成各種所需設計,蘋果甚至特地請來了專業的設計公司 Duarte 來進行講稿和講話內容的安排。因此,不管是內容安排、圖形設計還是技術支持,Al Gore 都有強有力的后盾,他們能夠幫助Al Gore 完成任何想達到的目標。不論是 FinalCut 還是 Keynote,一旦缺少任何 Al Gore 想要的功能,Apple 都可以給他開小灶實現。在片末的走馬燈字幕中,有大量 Apple 的 Keynote 組、Final Cut 組和圖形設計組的員工名字,以示鳴謝。
其次,上面這些資源的相互合作,也使得 Al Gore 的這場講話的講稿被精心制作,體現了精心設計的電子稿演講所能達到的最高成就。蘋果公司向來重視演講,也是各大企業中最會通過演講來營銷產品的公司。每年的 MacWorld 和 WWDC 的 Steve Jobs 講話都會吸引百萬人在計算機前觀看。每場講話都好戲連連,臺下的觀眾的歡呼和掌聲不亞于著名歌星的演唱會。這種風格顯然給 Al Gore 的講話風格帶來很大的影響。在影片中,觀眾看不到一個傳統的 bulletpoint(PowerPoint 用戶常愛使用的表示講話結構的方法),取而代之的是高清的照片、視頻,來展現環境的嚴峻性。觀眾不再會為枯燥無味的技術詞語而搞得昏昏欲睡,因為屏幕上的一切都是如此真實,各種科學現象由動畫效果配合,使其淺顯易懂。另外,所有的數據、圖表都精心使用軟件制作,使其一目了然,表現準確而美觀大方,而且 Al Gore 時而還會玩些小噱頭,比如講到現在的溫室氣體濃度是多么高時,他甚至爬上工作人員為他準備的升降機,升到舞臺頂端,來告訴觀眾,數據已經突破圖表的頂端了。現在距筆者觀賞完這部影片,已經五年過去了,但影片中的災難場景、冰川融化的影片段落、海平面上升的計算機模擬、二氧化碳濃度的數據圖表,至今都記得一清二楚,足以見得其表現力是何等深入人心。甚至有人在調侃他在 2000 年的競選演說是怎么回事?難道就是缺少了這些科技元素?
最后,Mac OS X 的各項技術也是這部片子的重要保證。Duarte 公司的 Ted Boda 表示(該幻燈片的設計師之一),Mac OS X 系統本身的反鋸齒功能把文字、圖片、矢量圖標表現得栩栩如生,使得幻燈片充滿美感。QuickTime 技術作為 Mac OS X 的一塊重要基石,又使得 Keynote 不需任何插件就能引入任何圖片和影像,所以類似使用 Illustrator、Photoshop、AfterEffects 等軟件做出的圖片、影像或動晝,不需要任何轉換過程就能直接拖到 Keynote 中。哪怕 1920×1080 的高清視頻,都可以輕松插入,流暢播放。他們組根本想象不出在 Windows上 使用 PowerPoint 會成什么樣子。
可以說,沒有 Mac OS X,就沒有這部電影。而實際上這部電影的作用遠勝過任何一部 Apple 公司的廣告。片中 Al Gore 時時拿著 PowerBook 的筆記本,在辦公室用 Safari 查網頁,字體渲染真實而美觀,甚至在車上都不忘打開筆記本用 Keynote 做幾張幻燈片,就更不用說電影中 Keynote 幻燈片曾經迷倒多少 Windows 用戶了。向筆者推薦這部電影的好朋友了解到這些全是 Apple 技術的功勞時,擁有一臺 Mac 就成為其人生夢想。
環保衛士的 Apple 之路
作為環保人士,Al Gore 對 Apple 的策略的影響也不容忽視。Apple 向來被各環保組織長期批評,即使 Apple 長年不斷地改進這方面問題,但綠色人士依然不買帳。哪怕在稍后的 2007 年,也仍有包括 GreenPeace 在內的七十多個組織聯名寫信給 Al Gore,敦促 Apple 更重視環境問題,信中指責 Apple 仍在大量使用 PVC 和 BFRs 等對環境有害的材料,也不注重對自家產品的回收。由于 Al Gore 是 Apple 董事會成員,使得這個問題受到了 Apple 的廣泛關注。Apple 在 2007 年后史無前例地邁開大步,大力推廣環保計劃(要求全世界的 IT 制造商們逐步棄用 PVC 等有毒的化學用品進行生產),讓 Apple 一躍成為注重電子產品環境保護問題的領頭羊。
從制造材料上,2007 年 8 月發布的 iMac 成為分水嶺。這款產品的設計主要使用可完全被回收的玻璃屏和鋁外框,減小了塑料等不環保物質的使用,此后蘋果一發不可收拾,把這項革命進行到底,從手機到筆記本,都全番設計。2008 年的 MacBook Air 引出的 Unibody 技術是這場革命的代表產品,不但在外觀上還是工程上做到極致,在環保上更是讓各綠色組織無可挑剔。
在造勢上,Apple 現在每項主要產品的都有“環境”的標簽頁,從制造、運輸、耗電、回收等性能情況分產品詳細列出。Apple 甚至在包裝上都動足腦筋,盡量減少每個產品的包裝,使得同一架飛機可以運輸更多的產品,從而在運輸相同數量產品的情況下減少飛機溫室氣體的總排放量。
Mac OS X 的各項節電功能的開發更是不用說了。休眠、調整空閑時的屏幕亮度、硬盤轉速等常規功能自然越做越好。而系統的多項技術能使程序更優地分配使用中央處理器和顯示卡。甚至系統還能在用戶打字時,每兩鍵之間的空隙減少處理器的占用從而節省擊鍵之間的功耗,這使得 Mac OS X 不但更節約能源,筆記本的電池使用時間也不斷提高。而這一切的變化,和 Al Gore 似乎都有著千絲萬縷的聯系。
由于《An Inconvenient Truth》中的講話讓 Al Gore 的觀點深入人心,同時也對美國政府在京都議定的決策產生重大的壓力,挪威諾貝爾委員會決定把 2007 年的諾貝爾和平獎頒給了 Al Gore,以表彰其在全球環境問題方面的努力,同時蘋果的主頁上全版刊發新聞,以示祝賀。賀詞如下:
Al has put his heart and soul, and much of his life during the past several years, into alerting and educating us all on the climate crisis. We are bursting with pride for Al and this historic recognition of his global contributions. (Al Gore 在過去幾年殫心積慮,全身心地投入對公眾關于氣候危機的警示和教育中。我們為他這次所得的榮譽和他全球性貢獻的歷史性承認感到無比自豪。)
或許,由于 Al Gore 在計算機領域的一貫低調(他也是 Google 的高級顧問),他在這些企業的工作很少被報道出來,但是他在政界的跨界身份是顯而易見的。Al Gore 在他的人生道路將何去何從,我們不得而知,但是從各種媒體信息的披露可以看出,Al Gore 對計算機事業的熱衷,對環保問題的投入,可能是美國歷任領導人中最突出的。
Mac OS X 背后的故事(五)Jean - Marie Hullot 的 Interface Builder 神話
Interface Builder,是用于蘋果公司 Mac OS X 操作系統的軟件開發程序,Xcode 套件的一部分,于 1988 年創立。它的創造者 Jean-Marie Hullot 自稱是“一個熱愛旅行、充滿激情的攝影師”,本篇分享 Hullot 熱愛技術的那一面——創造 Interface Builder 的過程。
因勢而動
1981年, Jean-Marie Hullot 拿到巴黎第十一大學的計算機科學博士資格后,開始了法國國家信息與自動化研究所(INRIA)的研究生活。
Jean-Marie Hullot 的名字似乎不為大眾所熟知,但他設計的 Interface Builder 卻深入人心,創造了一個個軟件神話。
20 世紀 70 年代初,正是面向對象程序設計開始走上歷史舞臺的時期。許多現代計算機技術的誕生地 Xerox PARC(施樂帕洛阿爾托研究中心)的 Alan Kay、Dan Ingalls、Ted Kaehler 、Adele Goldberg 等人,從 1969 年開始研發一款面向對象的程序語言 Smalltalk,并于 1980 年正式公布。這是一個完整地實現面向對象范型的編程套件,包含了一種面向對象的程序設計語言、一種程序設計庫和一個應用開發環境(ADE)。
雖然當時的機器跑得巨慢無比,但 Smalltalk 先進的思想對其他眾多的程序設計語言(Objective-C、Actor、Java 和 Ruby)的產生起到了極大的推動作用,對計算機工業界的發展產生了非常深遠的影響。我們將會在今后介紹 Objective-C 時,詳細介紹 Smalltalk 及其對 Objective-C 的影響,這里先一筆帶過。
Smalltalk 的發布在業界一石激起千層浪,也給 Jean-Marie Hullot 幼小的心靈帶來了巨大的震撼。他立即明白了面向對象思想所代表的先進生產力,一定會改變今后數十年的程序設計流程,他毫不猶豫地成為面向對象編程模式的早期粉絲。
SOS 的助力
那時,Jean-Marie Hullot 使用早期的 Macintosh 計算機進行開發。不過他很快就和其他開發者一樣,發現雖然 Mac 的用戶界面做得不錯,但開發程序實在是太糟糕了。他說:“當 Macintosh 被發明出來時,計算機和先前就大不一樣了,你至少需要花 60%~70% 的時間在用戶界面部分的代碼上。”在 Macintosh 被發明之前,用戶界面是相當簡單的,只需要在命令行下面打一串字符,計算機就會回應出一行行的信息。所以在那個時代,開發者完全不需要專注于用戶界面。而 Mac 一經發布,隨之而來的眾多的窗口和菜單,讓整個世界都不一樣了。雖然對于使用最終產品的用戶而言是簡單方便的,但對于碼工來說簡直是個噩夢。每次他們需要一個窗口或者菜單,都要從零開始構建。
聰明的 Hullot 開始動腦筋改進 Mac 編寫用戶程序難的現狀。他開發了一個程序,有點像現在 Windows 系統中的“畫板”。一側的工具條,是類似菜單這樣的大量可重用的對象;而另一側,則是程序員想構建的用戶程序界面。只要把工具條上的工具拖放到程序界面中,那么類似“打開”、“打印”等相關的功能,就可以被添加到用戶界面中。事實上,這個程序,是最早的一批能通過鼠標把控件拖入界面設計窗口實現相應功能的商業程序,是用戶界面設計軟件的先驅。
這個跨時代的發明被稱作 SOS,用 Lisp 語言編寫【注:What are we going to called this thing 中認為此時就是 Interface Builder,但據 The NeXTonian 等多處資料表明,在 Steve Jobs 見到以前,該程序名為 SOS】。當時,ExperTelligence 開發了一種叫做 ExperLisp 的方言,SOS 即用此語言寫成【注:http://en.wikipedia.org/wiki/Interface_Builder】。
此時 Hullot 忽然意識到,他設計的東西事實上很強大,其重要性簡直可以和 Smalltalk 這樣的發明相比——Smalltalk 讓開發者嘗到了面向對象語言的甜頭,而 SOS 則是直接把對象放到了開發者手邊。有了這么拽的東西,Hullot 意識到如果他只在研究所窩著,那只能讓十幾個人享受這一成果,而如果他跳槽,把這個工具公開,那對天下的碼工來說可是大福音。
誕生之源
經過不斷努力,Hullot 找到了一個值得推銷自己發明的好地方——劍橋的蘋果大學聯盟(Apple University Consortium)。這個蘋果和大學合作的組織看到 Hullot 的創作后反響很好,就推薦他去見 Jean-Louis Gassee。 Jean-Louis Gassee 是個法國人,時任蘋果開發研究院主任,見到 SOS 后也認為這是個好東西,便說服他去美國闖一闖。經過幾次的鼓勵和推薦,加上美國對 Hullot 來說又不陌生,于是他就買了機票跳上飛機就奔赴美國。
不過當 Jean-Marie Hullot 來到美國加州蘋果總部時,他卻認為這不是一個工作的好地方——蘋果已經是一個很龐大的企業,很難再有所創新發展。他最終決定不留在那兒,轉而在美國尋找一個能把這個產品賣出去的人。四處推銷之后,找到他用來寫 SOS 的 Lisp 解釋器的生產商,就是剛才提到的位于 Santa Barbara 的軟件公司 ExperTelligence。
事實上,當時的 ExperTelligence 正在尋找合作商賣自已的 Lisp,而 Hullot 也在找合作商賣自已的 SOS,兩者一拍即合,隨即打電話給 NeXT,共同推銷自家的產品。
NeXT 在 Palo Alto 總部的產品市場部人員接待了 Jean-Marie Hullot 和兩位來自 ExperTelligence 的員工,被 SOS 的理念鎮住,遂打電話請 Steve Jobs 下來看。Jean-Marie Hullot 像復讀機一樣又把自己的大作秀了一遍。老謀深算的 Steve Jobs 事實上早就看中了 SOS,但他對 ExperTelligence 的 Lisp 一點興趣都沒有。所以他裝作對這場演示毫無興致【注:這有很多引用該文的翻譯譯錯,原文說 nonplussed,字面意思為驚異,但在美國非正式表述中,此字表毫無興致】,揮揮手就把這三個人打發走了。
但當他們一行人走到停車場時,Steve Jobs 讓他手下把 Hullot 追了回來,當他只身回到 NeXT 總部時,發現 Steve Jobs 正恭敬地等著他。
“我想要你計算機上那個程序”【注:http://rixstep.com/2/0/people/】,Steve Jobs 說道:“你大概什么時候能開始給我們工作?”
Hullot 回答說自己翌日就要離開去度假。
“好吧,我兩周后給你打電話,”Steve Jobs 說。
“不行,老喬”,Hullot 表示:“我不游美國,我可要環游歐洲,你七個禮拜后再打給我吧。”
Steve Jobs 雖然一骨子傲氣,但他明白一個簡單的道理:21世紀最缺的是什么——是人才!即使 Jean-Marie Hullot 玩起了大牌,這電話自然還是要打的。Hullot 剛一度完假回來,Steve Jobs 的電話就如期而至。
如此三顧茅廬般的熱情,把 Jean-Marie Hullot 感動得第二天就登上了去美國的飛機。合約簽了半年,但實際上他最終在 NeXT 整整待了十年。在 NeXT 工作期間,他使用 Objective-C 和 NeXTSTEP 框架重寫了 SOS,命名為 Interface Builder。由此,Interface Builder 成為 NeXT 集成開發環境 Project Builder 標準套件之一。
進階與探索
Interface Builder 和 SOS 一樣,提供了一個工具箱,包含一系列用戶控件對象。工具箱并不是官方定死的,而是可以任意擴展的,比如如果用戶想使用類似 Safari 中的 toolbar,而這不是官方提供的,則下載第三方的 PSMTabBar 即可實現,甚至連 Cappuccino 這樣的網頁框架也可以用 Interface Builder 來完成設計。開發者只要把控件比如菜單和文本框拖入項目文件就能完成用戶界面設計,節省了幾乎所有和控件放置有關的代碼。
開發者拖拽鼠標,將控件可提供的動作(IBAction)和另一個對象的接口(IBOutlet)連在一起, 則建立了一個綁定。這樣,一旦動作被激發(比如用戶點了按鈕),那接口中相應的方法則會被執行。所以,大量對象關聯的代碼也能被省去。
有了這樣的模式后,Interface Builder 和 Cocoa 可以比后來出現的 Microsoft Visual Studio 或 Qt Designer 等軟件走得更遠——只要是對象,Interface Builder 就能夠操控它們,不需要一定是一個界面的控件。比如,數據庫的數據源、隊列等,都可以在 Interface Builder 中連接起來,于是很多原本需要上千行的復雜應用(比如用來顯示、修改企業中職工姓名、部門、電話、地址、頭像等信息 SQL 數據庫的用戶界面程序),數分鐘內就可以寫完,不用一行代碼。不信?讓 1992 年的 Steve Jobs 親自做給你看【注:http://www.youtube.com/watch?v=j02b8Fuz73A, 第 23 分鐘~第 29 分鐘】。
NeXT 被 Apple 收購后,蘋果把下一代操作系統建立在 NeXTSTEP 的基礎上。Objective-C 和 Cocoa 被作為主要框架,而 Interface Builder 和 Project Builder 也因此受到重用。就官方的工具箱而言,支持 Objective-C/Cocoa、Carbon 的 HIToolbox 和 WebObject。
2008 年 3 月 27 日,蘋果發布首個 iPhone SDK,設計 Cocoa Touch 界面的,也正是 Interface Builder。可以說,Interface Builder 一直隨著公司產品的發展而不斷拓新。
Jean-Marie Hullot 是在 NeXT 被收購時進入蘋果的。Steve Jobs 令他率領在法國的一個小團隊,秘密為 Mac OS X 10.2 開發一個辦公軟件。以往這樣量級的程序,都是由蘋果加州總部的大班人馬完成。而這次,為了向世人表明他的 Interface Builder 有多強大,iCal 橫空出世,展示復雜的界面元素(日歷、可拖拽的任務、五花八門的分類)和諸多功能(網絡同步、Apple Script 腳本控制)可以用相當快速的時間內開發出來【注:http://www.appleinsider.com/articles/07/10/17/road_to_mac_os_x_leopard_ical_3_0.html&page=2】。
最后,在 iCal 小組打完醬油的 Jean-Marie Hullot 榮升蘋果軟件開發部首席技術官。
Project Builder 在 Mac OS X 10.3 時被重命名為現在大家所熟知的 Xcode。Xcode 3 以前,Interface Builder 使用一種名為 nib 格式的二進制文件格式。不過由于 nib 不能用肉眼讀,也不方便使用版本管理工具來管理,所以 Xcode 3 開始新加入一種名為 xib 的文本文件格式,最后再在項目編譯階段輸出為 nib 格式。和產生靜態界面布局代碼的工具(如 MSVC、QtDesigner、 Delphi 等類似的軟件)很不同,nib 是不被轉譯成相應 Objective-C 代碼的。用戶程序執行時,nib 文件被讀入,解包,并且喚醒【注:awake,即載入 nib 會自動調用程序中 awakeFromNib 方法】,所以 nib 文件是在運行時動態加載的。
長期以來,Xcode 環境和 Interface Builder 是兩個獨立但相互工作的程序。而 2010 年釋出的 Xcode 4 預覽版中,Xcode 和 Interface Builder 合二為一,成為一個一體化的編程環境。所以現在,開發者甚至可以只用鼠標在用戶界面和代碼間來回拖拽就能完成,這樣一來 Interface Builder 對用戶代碼的解釋也比先前更正確。比早期分離的程序使用起來確實方便很多。
當然,一個負面的影響是,這樣用一體化集成開發環境寫程序,往往會發現屏幕空間是不夠的,所以像我這樣用 11 寸 Air 或者 13 寸 Macbook Pro 的人,出去打招呼都不好意思說自己是做 Mac 開發的。
下一個海闊天空
在而后的歲月里,Interface Builder 創造了一個又一個應用軟件神話,小到官方教程中的匯率計算器,大到蘋果所有的家用、專業軟件,都由 Interface Builder 完成。
在風起云涌的 1989 年,歐洲核子研究組織(CERN)工作的科學家 Emilio Pagiola 忽悠經費,買來研究所的第一臺 NeXT 計算機——當時 NeXT 計算機在 CERN 可是個新鮮事物——那里的科學家們紛紛前來把玩,普通青年發現里面有全本的韋氏詞典,并可自動檢查用戶輸入的拼寫錯誤,技術青年發現它跑的是 Unix 系統,還有一個可讀寫的光驅,文藝青年更是發現里面居然預裝了莎翁全集。不過畢竟像 Emilio Pagiola 這樣忽悠巨款買 NeXT 機器的青年不多,所以大家圍觀完了,也就回去該干嘛干嘛了。
但 Tim Berners-Lee 和別人不一樣,他不僅圍觀了那臺計算機,還看到了 Jean-Marie Hullot 設計的 Interface Builder,研究了 Objective-C,發現了面向對象編程范式開發環境的最高成就。這情景讓他心中漾起了巨大的波瀾,最終化為激情澎湃的投入,匯成了一行行面向對象的代碼,一瀉千里,奔向未來。
一年后,世界首個 HTTP 服務在 CERN 的 NeXT 計算機運行起來,而使用 Objective-C 和 Interface Builder 所編寫的超文本語言編輯器兼瀏覽器同步發行。他給這個主從式架構起了個好聽的名字——World Wide Web(萬維網)。
Aqua 是 Mac OS X Public Beta 全新用戶界面的名字,英文中為水的詞根,寓意以水為靈感,精心設計。Steve Jobs 曾介紹說,Aqua 的設計是如此之美好,初次見它甚至有想親吻的沖動。本篇 Cordell Ratzlaff 引發的 Aqua 革命(上)介紹的是 Aqua 的起源和來歷,在下篇中,我們將展示 Aqua 的具體設計過程。
“Mac OS 的圖形界面就是你們那么業余的人設計的嗎?” Steve Jobs 開門見山地問。
包括 Cordell Ratzlaff 在內的設計師們怯怯地點頭稱是。“你們就是一群白癡!” Steve Jobs 罵道。
這個場景發生在 Steve Jobs 回歸不久的圖形界面組組會上,前文提到的罵人的話,是他送給圖形界面設計組的見面禮。【注:參見 http://www.cultofmac.com/how-mac-os-x-came-to-be-exclusive-10th-anniversary-story/87889,How Mac OS X Came To Be,Leander Kahney】
不進則退的局面
Mac OS 曾是圖形界面設計的先驅。
從 System 1 開始,Mac 就打破了字符終端的模式,使用圖形界面和用戶交互設計。但自 System 1 到 System 7,10年過去了,界面卻始終沒有顯著的變化。設計組一直認為,為尊重用戶的習慣,定下的規矩不要輕易改動。但同時,Microsoft 的變化可以說是天翻地覆,從黑屏的 DOS,到全屏幕的 Windows 1,再到成熟的 Windows 3,最后演變到奠定當今 Windows 界面基礎的炫麗多彩的 Windows 95。用當時的眼光來看,這個變化是相當驚人的。由于因循守舊,Mac OS 在界面設計上從領先掉到了最后。舊的界面原語,一成不變的界面風格,讓 Mac OS 的圖形界面在 Windows 前顯得黯然無光。【注:參見 http://vimeo.com/21742166】
于是,在圖形界面組的組會上,Steve Jobs 抨擊了老 Mac OS 界面的各種不是——幾乎所有的地方都被罵了一遍。眾矢之的是各種打開窗口和文件夾的方式。在 Mac OS 中有至少 8 種打開窗口和訪問文件夾的方式,如彈出菜單、下拉菜單、DragStrip、Launcher、Finder 等不同的程序。
Cordell Ratzlaff 作為主管,他一開始担心是不是會被 Steve Jobs 炒掉(傳聞說 Steve Jobs 剛進入蘋果時最愛炒人,經常會發生一些“神奇”的情況,比如有員工和他一同進了電梯,等一同出電梯時,該員工已被炒掉)。不過批評大會進行到第 20 分鐘時,Cordell Ratzlaff 轉為淡定,因為他意識到如果 Steve Jobs 要炒他,不用廢那么多話,早就可以動手了。
其實 Cardell Ratzlaff 是 Apple 內部較早意識到小組設計不思進取的人之一。他意識到蘋果有三個重要的設計問題【注:參見 Designing Interactions 第二章 My PC 附錄訪談】。第一、Apple 的很多界面語言不明確。例如,在老 Mac OS 中,刪除文件的動作是把文件圖標拖到廢紙簍里,但當磁盤和光盤彈出時,居然也是把圖標拖到廢紙簍里。第二、老 Mac OS 不會對問題進行變通,如果有幾個圖標同時顯示,窗口還容易操作,但如果有幾十個圖標或窗口,以相同的方式顯示出來,那么在繁雜的頁面中找尋所需內容,對使用者則是巨大的挑戰。第三、Mac OS 的界面過于古板,看上去還是停留在 Windows 3.0 階段。總之,當時的 Mac OS 已經不能代表先進的生產力,也不能代表科技的前進方向,更不能讓廣大用戶得到更多的利益。在 Cardell Ratzlaff 看來, Mac OS 的界面面臨不進則退的重大困局,非改不可。
Cordell Ratzlaff 的試水
收購 NeXT 以后,Apple 開始考慮如何把 NeXTSTEP 作業系統變為下一代的 Apple 操作系統,但界面設計組的倦怠又浮出水面。設計組認為,這是一個浩大的工程,所以他們決定照著 Mac OS 8 的樣子改 NeXTSTEP 的代碼,把 NeXTSTEP 改成 System 8 的樣子。這并不困難,組里只需一個人就能完成這項任務,這人的工作極其無聊——像小孩子描紅模,把新界面的樣子臨摹得和老界面一模一樣。事實上,當 Apple 釋出 Rhapsody 和 Mac OS X Server 初版時,經典 Mac OS 的界面已經被學得惟妙惟肖了。
Cordell Ratzlaff 認為這種混搭,是一個極其讓蘋果丟顏面的事情。所以,除了那個搞山寨的人以外,他召集其他人做新界面設計的圖樣。而由于 NeXTSTEP 具有強大的圖形處理和動畫能力,因此很多新的圖樣是在新系統上完成的。
Apple 將“What's not a computer!”(看起來不是電腦的電腦)的概念應用在硬件外觀上,設計出具有浪漫主義氣質,半透明“果凍” 式且具有藝術美感的 iMac,這成了 Aqua 設計靈感的來源。
20世紀 90 年代初,Apple 和 Microsoft 的操作系統都素面朝天,色調簡單,統一的矩形窗口。到 1997~1998 年,Apple 的硬件外觀設計取得重大進展:由后來成為金牌設計師的 Jonathan Ive 領銜,設計出具有浪漫主義氣質、五彩斑瀾的、半透明外殼、具有曲線美感的 iMac,這個設計成為 Cordell Ratzlaff 和他的同事們設計的靈感,他們馬上就作出了一個全新的界面圖樣來。【注:參見 http://en.wikipedia.org/wiki/IMac_G3】
與此同時,Cordell Ratzlaff 著手解決前文提到的三個設計問題。第一、他提出了一個叫“實時狀態”的概念。當用戶拖動文件時,廢紙保持原樣,而如果拖動的是磁盤,那廢紙簍的圖標變成“彈出”的圖標。第二、窗口的問題統一采用動畫加以解決。比如窗口的最小化和還原都配有動畫,告訴用戶窗口的來去方向。當 Dock 項目有所增減時,項目長度和元素也會隨之改變。第三、Mac OS 一改死板面孔,呈現多彩的、小清新的圖形界面,所有尖銳的直角都被打磨成圓弧,并且有像 iMac 外殼一樣半透明的菜單。當時有評論指責 Apple 的設計太卡通缺乏權威感,其變化之大可見一斑。【注:參見 http://www.aresluna.org/attached/files/usability/papers/onethousandsquarepixelsofcanvas.pdf,One thousand square pixels of canvas On evolution of icons in graphical interfaces by Marcin Wichary 第五頁】
Cocoa 之父 Bertrand Serlet,作為 Cordell Ratzlaff 的上司,對新界面很滿意。但當時,他們認為這個新界面實現起來難度很大,既沒有時間也沒有資源把這個想法在 Mac OS X 中付諸實現。于是先前那位孤獨的照葫蘆畫瓢的設計者只好繼續工作。
Aqua 只是個設想(PS 出來的圖樣+模擬出來的視頻),還不是能用的代碼。
Steve Jobs 的怒火和 Aqua 的源頭
幾個月以后,Apple 舉辦了一個所有開發小組參加的長達兩天的匯報大會。Cordell Ratzlaff 匯報的時間被排在兩天的最后壓軸出場。大多數工程師對這長達兩天的大會報告早已疲倦,感嘆 Mac OS X 剩下的的工作很艱巨,認為發布遙遙無期。于是,Cordell Ratzlaff 報告成了整個報告會的最大笑場,所有工程師使出咆哮體來評價這個工作——“啊!!!你看這新界面多出位啊!!!有沒有有沒有!!!居然用的透明通道!!!還搞個實時的動畫!!!你難道不知道你這些永遠是天方夜譚不可能完成嗎???我們工程師傷不起啊傷不起!!!”這個新設計就這樣在所有 Apple 頂級工程師的鄙視下被廢了。
無奈于此,只好無聊地讓那位開發者繼續復制全套經典 Mac OS 界面,而當 Steve Jobs 召集所有設計組負責人時,這個山寨版 Mac OS 的展示把 Steve Jobs 看得情緒激動,就發生了文章開頭的那一幕。
Cordell Ratzlaff 前來解釋壓軸報告的尷尬局面,暗示千里馬常有而伯樂不常有的處境,還讓 Steve Jobs 觀摩了他的杰作。果然 Steve Jobs 看了這幾張圖例后大為驚異,拍著 Cordell Ratzlaff 的肩說:“很好!很強大!”然后讓設計組不惜一切代價做成試驗品。
在加班奮戰的三周后,設計組用 Macromedia Director 完成了一個試驗品。Steve Jobs 親自來 Cordell Ratzlaff 辦公室視察了一下午。結果是他激動地握著 Cordell Ratzlaff 的手,吐露心聲:“你是蘋果里我見到的第一個智商是三位數字的人。”得到了 Steve Jobs 的支持,Apple 的 Mac OS X 開發團隊,更加緊密地圍繞在以 Cordell Ratzlaff 為核心的界面設計概念周圍,開發操作系統。
有緣千里來相會,無緣對面不相識。Steve Jobs 和 Cordell Ratzlaff 算是相見恨晚。這樣由 Cordell Ratzlaff 主導的新界面,在 Steve Jobs 的支持下,橫掃一切困難,成為新版操作系統界面的最大亮點。
從這時到 Steve Jobs 正式在舞臺上秀他的 Mac OS X Public Beta,還有 18 個月。此時,系統界面革命的旅程已經開始,一道神秘的天光射向 Infinity Loop,千古杰作 Aqua 就要在這里誕生,其光輝歷程,我們下篇再談。
Mac OS X 背后的故事(七)上善若水下——Cordell Ratzlaff 引發的 Aqua 革命
在前一節中講到,Cordell Ratzlaff 新界面方案得到 Steve Jobs 的高度肯定,Steve Jobs 讓各開發組緊緊圍繞在界面設計組周圍,共同建造 Mac OS X。此時,離 Mac OS X 第一個公共測試版的發布,僅有一年半時間。這時蘋果的設計構想,還僅僅是個概念,在本篇中我們將展示 Aqua 的具體設計過程。
設計與軟件的融合
開發分設計和軟件兩條路并行走,“兩手抓,兩手都要硬”。
設計是個有趣的領域。有些人認為,設計就是產品的外觀看上去什么樣。但其實,如果細想一下,你會發現設計其實是有關產品如何工作的學問。
——Steve Jobs
首先,蘋果定下計劃,并規劃整個界面設計元素的方案,把設想通過可操作性強的材料讓工程師來實現。
Cordell Ratzlaff 每周都要和 Steve Jobs 開會,向他展示界面設計小組最新成果。任何大家現在見到的各界面控件,如菜單、按鈕、進度條、Steve Jobs 都一一過目,毫不馬虎。針對每一個控件,Cordell Ratzlaff 會要求拿出多套方案來,讓 Steve Jobs 選出他中意的。Steve Jobs 也會提出各種他自己的見解和改進建議,而 Cordell Ratzlaff 則會根據這些回饋不斷修改,直到 Steve Jobs 滿意為止。
與此同時,軟件工程師也以越來越重的比例加入到這個設計行列中。
圖形界面設計小組使用的設計軟件是 Macromedia Director。它能做出演示用的動畫,可以演示打開、關閉窗口、下拉菜單等模擬效果,但這些并不是可供用戶使用的最終軟件。軟件工程師需要把圖形界面設計師的設計,變為一行行代碼,運用到 Mac OS X 中。所以每次會議的 Macromedia Director 動畫演示機旁,還會有一臺計算機,預裝了軟件工程師轉換的代碼。當工程師們向 Steve Jobs 展示最新代碼如何工作時,Steve Jobs 會身體前傾,鼻子快貼到熒幕上,觀察細微到“像素級別”來比較軟件的表現和之前的設計是否完全一致。如果他有發現任何細微的差錯,一陣類似“你們全是一幫白癡”的腥風血雨就會在辦公室中展開。
設計整套方案是一個令人難以置信的漫長過程,尤其是遇到追求完美的 Steve Jobs。Mac OS X 中有一個控件叫滾動條(NSScroller)。當需要顯示的內容長于當前控件大小時就會出現滾動條,可上下翻閱內容。這是一個非常不起眼的控件,大多數時間,用戶甚至注意不到它的存在,甚至在十年后的今天它都被默認不顯示了(關于 Lion 圖形界面的改動受 iOS 思潮的影響我們今后會提到)。但哪怕是這種不起眼的細節,Steve Jobs 都偏執地當個大項目來做。Mac OS X 的界面設計是有史以來最復雜的一個,需要考慮諸多因素——比如所在窗口的活動與否,都會影響這個控件的顏色等屬性。就滾動條而言,箭頭的大小、位置的變化、顏色的啟用等全都是活動的屬性,牽一發而動全身。一根看似簡單得不能再簡單的滾動條,設計組花了整整六個月來修改。
當時,Mac OS X 的用戶界面有兩個重大的設計目標:第一是讓老用戶沒有壓力地遷移過來,且倍感新界面的好用;第二是讓那些從未摸過 Mac 的人盡快上手,并稱贊這界面很好很強大。所以,整個界面設計保留了老 Mac OS 界面元素的設計理念,但同時又對很多有問題的老設計進行了革新。比如,在老版 Mac OS 中,各種系統設置選項是隱藏在不計其數的系統擴展、控制面板,以及很多系統組件中的。用戶要想聯個網,要去五六個地方設網絡、設 IP、設連接設密碼,而在 Mac OS X 中,所有這些設置都被分門別類地規類到一個單一的程序——系統首選項(System Preferences),讓用戶“足不出戶”,就能進行一切相關設置。
精簡的狂熱追求和大膽的設計創新
Apple 偏愛最簡化的設計,而往往滿屏的窗口讓 Steve Jobs 忍無可忍。又酷又炫的 Dock 橫空出世,巧妙地解決了這個問題。Dock 的設計源于 Mac OS X 的前身 NeXTSTEP,但在 Mac OS X 中完全被重寫,并重定義了它的功能。Dock 提供用戶一個放置常用軟件圖標、閑置窗口、文檔的場所,Steve Jobs 說“任何東西都能被拉進 Dock”。但 Dock 真正神奇的,是它猶如多拉A夢的口袋,有無限的承載能力。當放入 Dock 中的東西變多時,它會自動把橫向寬度變長、圖標變小,可承載幾十個窗口。當窗口縮入和還原時,都配有“精靈”一樣的動畫——在 Dock 的圖標多的時候,每個圖標很小,用戶就很難找到需要的——靈動且放大動畫可以讓用戶能快速地找到所需。
另外,起初版本的 Dock 中每個圖標都是正方形的方塊,被換成半透明的背景,看得人垂涎欲滴。這些經典的設計,影響了整整一代圖形界面設計者,被各山寨界面抄了一遍又一遍,甚至又活在當今的 Ubuntu Linux 的 Unity 和 Windows 7 中。
Apple 追求清爽甚至到了發瘋的地步,在最初版的 Mac OS X Public Beta 中,每個窗口有一個按鈕,只要按下,除了當前窗口外,其它一切都會飛入 Dock。因此,只要一鍵,“整個世界都清靜了”。而在后來每個版本的 Mac OS X 中,都有大的更新來防止窗口或其他界面元素的堆積。10. 4 時代的 Expose,10. 5 時代的 Stack 和 Spaces,10.6 時代的 Expose 和 Dock 相結合雙管齊下,到 10.7 時代的 Mission Control,都是用來解決果面精簡這一個問題的。
而很多傳統的界面控件也被賦予了新的含義。比如 Steve Jobs 覺得,“最大化”一個窗口沒有實際意義,而且把整個窗口最大化,也會擋住后面的窗口(直到 2011 年,Apple 用“全屏”來重新定義傳統的“最大化”)。而 Mac OS X 沒有所謂的“最大化”,取而代之的是自動計算后調整窗口到所需大小的“最適化按鈕”。而關閉一個窗口的含意也不該是關閉一個程序,而只應是結束目前的內容。Apple 的許多設計都格外具有魄力,完全重寫了界面設計的教科書。當然,有許多地方 Apple 確實做得矯枉過正,比如 Apple 一直是我見過的只有拖住右下角才能改動窗口大小的唯一系統。這個置用戶于不顧的狂妄設計,一直在十年后發布的 Lion 中,才得以改變。
Steve Jobs 一直是界面設計的重要顧問。他有時候會提出一些看似稀奇古怪的意見,但往往最終又被證明是好的。比如,有一次他在會上指出,窗口左上角的“關閉”、“最小化”、“最適化”三個按鈕的顏色都是一樣的灰色,不容易區分他們。他建議把三個按鈕變成交通燈的顏色,并且當鼠標移到附近時,顯示出相應的圖形指示。當 Cordell Ratzlaff 一群人聽到這個主意后面色大變,認為簡直是計算機圖形設計史上最好笑的段子——誰會把電腦當交通燈使啊。不過改完后,他們對 Steve Jobs 心悅誠服——“紅燈給用戶一個終止的警示,這個窗口要被關掉;黃燈表示這個窗口要被放入等待隊列,以便以后再通行;最適化則是給這個窗口大開綠燈”——這樣高明的比喻,使 Cordell Ratzlaff 對 Steve Jobs 崇拜得五體投地。
18個月轉瞬即逝,“你們就是一群白癡”的罵聲依舊清晰,而此時的 Mac OS X 的圖形界面,已今非昔彼。
“語靜聲息。我走上舞臺。依著那打開的門,我試圖探測回聲中,蘊涵著什么樣的未來。”(北島翻譯的帕斯捷爾納克的《哈姆雷特》)。
18 個月后的 2000 年 1 月,新世紀的鐘聲剛剛敲響,Steve Jobs 鎮定地走上 MacWorld 大會的舞臺,獨領風騷的新世紀的經典大作 Aqua,此時,就要被他揭開帷幕。
Mac OS X 背后的故事(八)三好學生 Chris Lattner 的 LLVM 編譯工具鏈
2011年 12 月 3 日,LLVM 3.0 正式版發布,完整支持所有 ISO C++ 標準和大部分 C++ 0x 的新特性, 這對于一個短短幾年的全新項目來說非常不易。
開發者的驚愕
在 2011 年 WWDC(蘋果全球開發者大會)的一場與 Objective-C 相關的講座上,開發者的人生觀被顛覆了。
作為一個開發者,管理好自己程序所使用的內存是天經地義的事,好比人們在溜狗時必須清理狗的排泄物一樣(美國隨處可見“Clean up after your dogs”的標志)。在本科階段上 C 語言的課程時,教授們會向學生反復強調:如果使用 malloc 函數申請了一塊內存,使用完后必須再使用 free 函數把申請的內存還給系統——如果不還,會造成“內存泄漏”的結果。這對于 Hello World 可能還不算嚴重,但對于龐大的程序或是長時間運行的服務器程序,泄內存是致命的。如果沒記住,自己還清理了兩次,造成的結果則嚴重得多——直接導致程序崩潰。
Objective-C 有類似 malloc/free 的對子,叫 alloc/dealloc,這種原始的方式如同管理C內存一樣困難。所以 Objective-C 中的內存管理又增加了“引用計數”的方法,也就是如果一個物件被別的物件引用一次,則引用計數加一;如果不再被該物件引用,則引用計數減一;當引用計數減至零時,則系統自動清掉該物件所占的內存。具體來說,如果我們有一個字符串,當建立時,需要使用 alloc 方法來申請內存,引用計數則變成了一;然后被其他物件引用時,需要用 retain 方法去增加它的引用計數,變成二。當它和剛才引用的物件脫離關聯時,需使 release 方法減少引用計數,又變回了一;最后,使用完這個字符串時,再用 release 方法減少其引用計數,這時,運行庫發現其引用計數變為零了,則回收走它的內存。這是手動的方式。
這種方式自然很麻煩,所以又設計出一種叫做 autorelease 的機制(不是類似 Java 的自動垃圾回收)。在 Objective-C 中,設計了一個叫做 NSAutoReleasePool 的池,當開發者需要完成一個任務時(比如每開啟一個線程,或者開始一個函數),可以手動創立一個這樣的池子, 然后通過顯式聲明把物件扔進自動回收池中。NSAutoReleasePool 內有一個數組來保存聲明為 autorelease 的所有對象。如果一個對象聲明為 autorelease,則會自動加到池子里。如果完成了一個任務(結束線程了,或者退出那個函數),則開發者需對這個池子發送一個 drain 消息。這時,NSAutoReleasePool 會對池子中所有的物件發送 release 消息,把它們的引用計數都減一 ——這就好比游泳池關門時通知所有客人都“滾蛋”一樣。所以開發者無需顯式聲明 release,所有的物件也會在池子清空時自動呼叫 release 函數,如果引用計數變成零了,系統才回收那塊內存。所以這是個半自動、半手動的方式。
Objective-C 的這種方式雖然比起 C 來進了一大步,我剛才花了幾分鐘就和讀者講明白了。只要遵守上面這兩個簡單的規則,就可以保證不犯任何錯誤。但這和后來的 Java 自動垃圾回收相比則是非常繁瑣的,哪怕是再熟練的開發者,一不小心就會弄錯。而且,哪怕很簡單的代碼,比如物件的 getter/setter 函數,都需要用戶寫上一堆的代碼來管理接收來的物件的內存。
經典教材《Cocoa Programming for Mac OS X》用了整整一章節的篇幅,來講解 Objective-C 中內存管理相關的內容,但初學者們看得還是一頭霧水。所以,在 2007 年 10.5 發布時,Objective-C 做出了有史以來最大的更新,最大的亮點是它的運行庫 libobjc 2.0 正式支持自動垃圾回收,也就是由運行庫在運行時隨時偵測哪些物件需要被釋放。聽上去很不錯,可惜使用這個技術的項目卻少之又少。原因很簡單,使用這個特性,會有很大的性能損失,使 Objective-C 的內存管理效率低得和 Java 一樣,而且一旦有一個模塊啟用了這個特性,這個進程中所有的地方都要啟用這個特性——因此如果你寫了一個使用垃圾回收的庫,那所有引用你庫的程序就都得被迫使用垃圾回收。所以 Apple 自己也不使用這項技術,大量的第三方庫也不使用它。
這個問題隨 Apple 在移動市場的一炮走紅而變得更加嚴峻。不過這次,Apple 和與會的開發者講,他們找到了一個解決問題的終極方法,這個方法把從世界各地專程趕來聆聽圣諭的開發者驚得目瞪口呆——你不用寫任何內存管理代碼,也不需要使用自動垃圾回收。因為我們的編譯器已經學會了上面所介紹的內存管理規則,會自動在編譯程序時把這些代碼插進去。
這個編譯器,一直是 Apple 公開的秘密——LLVM。說它公開,是因為它自始至終都是一個開源項目;而秘密,則是因為它從來沒公開在 WWDC 的 Keynote 演講上亮相過 。
一直關注這系列連載的讀者一定還記得,在第二篇《Linus Torvalds 的短視》介紹 Apple 和 GPL 社區的不合時,提到過“自以為是但代碼又寫得差的開源項目,Apple 事后也遇到不少,比如 GCC 編譯器項目組。雖然大把鈔票扔進去,在先期能夠解決一些問題,但時間長了這群人總和 Apple 過不去,并以自己在開源世界的地位恫嚇之,最終 Apple 由于受不了這些項目組的態度、協議、代碼質量,覺得還不如自己造輪子來得方便。”LLVM 則是 Apple 造的這個輪子,它的目的是完全替代掉 GCC 那條編譯鏈。它的主要作者,則是現在就職于 Apple 的 Chris Lattner。
編譯器高材生 Chris Lattner
2000年,本科畢業的 Chris Lattner 像中國多數大學生一樣,按部就班地考了 GRE,最終前往 UIUC(伊利諾伊大學厄巴納香檳分校),開始了艱苦讀計算機碩士和博士的生涯。在這階段,他不僅周游美國各大景點,更是努力學習科學文化知識,翻爛了“龍書”(《Compilers: Principles, Techniques, and Tools》),成了 GPA 牛人【注:最終學分積 4.0 滿分】,以及不斷地研究探索關于編譯器的未知領域,發表了一篇又一篇的論文,是中國傳統觀念里的“三好學生”。他的碩士畢業論文提出了一套完整的在編譯時、鏈接時、運行時甚至是在閑置時優化程序的編譯思想,直接奠定了 LLVM 的基礎。
LLVM 在他念博士時更加成熟,使用 GCC 作為前端來對用戶程序進行語義分析產生 IF(Intermidiate Format),然后 LLVM 使用分析結果完成代碼優化和生成。這項研究讓他在 2005 年畢業時,成為小有名氣的編譯器專家,他也因此早早地被 Apple 相中,成為其編譯器項目的骨干。
Apple 相中 Chris Lattner 主要是看中 LLVM 能擺脫 GCC 束縛。Apple(包括中后期的 NeXT) 一直使用 GCC 作為官方的編譯器。GCC 作為開源世界的編譯器標準一直做得不錯,但 Apple 對編譯工具會提出更高的要求。
一方面,是 Apple 對 Objective-C 語言(甚至后來對 C 語言)新增很多特性,但 GCC 開發者并不買 Apple 的帳——不給實現,因此索性后來兩者分成兩條分支分別開發,這也造成 Apple 的編譯器版本遠落后于 GCC 的官方版本。另一方面,GCC 的代碼耦合度太高,不好獨立,而且越是后期的版本,代碼質量越差,但 Apple 想做的很多功能(比如更好的 IDE 支持)需要模塊化的方式來調用 GCC,但 GCC 一直不給做。甚至最近,《GCC 運行環境豁免條款 (英文版)》從根本上限制了 LLVM-GCC 的開發。 所以,這種不和讓 Apple 一直在尋找一個高效的、模塊化的、協議更放松的開源替代品,Chris Lattner 的 LLVM 顯然是一個很棒的選擇。
剛進入 Apple,Chris Lattner 就大展身手:首先在 OpenGL 小組做代碼優化,把 LLVM 運行時的編譯架在 OpenGL 棧上,這樣 OpenGL 棧能夠產出更高效率的圖形代碼。如果顯卡足夠高級,這些代碼會直接扔入 GPU 執行。但對于一些不支持全部 OpenGL 特性的顯卡(比如當時的 Intel GMA 卡),LLVM 則能夠把這些指令優化成高效的 CPU 指令,使程序依然能夠正常運行。這個強大的 OpenGL 實現被用在了后來發布的 Mac OS X 10.5 上。同時,LLVM 的鏈接優化被直接加入到 Apple 的代碼鏈接器上,而 LLVM-GCC 也被同步到使用 GCC 4 代碼。
LLVM 真正的發跡,則得等到 Mac OS X 10.6 Snow Leopard 登上舞臺。可以說, Snow Leopard 的新功能,完全得益于 LLVM 的技術。而這一個版本,也是將 LLVM 推向真正成熟的重大機遇。
關于 Snow Leopard 的三項主推技術(64位支持、OpenCL,以及 Grand Central Dispatch)的細節,我們會在下一次有整整一期篇幅仔細討論,這次只是點到為止——我們告訴讀者,這些技術,不但需要語言層面的支持(比如 Grand Centrual Dispatch 所用到的“代碼塊”語法, 這被很多人看作是帶 lambda 的 C),也需要底層代碼生成和優化(比如 OpenCL 是在運行時編譯為 GPU 或 CPU 代碼并發執行的)。而這些需求得以實現,歸功于 LLVM 自身的新前端——Clang。
優異的答卷——Clang
前文提到,Apple 吸收 Chris Lattner 的目的要比改進 GCC 代碼優化宏大得多——GCC 系統龐大而笨重,而 Apple 大量使用的 Objective-C 在 GCC 中優先級很低。此外 GCC 作為一個純粹的編譯系統,與 IDE 配合得很差。加之許可證方面的要求,Apple 無法使用 LLVM 繼續改進 GCC 的代碼質量。于是,Apple 決定從零開始寫 C、C++、Objective-C 語言的前端 Clang,完全替代掉 GCC。
正像名字所寫的那樣,Clang 只支持 C,C++和 Objective-C 三種C家族語言。2007年開始開發,C 編譯器最早完成,而由于 Objective-C 相對簡單,只是 C 語言的一個簡單擴展,很多情況下甚至可以等價地改寫為C語言對 Objective-C 運行庫的函數調用,因此在 2009 年時,已經完全可以用于生產環境。C++ 的支持也熱火朝天地進行著。
Clang 的加入代表著 LLVM 真正走向成熟和全能,Chris Lattner 以影響他最大的“龍書”封面【注:見 http://en.wikipedia.org/wiki/Dragon_Book_(computer_science)】為靈感,為項目選定了圖標——一條張牙舞爪的飛龍。
Clang 一個重要的特性是編譯快速,占內存少,而代碼質量還比 GCC 來得高。測試結果表明 Clang 編譯 Objective-C 代碼時速度為 GCC 的 3 倍【注:http://llvm.org/pubs/2007-07-25-LLVM-2.0-and-Beyond.pdf】,而語法樹(AST)內存占用則為被編譯源碼的 1.3 倍,而 GCC 則可以輕易地可以超過 10 倍。Clang 不但編譯代碼快,對于用戶犯下的錯誤,也能夠更準確地給出建議。使用過 GCC 的讀者應該熟悉,GCC 給出的錯誤提示基本都不是給人看的。
比如最簡單的:
struct foo { int x; }
typedef int bar;
如果使用 GCC 編譯,它將告訴你:
t.c:3: error: two or more data types in declaration specifiers
但是 Clang 給出的出錯提示則顯得人性化得多:
t.c:1:22: error: expected ‘;’ after struct
甚至,Clang 可以根據語境,像拼寫檢查程序一樣地告訴你可能的替代方案。
比如這個程序:
#include
int64 x;
GCC 一樣給出亂碼似的出錯提示:
t.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘x’
而優雅的 Clang 則用彩色的提示告訴你是不是拼錯了,并給出可能的變量名:
t.c:2:1: error: unknown type name ‘int64′; did you mean ‘int64_t’?
int64 x;^~~~~int64_t
更多的例子可以參考 http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.html。 而同時又因為 Clang 是高度模塊化的一個前端,很容易實現代碼的高度重用。所以比如 Xcode 4.0 的集成編程環境就使用 Clang 的模塊來實現代碼的自動加亮、代碼出錯的提示和自動的代碼補全。開發者使用 Xcode 4.0 以后的版本,可以極大地提高編程效率,盡可能地降低編譯錯誤的發生率。
支持 C++ 也是 Clang 的一項重要使命。C++ 是一門非常復雜的語言,大多編譯器(如 GCC、MSVC)用了十多年甚至二十多年來完善對 C++ 的支持,但效果依然不很理想。Clang 的 C++ 支持卻一直如火如荼地展開著。2010 年 2 月 4 日,Clang 已經成熟到能自舉(即使用 Clang 編譯 Clang,到我發稿時,LLVM 3.0 發布已完整支持所有 ISO C++ 標準,以及大部分C++ 0x 的新特性。
這對于一個短短幾年的全新項目來說是非常不易的。得益于本身健壯的架構和 Apple 的大力支持,Clang 越來越全能,從 FreeBSD 到 Linux Kernel , 從 Boost 到 Java 虛擬機, Clang 支持的項目越來越多。
Apple 的 Mac OS X 以及 iOS 也成了 Clang 和 LLVM 的主要試驗場——10.6 時代,很多需要高效運行的程序比如 OpenSSL 和 Hotspot 就由 LLVM-GCC 編譯來加速的。而 10.6 時代的 Xcode 3.2 諸多圖形界面開發程序如 Xcode、Interface Builder 等,皆由 Clang 編譯。到了 Mac OS X 10.7,整個系統的的代碼都由 Clang 或 LLVM-GCC 編譯【注:http://llvm.org/Users.html】。
LLVM 周邊工具
由于受到 Clang 項目的威脅,GCC 也不得不軟下來,讓自己變得稍微模塊化一些,推出插件的支持,而 LLVM 項目則順水推舟,索性廢掉了出道時就一直作為看家本領的 LLVM-GCC,改為一個 GCC 的插件 DragonEgg。 Apple 也于 Xcode 4.2 徹底拋棄了 GCC 工具鏈。
而 Clang 的一個重要衍生項目,則是靜態分析工具,能夠通過自動分折程序的邏輯,在編譯時就找出程序可能的 bug。在 Mac OS X 10.6 時,靜態分析被集成進 Xcode 3.2,幫助用戶查找自己犯下的錯誤。其中一個功能,就是告訴用戶內存管理的 Bug,比如 alloc 了一個物件卻忘記使用 release 回收。這已經是一項很可怕的技術,而 Apple 自己一定使用它來發現并改正 Mac OS X 整個系統各層面的問題。但許多開發者還不滿足——既然你能發現我漏寫了 release,你為什么不能幫我自動加上呢?于是 ARC 被集成進 Clang,發生了文章開頭開發者們的驚愕——從來沒有人覺得這件事是可以做成的。
除 LLVM 核心和 Clang 以外,LLVM 還包括一些重要的子項目,比如一個原生支持調試多線程程序的調試器 LLDB,和一個 C++ 的標準庫 libstdc++,這些項目由于是從零重寫的,因此要比先前的很多項目站得更高,比如先前 GNU、Apache、STLport 等 C++ 標準庫在設計時,C++0x 標準還未公布,所以大多不支持這些新標準或者需要通過一些骯臟的改動才能支持,而 libstdc++ 則原生支持C++0x。而且在現代架構上,這些項目能動用多核把事情處理得更好。
不單單是 Apple,諸多的項目和編程語言都從 LLVM 里取得了關鍵性的技術。Haskell 語言編譯器 GHC 使用 LLVM 作為后端,實現了高質量的代碼編譯。很多動態語言實現也使用 LLVM 作為運行時的編譯工具,較著名的有 Google 的 Unladen Swallow【注:Python 實現,后夭折】、PyPy【注:Python 實現】,以及 MacRuby【注:Ruby 實現】。例如 MacRuby 后端改為 LLVM 后,速度不但有了顯著的提高,更是支持 Grand Central Dispatch 來實現高度的并行運行。由于 LLVM 高度的模塊化,很方便重用其中的組件來作為一個實現的重要組成部分,因此類似的項目會越來越多。
LLVM 的成熟也給其他痛恨 GCC 的開發項目出了一口惡氣。其中最重要的,恐怕是以 FreeBSD 為代表的 BSD 社區。BSD 社區和 Apple 的聯系一向很緊密,而且由于代碼相似,很多 Apple 的技術如 Grand Central Dispatch 也是最早移植到 FreeBSD 上。BSD 社區很早就在找 GCC 的替代品,無奈大多都很差(如 Portable C Compiler 產生的代碼質量和 GCC 不能同日而語)。
一方面是因為不滿意 GCC 的代碼品質【注:BSD 代碼整體要比 GNU 的高一些,GNU 代碼永無休止地出現各種嚴重的安全問題】,更重要的是協議問題。BSD 開發者有潔癖的居多,大多都不喜歡 GPL 代碼,尤其是 GPL 協議第三版發布時,和 FreeBSD 的協議甚至是沖突的。這也正是為什么 FreeBSD 中包含的 GNU 的 C++ 運行庫還是 2007 年以 GPLv2 發布的老版本,而不是支持C++0x 的但依 GPLv3 協議發布的新版本。因此歷時兩年的開發后,2012年初發布的 FreeBSD 9.0 中,Clang 被加入到 FreeBSD 的基礎系統。 但這只是第一步,因為 FreeBSD 中依然使用 GNU 的 C++ STL 庫、C++ 運行庫、GDB 調試器、libgcc/libgcc_s 編譯庫都是和編譯相關的重要底層技術,先前全被 GNU 壟斷,而現在 LLVM 子項目 lldb、libstdc++、compiler-rt 等項目的出現,使 BSD 社區有機會向 GNU 說“不”,因此一個把 GNU 組件移出 FreeBSD 的計劃被構想出來,并完成了很大一部分。編寫過《Cocoa Programming Developer’s Handbook》的著名 Objective-C 牛人 David Chisnall 也被吸收入 FreeBSD 開發組完成這個計劃的關鍵部分。 預計在 FreeBSD 10 發布時,將不再包含 GNU 代碼。
LLVM 在短短五年內取得的快速發展充分反映了 Apple 對于產品技術的遠見和處理爭端的決心和手腕,并一躍成為最領先的開源軟件技術。而 Chris Lattner 在 2010 年也贏得了他應有的榮譽——Programming Languages Software Award(程序設計語言軟件獎)。
半導體的豐收(上)
在美國賓夕法尼亞州的東部,有一個風景秀美的城市叫費城。在這個城市誕生了一系列改變世界的奇跡:第一個三權分立的國家——美立堅合眾國,就在第五街的路口誕生;舉世聞名的費城交響樂團,1900年在市中心的 Academy of Music 奏響了他們的第一個音符。而寫這篇文章時,我正坐在三十四街的賓夕法尼亞大學計算機系的一樓實驗室,面前擺放著世界上第一臺電子計算機——ENIAC。
1946年 2 月 14 日,ENIAC 問世,每秒可運行 5000 次加法運算或 500 次乘法運算,面積達 170 平方米,重約 30 噸,拉開了計算機處理器革命的序幕。這場革命是各處理器廠商長達數十年的競賽,而摩爾定律從一開始就準確地預測了這場比賽的走勢。根據摩爾定律,同樣價格的集成電路上可容納的晶體管數目,每隔約 18 個月便會增加一倍,性能也將提升一倍。但事實上,并無法用老路子來保持這個增長速度,因為會遇到包括能耗、散熱等各種技術瓶頸。所以每隔幾年就會有用來繞過這些瓶頸的新一代產品推出。如采用超純量(superscala)、指令管線化、快取等。這些技術通過一定程度的高效并行來挖掘計算機處理器的速度所能達到的高度,以促使用戶更新換代。
世界上第一臺計算機 ENIAC,1946年 2 月 14 日誕生于賓夕法尼亞大學
和 66 年前的 ENIAC 相比,今天的處理器已有了質的飛越。而 21 世紀的前十年,我們更是見證了個人計算機處理器的三次重大革命——64位處理器、多核心和高效圖形處理器在個人電腦出現。在這樣的背景下,喬布斯在 2008 年 WWDC(蘋果全球開發者大會)上,宣布下一代 Mac 操作系統 Mac OS X 10.6 將被命名為 Snow Leopard(雪豹)來適應硬件架構的革新。就在那天下午,Bertrand Serlet 在一場開發者內部講座上透露,和先前兩個發行版包含大量的新功能(10.4 Tiger 包含 150 個新功能,10.5 Leopard 包含 300 個新功能)不同,Snow Leopard 不含任何新功能,僅是對 Leopard 中諸多技術的重大更新,以使其在現代架構上更穩定、高效。 在這十年的最后一年,2009 年 8 月 28 日,蘋果發布了 Mac OS X 10.6 來有效地支持這三項技術,而本文將為讀者介紹其對應的三項軟件技術——64位架構、Grand Central Dispatch,以及 OpenCL。 其他 Mac OS X 10.6 技術更新,如全新的 QuickTime X 和跳票的 ZFS,有著更復雜的歷史背景(以后再為讀者介紹)。
64 位架構出現的緣由
前文提到,根據摩爾定律,同樣價格的集成電路上可容納的晶體管數目,約每隔 18 個月便會增加一倍,性能也將提升一倍。事實上,存儲器的容量增長可能更快,每過 15 個月就會翻一番。有了更快更強的電腦,可能會讓數值計算的科學家們喜出望外,但對普通大眾來說,摩爾定律給普通消費者一個假象——如果你覺得 1000 美元的蘋果電腦太貴,那等上 18 個月就可以用 500 美元買到同樣的電腦。十年前你在用電腦寫 Word 文檔,十年后你還在用電腦寫 Word 文檔,反正計算機不是耗材,一臺電腦只要不壞,就不用去買新的。計算機產業的巨頭們自然知道摩爾定律對他們造成的致命打擊,因此,一個陰謀被以 Intel 和 Microsoft 為首的巨頭們構想出來——Intel 負責把硬件越做越快,而 Microsoft 則負責把自己的軟件越做越臃腫、越做越慢——至于你信不信,反正我是信的。因此,使用軟件、服務等,直接促進計算機產業的消費,使得計算機產業走上可持續發展的道路。這在計算機產業被稱為 Andy-Bill 定律,分別以 Intel 和 Microsoft 總裁的名字命名。
當然,軟件公司未必真心欺騙消費者,故意把軟件做大做慢——為了實現一個新功能,軟件勢必會比原先龐大。但現代軟件的速度、大小和其增加的功能并不成比例。比如對最終用戶來講,Windows Vista 到底比 Windows XP 多了多少功能呢?可能只有 20%~30%。Word 2007 對比 Word 2003 多了多少功能呢?可能也只有 20%~30%。但 Windows Vista、Word 2007 占用的 CPU、內存、磁盤空間,卻比 Windows XP 和 Word 2003 翻了幾番。究其原因,為了能趕快把新功能帶給用戶,我們不惜使用更方便但低效的編程語言(.NET、Java 等依賴虛擬機的語言就要比 C 慢許多,Python 等動態語言比 C 慢的不是一星半點)、快速開發(我們原先處理一個大文本,先分塊,一點一點讀到內存中,然后把處理完的部分寫回磁盤,清空內存;而現在直接把它全讀進來處理,開發方便,執行也快)。而用戶必須為這些新功能買不成比例的單。64 位就是在這個背景下迅速走入尋常百姓家的——程序占用越來越多的內存,而 32 位的尋址空間已不能滿足軟件運行的需要了。
64位 CPU 是指 CPU 內部的通用寄存器的寬度為 64bit,支持整數的 64bit 寬度的算術與邏輯運算。早在 1960 年代,64位架構便已存在于當時的超級電腦,且早在 1990 年代,就有以 RISC 為基礎的工作站和服務器。2003 年才以 x86-64 和 64 位元 PowerPC 處理器架構(在此之前是 32 位元)的形式引入到個人電腦領域。從 32 位元到 64 位元架構的改變是一個根本的改變,因為大多數操作系統必須進行全面性修改以取得新架構的優點。
成功的遷移
蘋果向 64 位處理器的遷移花了整整 6 年時間,遠長于該公司其他技術的遷移——向 Intel 的遷移僅用了一年時間,從經典 Mac OS 到 Mac OS X 也僅用了三年時間。總而言之,這場遷移是非常成功的:一方面,用戶基本無痛苦,老的 32 位程序在目前最新版的 Mac OS X Lion 中依然可以完全兼容地執行;另一方面,對開發者而言,基本只需做微小的調整,重新編譯程序,而且若干技術如 Universal Binary,使他們發布程序非常方便。當然,對于某些大量使用過時技術的公司,如 Adobe 和 Microsoft,這場遷移則要折騰得多。
這場遷移整整用了四個發行版的時間(10.3 至 10.6),不同于 Windows 或 Linux,Mac OS X 對 64 位的遷移自下而上,再自上而下。先是內核擴展,逐漸上升至 Unix 空間,然后上升至用戶界面,再上升至整個應用程序生態,最后完成內核的遷移。要提醒讀者的是,Mac OS X 的 32 位和 64 位內核空間與用戶空間的分配和實現,和 Windows 存在本質的區別,但在本期介紹中,我們盡可能少地把 Mac OS X 的 64 位遷移和 Windows 進行比較,不拘泥于技術細節,對此區別有興趣的讀者,請移步 AppleInsider 的系列專題。
2003 年,蘋果發布了其第一款 64 位計算機工作站 Power Mac G5。同期發布的 Mac OS X 10.3 也因此增加了非常簡單的 64 位支持,于是 XNU 內核開始支持 64 位的寄存器和整數計算。但對于用戶空間而言,程序可見的地址依然是 32 位的。程序當然可以使用大于 4GB 的內存(Power Mac G5 最高可達 8GB 尋址空間),但這要求程序手動地在兩個 32 位內存空間中來回轉換。
兩年后,蘋果發布了當時最成功的 Mac OS X 發行版 Mac OS X 10.4 Tiger。10. 4 的內核是革命性的,除了增加對內核并行多線程的支持,它把用戶空間可見的地址空間擴展到了 64 位,因此理論上用戶程序可以以 64 位方式執行。當然,在這個時期,幾乎系統內的所有程序,哪怕是內核,依然是 32 位的。系統中唯一帶的 64 位二進制文件是名為 libSystem.dylib 的系統庫。它是 Mac OS X 上對 C 標準和 POSIX 標準的支持庫,由 libc、libinfo、libkvm、libm 和 libpthread 五部分組成。但這僅有的 libSystem.dylib 理論上就能讓所有僅使用 C 標準庫和 POSIX 標準庫的程序以 64 位模式運行。當時,用戶對 64 位的需求較少,主要限于科學計算或圖形處理等需要大數組的領域。因此,10.4 能較好地滿足這部分用戶的需求。但如果程序需要調用除 BSD Unix 以外的系統調用,比如想用 Cocoa 來畫圖形界面,那么該程序僅能以 32 位方式運行了。對于一些需要 64 位尋址空間的科學計算程序,比如 Mathematica,就需要采用一些比較麻煩的做法:用一個進程調用 32 位的 Cocoa 畫圖形界面,用另一個進程調用 64 位的 libSystem 來進行運算和 Unix 系統調用,并用 Unix 管道或進程間通信的方式管理兩個進程間的輸入/輸出。
蘋果在 Mac OS X 10.4 發布同期的另一項重要決策是向 Intel 平臺 x86 及 x86_64架構的遷移。為了幫助開發者和用戶順利遷移,蘋果正式公布了 Universal Binary。Universal Binary 技術是 Mach-O 二進制文件早就具有的特性,只是在這個場合作為一個商業詞匯進行宣傳。NeXT 時代 NeXTSTEP 操作系統就支持許多種不同的硬件架構,自然可以要求開發者對每個平臺發布一個獨立的版本,但這樣的分發模式很麻煩,消費者也需要搞清到底購買哪種平臺的軟件。因此 NeXT 的 Mach 內核所支持的 Mach-O 二進制文件格式引入了一種叫 fat binary 的特性,說白了就是在一個平臺架構上分別交叉編譯所有平臺的二進制格式文件,然后把每個文件都打包成一個文件。Universal Binary 就是指同時打包 Intel 平臺和 PowerPC 平臺的二進制文件。Mac OS X 10.4 最終支持四個平臺的 BSD 系統調用——32 位 Power PC、64 位 PowerPC、32 位 x86 和 64 位 x86_64。作為最終用戶,無須搞清這些區別,因為使用 Universal Binary 技術,買回來的軟件直接會解出相應平臺程序的二進制文件并執行。這是蘋果很成功的一步——不像 Windows 系統中要用不同的路徑(\Windows\System、\Windows\System32、\Windows\System64)分別存放不同架構的二進制庫,并且用戶還需在 32 位版和 64 位版之間猶豫不決。
Mac OS X 10.5 Leopard 經過一系列跳票終于在 2007 年末發布,跳票主要原因是當時蘋果投入了大量人力和物力去做 iPhone,以至于 10.5 跳票了整整一年。10.5 包含了約 300 項新功能,而最重要的一項是蘋果把對 64 位的支持帶入了 Cocoa 層面。因此,幾乎系統中所有的庫都有四個平臺的版本。在 WWDC 上喬布斯親自向與會者介紹遷移到 64 位的好處,而能使用更大的內存自然是一項重要優勢,程序可以申請更大的內存,把所有數據一并讀入內存中操作,而無須分塊后來來回回地在內存和磁盤搬運數據。另外,對 Intel 平臺來說,x86 架構只有 8 個寄存器,而 x86_64 平臺有 16 個寄存器,這也就意味著,對該平臺來說,只要重新編譯程序,程序就能自由調度比原先翻倍的寄存器數量而無須快取或在內存中來回查找和讀寫。根據粗略估算,一般涉及大量數值計算的程序會加快一倍。所以他很開心地勸說所有的開發者都遷移到 64 位架構。
歷時整整 6 年時間,蘋果完成了向 64 位處理器的遷移,同時這也給蘋果提供了良好的清理門戶的機會——清理過時的技術和 API。
徹底的清理
同時,蘋果做出了一個大膽的舉動——Carbon 框架并未出現在這次遷移中。Carbon 是 Mac OS X 誕生之初為了幫助 Mac OS 開發者把老程序遷移到新的 Mac OS X 操作系統上所提出的一個兼容 API,這套 API 長得很像經典 Mac OS 的 API,但能夠得到 Mac OS X 平臺提供的一切新特性,Adobe、Microsoft 等都是通過 Carbon 把它們經典的 Mac OS 程序移植到 Mac OS X 上的。蘋果的本意是希望開發者用 Carbon 遷移老程序,用 Cocoa 開發新程序,但在 Carbon 誕生之初,其受關注度遠大于 Cocoa,據 TeXShop 開發者 Dick Koch 回憶,在 Mac OS X 剛誕生的開發者大會上,Carbon 講座的教室擠滿了人,而 Cocoa 相關的講座上聽者無幾。維護兩套雷同的 API 的代價自然很高,所以砍掉一個是大勢所趨。Carbon 和 Java 的熱度甚至一度讓蘋果產生索性把 Cocoa 或 Objective-C 砍掉的想法。大量蘋果自家的程序如 Finder、iTunes、Final Cut、QuickTime 等也都是用 Carbon 寫成的。不過在此后由于大量涌現在 Mac OS X 平臺上的新程序都是 Cocoa 寫的,導致 Cocoa 技術不斷走高。2007年的 iPhone 也完全依賴于 Objective-C 和 Cocoa 的一個裁剪版 Cocoa Touch。因此在 WWDC 2006 上,蘋果在 Mas OS X Leopard 10.5 的開發預覽版中包含了測試版本的 64 位 Carbon 庫,甚至還有講座教如何開發 64 位的 Carbon 程序。但蘋果卻在 2007 年告訴 Carbon 開發者,他們的程序將不可能再被編譯成 64 位,要做到這點,必需先把程序用 Cocoa 重寫。
這個突然的決定激怒了很多開發者,尤其是以 Microsoft 和 Adobe 這些巨頭為代表的公司。Adobe 全套的 Creative Suite 和 Microsoft 全套的 Microsoft Office 是很多蘋果用戶必備的軟件,數百萬行代碼全是用 Carbon 寫的。所以直到今天,除了 Adobe Photoshop 等少數程序終于在 2010 年全面移植到 Cocoa 后做出了 64 位版,其他大部分程序依然停留在 Carbon 的 32 位模式。
蘋果也花了很長時間來重寫 Finder、FinalCut、iTunes、QuickTime 等程序或技術,耗費了大量精力。當 Adobe 發布 64 位的 Lightroom 2.0 時,蘋果還在手忙腳亂地重寫 Aperture。不過公正地講,長痛不如短痛,砍掉對 Carbon 的支持能夠使蘋果把更多精力放在該做的事上,也使得 Mac OS X 的結構更簡潔,并且事實上,64 位的遷移為蘋果提供一個砍去老 API 的機遇,哪怕對 Cocoa 也是。一方面,Cocoa 框架中很多類不是使用類似 Carbon 的 API,就是依賴于用 Carbon 實現(注意,和傳統觀念不同,Carbon 和 Cocoa 在早期 Mac OS X 上是相互依賴的,比如菜單 NSMenu 就使用了 Carbon 的菜單管理器),這些 API 在 64 位得到了徹底清理,QuickTime 相關的 C 接口全被砍去。Cocoa 經過很長時間的發展,自然也保留了很多過時的 API 以保證和原先的產品兼容,而這次機會給蘋果足夠的理由徹底推翻原先的設計。在 Mac OS X 10.5 中, Objective-C 的運行庫 libobjc 更新到 2.0,提供了全新的并發、異常處理、自動內存回收、屬性(property)等新機制,其中很多新特性只供64位享用。同時,所有 int 都被改為 NSInteger,Core Graphics 中的 float 都改為 CGFloat,以保持 API 統一,這些都是 64 位架構上的改動。因此 64 位遷移給蘋果一個很好的清理門戶的機會。
作為相反的例子,這次清理也有不徹底的地方。比如從老版 Mac OS 中混進來的 Keychain 庫,甚至具有 Pascal 風格的 API,由于沒有替代品,它也得到了 64 位的更新。所以類似 keychain 這樣的庫成了現在 Mac OS X 程序員的噩夢。我每次用到 Keychain 都有痛不欲生的感覺。
而 2009 年發布的 Mac OS X 10.6 Snow Leopard 則是對 64 位真正完整的支持。Unix 層雖然 10.4 就提供了 64 位的 libSystem,但所有的 Unix 用戶空間工具包括 ls、Python 等,以及 Xcode 中的 gcc,也都是以 32 位二進制的模式發布的。圖形界面層,在 10.5 Leopard 中,雖然整個系統的庫都遷移到 64 位,以 32 位和 64 位的混合模式發布,但用戶應用程序依然是 32 位的。只有 Chess、Java、Xcode 套件等少數程序以 64 位編譯。但在 10.6 中,基本所有的應用程序都被遷移到 64 位,不管是 Safari、Mail、Dock,還是 TextEdit。當然,各種 Unix 工具包括 LLVM、GCC 等也都以 64 位的模式發布。10.6 只有四個 Carbon 程序(Front Row、iTunes、DVD Player 以及 Grapher)未得到 64 位升級【2009 年查閱,現頁面已更新至 10.7】。其中, Front Row 在 Mac OS X 10.7 Lion 中被砍掉, iTunes 在 10.7 發布時依然以 32 位模式發布,在 2011 年末的更新中才遷至 64 位。
為了使應用支持 64 位,蘋果不遺余力地改寫了大量代碼,Snow Leopard 中最重要的重寫當屬 Finder,這個程序自 Mac OS X 發布以來就一直是一個 Carbon 程序,并且蘋果一直不停地改進它以展示 Carbon 無所不能。但自從 10.5 時代蘋果下決心砍掉 Carbon 后,該程序被完整地重寫。新的 Finder 和 Carbon 版的 Finder 看上去并沒有太大差別,但 Finder 使用 Cocoa 重寫后,不僅速度更快,而且增加了許多 Cocoa 新特性,比如加入了更多的 Core Animation 特效來平滑過渡動畫。總之,雖然蘋果在 10.6 期間沒有提供太多新功能,但這樣大規模的重寫,為今后代碼的可維護性奠定了良好的基礎。
Mac OS X 10.6 發行版也完成了 64 位化的最后一步——內核的 64 位化。
半導體的豐收(中)
經過 6 年時間,4 個發行版,蘋果終于完成了向 64 位的遷移,并隨著 Snow Leopard 的發布推出了解決并行編程問題的 Grand Central Dispatch(簡稱 GCD)技術,釋放了多核系統的潛力。
和 10.5 一樣,在 10.6 Snow Leopard 中,蘋果繼續利用 64 位的遷移砍掉了諸多老技術,很多新技術僅以 64 位的模式被支持。例如重寫的 QuickTime X 框架,雖然 QuickTime X 應用程序以 32 位和 64 位的模式發布,但其 API 僅暴露給 64 位。另一個例子是 Objective-C 2.1 的運行庫,快速 Vtable 調度,新的和 C++ 統一的異常處理模型,以及徹底解決對象的 FBI 問題等,都僅限 64 位程序使用。
內核的 64 位化
讀者應該發現,經過這 4 個發行版,Mac OS X 自下而上地對整個系統向 64 位遷移。10.3 內核空間提供了 64 位整數運算的支持。10.4 允許程序以 64 位模式運行在用戶空間,并且提供了 64 位的 libSystem 使得開發者可以開發 64 位的 Unix 程序,而 10.5 中系統所有未廢棄的函數庫、框架都提供 64 位版本,到了 10.6,所有用戶空間的程序,包括 Unix 層和圖型界面層,基本都更新到 64 位。細心的讀者不禁會問—那內核是 64 位的嗎?是的,自下而上支持 64 位后,10.6 又從上往下,遷移了整個系統中最后一個也是最重要的部分—內核。
內核 64 位化的意義
對于 Windows、Linux,以及 FreeBSD 等操作系統,64位實現的第一步是實現 64 位的內核。然而 Mac OS X 卻反其道而行。主要原因是,反正 32 位的內核也能以非模擬、非兼容的方式原生地運行 64 位用戶空間程序,而內核和與內核動態鏈接的驅動,很少需要用到 64 位的尋址空間(你什么時候見過內核本身使用 4GB 內存?),所以該問題可以暫緩。
但要記住,用戶空間的內存是由內核管理的,虛擬內存、內存分頁等機制,都是由內核一一實現的。一旦在不久的將來,隨著用戶空間的內存占用越來越多,虛擬內存的分頁比也會不斷膨脹。比方說,一個用戶程序使用 4GB 的空間,每個分頁包含 4KB 的頁面,那么總共有 1M 個頁面。因此,假設一個頁面需要 64B 的 PTE 來記錄該頁的位置,那總共也就需要 64MB 的內核空間來記錄這個用戶空間程序的虛擬內存,不算太多。而在不久的將來,如果一個 64 位用戶程序使用 128GB 的空間,則需要 32M 個頁面,每個頁面 64B 的 PTE 會導致 2GB 的內核地址空間來尋址(暫不考慮大分頁)。32 位的內核就顯得非常緊張。
另外,上一期我們也提到 64 位的 Intel 架構提供了比 32 位多一倍的寄存器,因此,用戶空間程序對 64 位內核的系統調用也會更快。根據蘋果的數據,系統調用的響應速度比原先快了 250%,而用戶空間和內核空間的數據交換也快了 70%,因此,64位內核要比 32 位內核更快。
內核完成 64 位遷移
雖然在 Mac OS X 10.6 中,蘋果提供了 64 位模式運行的內核,但在大部分蘋果計算機上,這個特性并不默認啟用。其原因是,雖然 64 位程序和 32 位程序可以在計算機上同時運行,但 64 位的程序只可以加載 64 位的庫或插件,32位程序只能加載 32 位的庫或插件。因此,如果默認使用 64 位模式啟動,則諸多第三方的 32 位驅動或內核模塊將無法使用。當然,用戶可以通過修改 com.apple.Boot.plist、nvram,或開機按住 6 和 4 強制加載 64 位內核,不過蘋果并不推薦這樣的方式。直到 Mac OS X 10.7 時,第三方內核擴展已趨完善,大部分的 Mac 才默認使用 64 位內核模式啟動。
蘋果用了整整 6 年的時間完成 64 位的遷移,在 2009 年 WWDC 的一個講座上,Bertrand Serlet 告訴開發者,我們這個 64 位技術的講座,只針對 Mac OS X,而 iPhone、iPad 等 iOS 設備,由于使用 ARM 平臺,在可預見的未來可能并不會支持 64 位技術。
不過兩年之后的 2011 年 10 月 27 日,ARM v8 發布,ARM 正式宣布支持 64 位。未來會不會出現基于 ARM 的 Mac,或是 64 位的 iPad,除了蘋果,誰知道呢?
Bertrand Serlet 在 WWDC 2009 上介紹 Snow Leopard 的 64 位和 Grand Central Dispatch 技術
GCD(Grand Central Dispatch) 來臨
很長一段時間以來,處理器靠更快的運行時鐘來獲得更高的效率。軟件開發者無需改動或重新編譯他們的代碼,就能得到摩爾定律許諾他們的好處,因為處理器順序地執行計算機指令,新一代的處理器就自動會跑得比原先更快。后來每每達到一個技術極限時,總有一些聰明的方法繞過這些極限,比如超純量、指令管線化、快取等,不是悄無聲息地把多條互相獨立的指令同時運行,就是隱藏掉數據讀寫的延時。
GCD 出現的緣由
到了 21 世紀,能想的辦法基本都想盡了——現代處理器已經足夠并行了,也采取了各項優化來不斷提升各種預測器的準確率,而時鐘頻率卻是不能無限提高的——提高時鐘頻率會極大地增加處理器的產熱,使得服務器機房或筆記本的散熱成為一個頭痛的問題。同時對于便攜設備而言,高頻也意味著短得多的電池時間,因此摩爾定律正在經受重大的考驗。
因此大約在 21 世紀頭十年過掉一半時,“多核”處理器,終于開始躍入普通消費者的視線。“多核”顧名思義,就是把原先單核的半導體線路復制多份排于同一裸片上,每個核相互獨立,又能彼此通信。多核處理器的出現,有效緩解了計算機處理器生產商的設計和制造壓力,從而達到忽悠消費者買更新款產品這一不可告人的目的。
但這一次技術革新,并不如之前那么順利,因為程序并不會自動在多核系統上跑得更快,甚至有很多程序每一步都有前后依賴,不能高效地并行運行。即使能夠高效并行的程序,也需要大規模改寫才能充分利用多核所帶來的優勢。
傳統的并發編程模式,就是學習使用線程和鎖。這聽起來很簡單,幾句話能說明白:
但是實際操作起來,多線程程序的編寫要比單線程難上不止一個數量級。一方面,調用大量內存和數據反復的加解鎖本身效率就非常低下;另一個重要原因在于,由于多線程程序可能以任意的次序交錯執行,程序再也無法像順序執行時那樣產生確定的結果。多線程程序看似容易編寫,但難分析、難調試,更容易出錯。即使是最熟練的開發者,在茫茫線程和鎖之間,也會迷失方向。且程序的錯誤在很多時候甚至是不可重現的。所以,程序員使用線程和鎖機制編寫并行程序的代價是很高的。
GCD 就是在這種背景下被蘋果提出來的。2008年最初提出但未公布細節時,很多人懷疑它是 FreeBSD 的 ULE 調度器在 Mac OS X 上的實現。ULE 是 FreeBSD 當時最新的內核調度器,用來替換掉老一代的 4BSD 調度器,當時使 FreeBSD 上跑多線程程序的效率獲得了重大的性能提高,遠高于同期 Linux 和 Solaris 的算法效率。但當時我就認為 GCD 依賴 FreeBSD 這項技術的可能性不大,因為 Mac OS X 中管理進程和線程主要用的是 Mach 而不是 BSD。不過后來證實我只猜對了一半,GCD 的實現,實際上是依賴于 FreeBSD 的另一項技術 kqueue。kqueue 是一個由 FreeBSD 4 時代引入的新功能,內核級別地支持消息通信管理。GCD 的隊列,其實就是用 kqueue 實現的。
GCD 出現的意義
在 GCD 中,開發者不再管理和創建線程,而是將要實現的運算抽象成一個個任務,一起扔給操作系統,轉而讓操作系統管理,這在計算機科學中,被稱為線程池管理模式。
在 GCD 中,開發者使用很簡單的方式就能描述清應用程序所需執行的任務,以及任務之間的相互關聯。每一個任務在代碼中被描述成塊(block),然后開發者把一個一個塊顯式地按順序扔到隊列(queue)中。使用塊和隊列兩個抽象的表述,開發者無須創建線程,也無須管理線程,更無須考慮數據的加解鎖。換之而來的,是更簡短可讀的代碼。剩下的事,全都扔給操作系統去完成。
在操作系統那邊,GCD 在程序運行時,管理著一定數量的線程,線程的數量是自動分配的,取決于用戶計算機的配置和用戶程序運行時的負載。多核工作站每個程序配到的線程,自然就會比單核手機或雙核筆記本來得多。而且這個線程的數量是會動態變化的。當程序非常忙時,線程數會相應增多,而當程序閑置時,系統會自動減少其線程數量。然后,GCD 會一一從隊列中讀入需要執行的塊,然后扔到線程上并發執行。
相信讀者已經看出 GCD 和傳統線程-鎖機制的區別來了。傳統的方式按勞分配,強調程序自由獨立地管理,妄想通過“無形的手”把系統資源平均分配,走的是資本主義市場經濟的道路。而 GCD 按需分配,真正實現了社會主義計劃經濟管理模式。因此在政治上 GCD 就是一個代表先進生產力的計算機技術(我被自己雷了,但事實就是這樣)。
GCD 是一個自底向上的技術,它實際上由以下 6 個部分組成。
GCD 還有一些工程上的優勢。首先,程序的響應速度會更快。GCD 讓程序員更方便地寫多線程程序,因此寫一個多線程程序來實現前后臺簡單多了,極大改善了 Mac OS X 上應用程序的生態環境。而且 GCD 的代碼塊隊列開銷很小,比傳統線程輕量得多。統計表明,傳統的 Mac OS X 上使用的 POSIX 線程需要數百個計算機匯編指令,占用 512KB 的內存,而一個代碼塊隊列才用 256 字節的長度,把塊加入隊列,只需要 15 個計算機匯編指令,因此開成百上千個也不費什么事。
其次,線程模式是一種靜態的模式,一旦程序被執行,其運行模式就被固定下來了。但用戶的計算機配置各不相同,運行時別的程序有可能耗用大量的計算資源。這些都會影響該程序的運行效率。而動態分配系統資源則能很好地解決這個問題。蘋果自然也是不遺余力地忽悠開發者使用 GCD,因為各個軟件共享多核運算的資源,如果 GCD 被更多的開發者采用,整個蘋果平臺的生態也就更健康。
而最重要的,還是 GCD 采用的線程池模式極大簡化了多線程編程,也降低了出錯的可能性。著名 FreeBSD 開發者 Robert Watson 還發布了一個他修改過的 Apache,并釋出了補丁,聲稱只需原先 1/3 至 1/2 的代碼量,就實現了原先的多線程模塊,并比原先的效率更好。
如何應用 GCD
當然,老王賣瓜,自賣自夸,沒有實際的例子,是不能讓讀者信服的。下面我們就來簡單講解 GCD 的技術。
首先是塊狀語法,是一個對 C、C++ 和 Objective-C 語言的擴展。用來描述一個任務,用^引導的大括號括起來。比如最簡單的:
則 x 就變成了一個塊。如果執行:
那么程序會打印 hello world 出來。當然,blcok 像函數一樣,可以跟參數,比如:
這里 MyBlock 是一個帶參數的代碼塊。
讀者看到這里不禁要問,塊到底有什么好處?它和 C 的函數指針有什么不同?我們依然用上面的例子來說明問題,雖然后面我們把 spec 變量改為 0,但事實上在 MyBlock 創立時,已經生成了一個閉包,因此它最后輸出的結果,仍是 16,不受 spec 值改動的影響。這對于搞函數式編程的人來說再熟悉不過了,因此很多開發者親切地稱呼塊語法的 C 擴展為“帶 lambda 的C”。
有了閉包功能的 C 頓時牛起來——你可以把函數和數據包裝在一起——這就是塊的真正功能。因為只要一個閉包包含了代碼和數據,它的數據就不會被別的閉包輕易改動,所以在它執行時,你根本不用為數據上鎖解鎖。
有了一系列的代碼塊后,接下來的事是把代碼塊扔到隊列里。比如最簡單的:
dispatch_queue_t queue = dispatch_get_global_queue (0,0);
來創建一個輕量級的隊列,然后
dispatch_async (queue,
^{printf (“hello world\n”);});
那這個代碼塊就被扔進 queue 這個隊列中了。你可以手動依次添加任意多個項目,比如“帶著老婆”、“出了城”、“吃著火鍋”、“唱著歌”、“突然就被麻匪劫了”等。當然在更多的場合,你會更傾向于使用自動事件源,每當一個事件觸發時(比如定時器到點、網絡傳來包裹,或者用戶點擊了按鈕),相應的代碼塊被自動添加到隊列中。
一旦隊列不是空的,GCD 就開始分配任務到線程中。拿上面的例子來說,“老婆”、“城”等變量可是封在閉包里的,所以在運行時,不用考慮它們被某個別的閉包改掉(當然也有方法來實現這個功能)。總體而言,這個模式比線程-鎖模型簡單太多——它的執行是并行的,但思維卻是傳統的異步思維,對沒有學習過系統多線程編程的開發者來說,依然能很容易地掌握。
讀者可能要問,如果閉包之間有復雜的依賴關系,需要申明某兩個操作必須同步或異步怎么辦?比如“出了城”必須在“吃著火鍋”之前。在 GCD 中,可以使用 dispatch_async 和 dispatch_sync 來描述這樣的依賴關系,而在 Cocoa 層面,NSOperation 中的隊列依賴關系甚至可以被描述成有向圖。
GCD 得到廣泛應用
GCD 一經推出就得到了廣泛的應用。蘋果自家的軟件 Final Cut Pro X、Mail 等軟件,都采用 GCD 來實現任務并發和調度,因此 Mac OS X 10.6 成為了有史以來最快的發行版。從 iOS 4 開始,iPhone 和 iPad 也加入了 GCD 的支持。更別提原來使用 Cocoa 的 NSOperation 相關接口的程序,無需改動即享受 GCD 的優惠。
GCD 在 Mac OS X 10.6 發布后,又以 libdispatch 為名,作為一個獨立的開源項目發布。 所需的外圍代碼,如編譯器的塊支持、運行庫的塊支持、內核的支持,也都能在 LLVM 和 XNU 等開源項目代碼中找到,所以很快被別的操作系統采用。作為 Mac OS X 的近親, FreeBSD 在一個月后即完整移植了整套 GCD 技術,并最終在 FreeBSD 9.0 和 8.1 中出現。諸多 Linux 發行版也提供 libdispatch 的包,使用 Linux 內核的 epoll 來模擬 FreeBSD 的 kqueue。2011年 5 月 5 日, Windows 的移植工作也宣告完成。
另外,GCD 也成為拯救動態語言的重要法寶。由于受 GIL(全局解釋鎖)的限制,動態語言雖然有操作系統原生線程,但不能在多核處理器上并行執行。而 GCD 成功繞開了這個限制,如加入 GCD 支持的 Ruby 實現 MacRuby 就能在多核處理器上高效執行。 因此,在蘋果生態圈以外,GCD 也會得到越來越多的應用。
半導體的豐收(下)
隨著 CPU 與 GPU 合并成技術發展的趨勢,蘋果開發出了 OpenCL 框架,能夠進行高速并行處理的能力使 OpenCL 成為了業界標準,被廣泛應用。
最近幾年,GPU 的發展吸引了很多來自科學計算界人士的目光。GPU 有穩定的市場推動力——公眾喜聞樂見的電子游戲產生了源源不斷的升級 GPU 的需求——因此比 CPU 的更新步伐更快。從技術上講,GPU 本身就是多核架構,高端顯卡往往有五百多個核心,即使低端的集成 GPU 也有二三十個核心,所以能夠通過并行來高效處理成千上萬的線程。同時,對于科學技算中的浮點計算,GPU 往往通過硬件加速使其效率比傳統 CPU 更高,因為圖形渲染等工作基本都是浮點計算。
GPGPU 浮出水面
早期的 GPU 只能執行固定的程序,而不開放給程序員編程。隨著時代的發展,圖像處理有時需要對著色器進行編程以實現一些特效,因此需要程序員可以使用 GPU 的匯編語言寫簡單的著色程序。這自然對程序員要求過高,所以一些高階的著色語言又被 GPU 廠商開發出來。比如微軟和 NVIDIA 共同開發的 Cg 語言,就能為頂點和像素編寫專門的著色程序。這類技術雖然面向圖形渲染工作者,卻吸引了一小簇科學計算研究者的興趣。以計算流體力學為例,它是用納維斯托克斯方程【注:把牛頓第二定律和質量守恒應用到流體后,所得到的偏微分方程】來求解流體力學問題的一種算法,廣泛用于天氣預報、F1 方程式賽車設計等工程領域。同時,對于電影制片特效,計算流體力學也是最基本的用來模擬流體流動特放的算法,皮克斯動畫工作室的《尋找尼莫》中的海洋流動和水花等,都是使用納維斯托克斯方程來模擬的。
首先,對于一個幾何空間進行網格化,每個網格中的流體,都可以列出納維斯托克斯方程,把這些方程聯立起來進行求解,即可得到各點的溫度、壓力、濕度、速度等流體信息。整個求解過程可以高度并行,因為每個網格的控制方程是完全一樣的;同時也牽涉大量的浮點運算。但 Cg 這類語言并非面向普通的計算,其變量都是顏色、頂點、像素等圖形學專用變量。來自北卡羅萊那大學教堂山分校的 Mark Harris 突發奇想:可以把流體力學中每個網格的速度、壓力等變量,存成 RGBA 顏色后讓 Cg 去處理,所以他在《GPU Gems》中著名的一章,公布了使用 Cg 來高速實現計算流體力學運算的成果,吸引了大量計算界的目光。然而,這種編程模式對科技工作者來說很不友好,因為這要求一個學力學的、學生物的、學化學的學生,先要明白復雜的 GPU 渲染原理,了解圖形學中材質、頂點、合成、像素、光柵化、光線跟蹤等深奧的理論,才能編寫他們專業相關的 GPU 程序。
GPU 生產廠商洞察到了 GPU 高速并行浮點數運算的潛力,所以 GPGPU(General Purposed Graphics Processing Unit)概念終于浮出水面。一方面 GPU 設計一代比一代可編程化,另一方面各公司也在加緊研制新一代 GPU 編程語言。新一代的語言對比 Cg,去掉了對于渲染相關的知識要求,獨立于圖形學之外,是純粹的普通語言,比如變量不再是像素、頂點、面等類型,而是 C/C++ 語言開發者喜聞樂見的浮點數組、整形數組等。這一時期為代表的語言,主要是 CUDA(Compute Unified Device Architecture)。CUDA 是 NVIDIA 在 2007 年公布的一項面對科學計算工作者的編程框架。通過該技術,使用者可利用 NVIDIA 的 GeForce 8 以后的 GPU 和較新的 Quadro GPU 進行高性能編程。用戶先編寫一個特殊的 C++ 代碼文件,擴展名為 cu,文件中需要申明創建的變量、GPU 計算核心(kernel)以及使用給定的編程接口來實現變量在 CPU 和 GPU 中的傳送。然后通過 NVIDIA 自家的編譯器編譯這個代碼,鏈接到 NVIDIA 自家的庫上,即可把該運算核心編譯為 GPU 匯編語句扔到特定型號的 GPU 上高度執行。其他廠家也緊隨其后,比如 AMD 為 ATI 生產的 GPU 卡提供了一個類似的框架叫 Stream SDK(先前被命名為 CTM, Close to Metal, ATI Stream Computing – Technical Overview, 03/20/2009 http://en.wikipedia.org/wiki/Close_to_Metal)。而微軟更是趁 Vista 和 Win7 推出了 DirectCompute,作為旗下 DirectX 技術的一部分。
CUDA 并不完美
對科學工作者來說,CUDA 比 Cg 友好太多。使用 CUDA 加速流體力學運算相關的論文更是雨后春筍般涌現。然而不久后,我發現它存在許多問題。
首先,對初學者來說,CUDA 編程模式很容易學混。因為一個 GPU 數組和一個 CPU 數組在 CUDA 中的表述都是同樣的C指針,但對于 GPU 數組和 CPU 數組,CUDA 的處理模式完全不同,CPU 數組使用常規的 malloc 來初始化,而 GPU 數組得使用 CUDA 提供的 malloc。所以程序寫著寫著,就忘了一個變量到底是給 CPU 用的還是給 GPU 用的,這無疑增加了學習難度。同時,CUDA 對 C/C++ 語言進行了一系列擴展,這不但意味著寫的程序不再具有 C/C++ 那樣良好的可移植性,而且這種計算核心和傳統 C 程序混寫的編程語言很不美觀。
其次,CUDA 這類語言的實現各自為政。如果你寫了一個 CUDA 程序,就意味著這個代碼只能運行在 NVIDIA 的顯卡上。如果想使用 ATI 的顯卡呢?沒門,請用 ATI Stream SDK 重寫。
再次,CUDA 是在編譯時就靜態產生 GPU 代碼的,所以只能產生特定的 GPU 代碼。如果你發布了一個 CUDA 程序,它僅對某幾種 NVIDIA 顯卡進行特定的代碼優化。如果 NVIDIA 自家出了一種新顯卡,很抱歉,哪怕新顯卡可能兼容老顯卡的匯編指令而你的程序恰巧可以在新顯卡上跑起來,你也無法發揮新顯卡的所有特性。必須用針對新顯卡的編譯器重新編譯源代碼,才能夠保證程序在新顯卡上高效執行。
最后,CUDA 這類語言僅能產生高效的 GPU 代碼,而無法產生 CPU 代碼,即:寫完的代碼只能跑在 GPU 上,在 CPU 上只能“模擬執行”,僅供調試用。所以在一臺不具備給定 GPU 的機器上,無法高效運行 CUDA 程序。同樣,如果你有一個性能很強的工作站,那么你的 CPU 亳無用處——CUDA 不可能分配一部分任務給 CPU 完成。
另外還有未來計算機架構的不確定性。當時,GPU 越來越一般化,可以跑多種數值計算程序,而 CPU 隨著多核成為主流也越來越像 GPU。所以很多廠家在考慮 CPU 和 GPU 合并的可能性。
當時轟動一時的熱門事件,是 CPU 廠商 AMD 買下了 GPU 廠商 ATI,來開發下一代處理器 AMD Fusion,把 GPU 和 CPU 合并到一起。Intel 自然不甘示弱,做出了 Nehalem 平臺,在該平臺上,CPU 和集成 GPU 處于同一個包裝中,外界一度猜測這樣可使合并后的 CPU 具有圖形處理工能,從而用戶購置計算機就不用再考慮配一塊 GPU 了。
更強大的是,當時 Intel 還公布了 Larrabee 計劃,讓 GPU 支援 x86 指令,使得一個常規的 x86 平臺的程序不需要修改和重新編譯便可在 GPU 上運行。
雖然事實和這些預期有稍許出入,但當時的技術趨勢是:在將來可能出現一種新的合并 GPU/CPU 的技術,能夠并行高速地運行一般的計算機程序,而面對這樣新的可能的平臺,我們如何準備?
OpenCL 誕生
OpenCL 則是蘋果為這個新局面畫下的藍圖。這項技術初期全稱為 Open Computing Library(如果留意蘋果早期宣傳廣告的話),后改名為 Open Computing Language。這項技術從本質上來說,和 CUDA 并沒有太多的兩樣,但由于蘋果在借鑒他人技術并把他人技術改得更棒這一點上是出了名的,所以 OpenCL 很好地解決了以上所有問題。
下面簡單介紹一下這個框架。OpenCL 技術的結構十分清晰,對程序員來說,它是一個 Mac OS X 的 Framework,定義了兩套標準,一套是一個 C 語言的編程界面(API),使得開發者創建、拷貝、回收 GPU 使用的對象,同時也包含檢測處理器、為該處理器編譯并調用核心程序(kernel)相關的接口;另一套是 OpenCL 核心程序語言的定義,是一套基于 C99 發展而來的語言。
例如我們有兩個大數組,1024 維的 a 和 1024 維的 b(當然,1024不算大,OpenCL 往往用來處理十萬、百萬數量級的任務),我們把兩個數組對應的元素加和,結果是一個 1024 維的數組c。C 程序員很容易能寫出下面的程序:
OpenCL 的核心程序,則是取每個獨立的可并行的循環分支,即上面程序中的 c[i]=a[i]+b[i]。所以核心程序大概是下面這樣:
其中,get_global_id () 函數可以返回當前函數是全局中的第幾個元素。把該程序保存為 add.cl,就是一個 OpenCL 的核心程序,為 C99 語言的一個子集。
使用 OpenCL 的 API 就能調用這個核心程序。每個 OpenCL 程序基本上是模式化地照搬下面流程:
1. 探測硬件(用 clGetDeviceIDs 函數護取計算設備(可以指定使用 GPU 或是 CPU),用 clCreateContext 函數來新建一個上下文(context),用 clCreateCommandQueue 函數針對設備和上下文新建一個命令隊列);
2. 編譯核心(讀入 add.cl,用 clCreateProgram-WithSource 和 clBuildProgram 以及 clCreateKernel 來編譯讀進來的字符串,產生一個核心程序);
3. 寫入數組(用 clCreateBuffer 創建a、b、c三個內存對象,用 clEnqueueWriteBuffer 把 C 數組寫到內存對象中);
4. 運行核心(把內存對象作為核心程序函數的輸入參數執行這個核心,程序會并發為 1024 個線程,每個線程執行一次相應的加法運算);
5. 讀出結果(用 clEnqueueReadBuffer 讀取c內存對向,寫為C的數組);
6. 回收內存。
OpenCL 之美
讓我們逐條來看前面那些問題是如何被解決的。
首先,OpenCL Framework 由 C API 和 OpenCL 語言組成,涇渭分明,所有的 GPU 變量在 C API 中,都是內存對象的形式出現,有別于 C 自建的數組。因此,你永遠不會搞混兩者。同理,OpenCL 核心程序是獨立在 C 源程序之外的,不僅美觀,也能保證你的 C 程序能被所有 C 編譯器編譯,因為調用 OpenCL 庫和調用其他 C 的函數庫沒有任何不同。
其次,蘋果開發出 OpenCL 后,覺得該技術甚好,索性聯合 AMD、ARM、ATI、TI、Intel、IBM、Nokia 等公司,把它做成一個由 Khronos 組織主持的開放標準。不管電腦上用的顯卡是 ATI 的還是 NVIDIA 的,OpenCL 都能像 OpenGL 那樣在你的設備上無縫運行。事實上,OpenCL 已同 OpenAL 和 OpenGL 一樣,成為 Khronos Group 旗下的三大業界標準。
再次,CUDA 是在編譯時就靜態產生 GPU 代碼的,所以只能產生特定的 GPU 代碼。而 OpenCL 的核心程序(kernel)是在運行時被編譯成 GPU 指令的。由于 kernel 所用的 OpenCL 語言,僅是 C99 的一個子集,所以負責編譯這個程序的是 OpenCL 運行庫自帶的 LLVM-Clang。這樣做的好處是明顯的,舉例來說,如果用戶有一堆 OpenCL 的程序,比如蘋果最新的 Final Cut Pro X 就在許多地方采用了 OpenCL,如果某一天硬件廠商發布了一個全新的 GPU 架構,那么用戶安裝顯卡后,只要下載或更新相關的驅動程序和運行庫即可,而不需要再求軟件廠商發布一個新版本的 Final Cut Pro X。因為 OpenCL 在運行時,會根據顯卡廠商提供的驅動和新運行庫自動優化程序到特定架構上。所以,程序兼容性問題也被圓滿解決。
最后,由于 OpenCL 是個開放標準,也支持 CPU 和其他任何計算設備,比如數字信號處理芯片(DSPs)和各種專門的處理器架構。所以只要有相關的驅動和運行庫,OpenCL 程序可以高效地并行運行在任何架構的運算設備上。由于 OpenCL 和 GCD 的編程模式是一樣的,因此當 OpenCL 程序在 CPU 上執行時,是跑在 GCD 隊列上的。
由于 OpenCL 能高速地進行并行處理(如 http://macresearch.org/opencl_episode1 的演示,OpenCL 編寫的 GPU 程序比單核 CPU 能快上數十至數百倍,筆者的論文 Yue Wang, Ali Malkawi, Yun Yi, Implementing CFD (Computational Fluid Dynamics) in OpenCL for Building Simulation, 12th Conference of International Building Performance Simulation Association, 2011 也得出了類似的結論),OpenCL 被廣泛地使用在很多產品中,蘋果也是 OpenCL 的主要用戶之一。如上面提到的 Final Cut Pro X 就是個典范,使用 GCD 和 OpenCL 進行大量并行的流媒體處理。在老版本 Final Cut 中,每當用戶執行一次流媒體操作,都會彈出一個進度條來告訴用戶剩余的處理時間,而 Final Cut Pro X 優化后的速度是如此實時,以至于這個進度條被去除了。Mac OS X 許多的底層庫也使用 OpenCL 重寫,如 Core Image,本身也是一個 GPU 加速庫,使用 OpenCL 后相比原來,依然獲得了可觀的性能提升。
Snow Leopard 的發布標志著第一個 OpenCL 框架的完整實現,OpenCL 成為業界標準后,AMD 拋棄了原先的策略,投入開放標準的懷抱,一連放出了幾個測試版本的集成 OpenCL 的 ATI Stream SDK,并在 2009 年年底發布了穩定版,2011年 8 月 8 日宣布廢除原先的 Close to Metal 相關技術。NVIDIA 也是早早地在 CUDA SDK 中加入了 OpenCL 相關的庫。CUDA 越來越不被看好,所以 NVIDIA 索性把 CUDA 發布為一個開源項目,并把 CUDA 架構在 LLVM 之上。這和 OpenCL 近幾年的走強有很大關系。
開發者的瓶頸
目前看來,OpenCL 雖然解決了上面的所有問題且速度飛快,但對普通程序員來說,依然是非常底層的技術。而且由于硬件的限制(顯卡不支持指針運算),很多 C 的標準并未在 OpenCL 中出現,寫鏈表還需要用整數去模擬地址。程序員需要手動管理內存,處理底層的核心調用以及數據讀寫。而顯卡廠商也大多不愿公開 GPU 的技術細節,因此不像 CPU 程序很容易通過匯編指令分析計算機底層干了什么,顯卡對于開發者純粹是個黑盒,把整個問題分成多少個線程并發也沒有一個規律可循,有可能不起眼的改動會使程序運行瞬間變快或變慢數十倍,開發者也不知道其中的原因,只能憑經驗操作。而且由于不存在良好的調試工具,所以很難改正程序的錯誤。
顯卡作為系統最為重要的共享資源之一,不像現代操作系統那樣提供內存保護機制,因此一個用戶 OpenCL 程序的錯誤很容易導致整個計算機崩潰,所以經常是程序跑一遍后發現操作系統掛了,重啟后發現了一個可能的錯誤,改完后編譯運行,操作系統又掛了。我用 OpenCL 編寫科學計算程序時,大量時間是在重啟電腦而不是寫程序。這些問題仍然阻礙著 OpenCL 被廣泛采納,不過,在科學計算界,已經涌現出了越來越多相關的論文和技術,相信在不久的將來,情況會有所改觀。
結語
當寫完這篇技術長文時,天色已晚,走出教室,和 ENIAC 擦肩而過。ENIAC 的出現激勵了之后一次次的處理器革命。2009 年發布的 Snow Leopard 可能在整個 Mac OS X 發行版歷史中不算最出彩,卻是對于半導體集成電路革命的一次重大收獲。
Mac OS X背后的故事(十)Mac OS X 文件系統的來龍去脈
(上)
HFS+ 和 UFS 文件系統同時被引入早期的 Mac OS X,隨著若干年的發展,HFS+ 提供的功能已超越 UFS,使其在 Mac OS X 10.5 之后成為成為唯一正式的 Mac OS X 系統,但因為其背負許多的歷史包袱,為考慮兼容性,這些陳舊的設計并不能被推翻重來,所以蘋果開始秘密研發下一代的文件系統。
著名 BSD 開發者 Marshall Kirk McKusick
UFS:經典的 Unix 文件系統
在 Unix 系統剛誕生的遠古時期,文件系統被簡單地稱為 FS。FS 只包括啟動塊、超級塊(處于硬盤分區開頭用來保存文件系統信息)、inodes(索引節點)及數據。FS 文件系統在 Unix 系統剛誕生時還能滿足新老客戶的需求,但隨著科學技術的進步,FS 已不能符合現代文件系統的需求,且會導致抖動等一系列問題。當時還是加州大學伯克利分校研究生,后成為著名 BSD 開發者 Marshall Kirk McKusick 在 BSD 4.1b 上承接傳統的 FS 文件系統實現了 FFS(Fast File System),妥善地解決了這一難題,把先前整塊的磁盤文件系統分為小塊,每塊包含自已的索引節點和數據,因而增加了文件的局部性,減少了尋道時間。由于 Marshall Kirk McKusick 的 FFS 文件系統很好很強大,所以立即被各大 Unix 系統所使用。SunOS/Solaris、System V Release 4、HP-UX 及 Tru64 UNIX 都使用它,也成為當今各 BSD 分支(FreeBSD、OpenBSD、NetBSD 及 DragonFlyBSD)的標準文件系統。每個不同的系統,無論開源與否,又會在 FFS 文件系統上增加各種擴展,這些擴展往往不互相兼容,但神奇的是,大家又都使用和原版同樣的塊大小和數據塊寬度。因此在很大程度上,這些山寨版 FFS 文件系統又相互兼容,至少在一個操作系統上能對另一操作系統的文件系統執行只讀操作。因此,FFS 事實上已經成為 Unix 系統的標準文件系統,故它有了一個更廣泛的稱謂——UFS(Unix File System,即 Unix 文件系統)。
UFS 在后來的若干年又取得了長足的發展。Sun 公司在 Solaris 7 系統中,給 UFS 提供了簡單的日志功能。日志文件系統指在檔案系統發生變化時,先把相關的信息寫入一個被稱為日志的區域,然后再把變化寫入主文件系統的文件系統。在文件系統發生故障(如內核崩潰或突然停電)時,日志文件系統更容易保持一致性,并且可以較快恢復。Marshall Kirk McKusick 又實現了 BSD 一度引以為豪的 Soft Update 功能,來保證計算機掉電或系統崩潰時,通過使元數據按依賴順序更新來確保磁盤上總的文件系統保持一致的實現機制。Soft Update 的目標和日志類似,但實現代價比日志輕量許多。不過這項功能有所代價,主要是需要引入一個后臺 FSCK 檢查。
2009 年,Jeff Roberson 正式發表了對 UFS 的一項改進,為 Soft Update 加入了日志功能,并消除了對 FSCK 的依賴,這項改進最終集成進了 FreeBSD 9 中。TrustedBSD 項目又為 BSD 分支的文件系統設計了 ACL 訪問控制表功能(Access Control Lists)。先前,Unix 文件系統的訪問控制是非常簡單的,其權限管理分為三個不同的類別:用戶、同組用戶以及其他用戶,對每個類別,Unix 文件系統提供讀、寫、執行三種權限的管理。這樣的許可管理過于粗糙,無法指定某一用戶訪問的權限,也無法指定更為細致的權限內容(例如準許對一文件實行刪除操作)。為解決這個問題,訪問控制表被增加到文件系統中,使用以存取控制矩陣為基礎的存取控制方法。存取控制串列描述每一個文件對象各自的存取控制,并記錄可對此物件進行存取的所有主體對對象的權限。總之,UFS 與時俱進,不斷增加新的功能。
HFS+:更現代的 HFS
作為 Mac OS X 的老祖宗 NeXTSTEP,因為基于 BSD,所以自然也使用 UFS。而老版的 Mac OS 則使用一個叫做 HFS 的文件系統。HFS 是一個比較古老且不思進取的文件系統,因此,在 20 世紀 90 年代末已不能滿足當時的需要。在《Mac OS X 背后的故事(一)》中我們提到,為了實現 Mac OS 的現代化,Copland 項目被提出。Copland 項目的子項目 Sequoia 旨在 HFS 的基礎上,加入現代文件系統所必需的新功能,如大文件支持、Unicode 文件名支持、長文件名支持、32 位文件映射表支持等。Sequoia 項目即成為后來熟知的 HFS+,由 Don Brady 領導,這個團隊先花了 6 個月時間把 HFS 項目原本的 Mac 使用的 68K 處理器匯編碼改寫成 C 代碼,然后逐漸加入新功能。
后來由于 Copland 被力挽狂瀾的 Ellen Hancock 給廢了,所以一些有用的更新,如 HFS+ 即被集成到 Mac OS 8.1 中。在 Mac OS X 誕生初期,HFS+ 和 UFS 文件系統同時被引入早期的 Mac OS X 中。不過由于 HFS+ 根植 Mac OS,缺乏 Unix 文件系統所必需的功能,如符號鏈接、硬鏈接及其他各種 POSIX 兼容性,所以 HFS+ 開發組又花了一些工夫在不影響和 Mac OS 兼容性的情況下引入了這些功能。由于 HFS+ 是對 HFS 的擴展,故 HFS+ 支持 Mac OS 至 Mac OS X 的平滑過渡,所以 Mac OS X 一直默認使用 HFS+。但當時的 UFS 提供比 HFS+ 更先進的功能,因此 Mac OS X 10.0 至 10.4,也都支持把系統安裝在 UFS 系統上。
Mac OS X 10.0 發布后,蘋果不遺余力地對 HFS+ 進行大規模的擴展和維護,增加了很多 UFS 獨有的功能。這些新功能使得文件系統更加安全穩定可靠。例如 Mac OS X 10.2.2 中,HFS+ 支持日志。日志功能在 Mac OS X 10.2 服務器版中可以簡單地設定,但在普通桌面版中需要使用命令行進行操作。在 Mac OS X 10.3 中,帶日志功能的 HFS+(被稱為 HFSJ,即 HFS+ volume with journal)成為默認設置。Mac OS X 10.3 亦增加文件名、目錄名區分大小寫及 Unicode 3.2 的支持。Mac OS X 10.4 中,HFS+ 更是增加了 ACL 訪問控制表功能,提供更復雜的對傳統 Unix 文件系統權限的擴展。
文件系統除了讓用戶供穩定地存放文件這一目標以外,還是各項操作系統功能的基礎。Mac OS X 每個大發行版都要增加數百項新功能,許多新功能嚴重依賴于文件系統的實現。Mac OS X 10.3 提供了 FileVault 來加密用戶文件,因此用戶主目錄被保存在一個 HFS+ 文件系統加密鏡像中。Mac OS X 10.4 提供了系統內置的 Spotlight 桌面搜尋搜索功能,能讓用戶對整個磁盤系統進行快速搜尋、隨打即顯。這項功能要求文件系統提供任意長度文件元數據(metadata)的支持。Mac OS X 10.4 轉向了對 Intel 處理器的支持,因此蘋果發布了一個測試版本的 BootCamp 來讓用戶安裝 Mac OS X、Windows 雙系統,并在 Mac OS X 10.5 正式集成進系統。
哪怕在 Mac OS X 系統運行,BootCamp 也可以實時調整系統主分區的大小,來空出磁盤空間給 Windows,因此,HFS+ 又需要支持動態分區大小調整。在 Mac OS X 10.5 中集成了 Time Machine,它是蘋果公司所推出備份的工具程序,于 2006 年 8 月 7 日在蘋果計算機全球研發者大會(WWDC)中首次公開,成為當天觀眾歡呼聲最高的功能。Time Machine 對于修改過的文件會在備份盤上保存一個新拷貝,而對于不變的內容,僅在備份盤上存一個指向先前文件的硬鏈接。因此每一次快照只保存改動的文件,而別的文件只保存占用空間很少的硬鏈接。但 Unix 一般只支持文件的硬鏈接而不支持目錄的硬鏈接。因此 HFS+ 在這點上走得比 Unix 文件系統更遠,提供了對于目錄的硬鏈接支持。在 Mac OS X 10.6 中,HFS+ 甚至支持文件系統壓縮,使得安裝后占用比 Mac OS X 10.5 少得多的空間。Mac OS X 10.7 提出了 FileVault2,能加密整個磁盤而不是一個用戶目錄。這些功能我們在為讀者介紹每個發行版時亦會提到,但總之讀者看到,HFS+ 的功能隨著 Mac OS X 的商業需求不斷被擴展。“我在做了這么多工作后回想才發現,我們為 HFS+ 增加了那么多新功能,”蘋果前文件系統開發者 Don Brady 如是說。
由于 HFS+ 經過后來若干年的發展,提供的功能已不遜于 UFS,甚至更多更好,故至 Mac OS X 10.5 砍掉了安裝至 UFS 的支持。HFS+ 成為唯一正式的 Mac OS X 系統。
HFS+ 并不完美
HFS+ 自發布以來,幾乎每個發行版都有令人欣喜的改動。它也逐漸成為一個非常完善的文件系統。但 HFS+ 立足于 HFS 設計,HFS 已有 27 年的歷史,HFS+ 亦有 14 年歷史。這個文件系統有太多的歷史包袱,為考慮兼容性,這些陳舊的設計并不能被推翻重來。
HFS+ 基于B-樹實現,當查找B-樹中未使用的節點時,HFS+ 只能每次處理 16 位,原因是老 Mac 使用的 Motorola 的 68K 芯片原生支持 16 位的數據操作。但不管是 PowerPC 還是 Intel,寄存器都支持 256 位寬的寄存器。
HFS+ 的元數據(metadata)都以大字節序保存,原因是 Motorola 的 68k 和后來 Mac 使用的 PowerPC 都使用大字節序。但經過 Intel 遷移后,當今的 Mac 都使用 Intel 芯片,而 Intel 芯片是使用小字節序的。因此每當數據讀取或存入時,還要經過小字節序和大字節序的轉換。遠古時期磁盤很慢,計算機處理器的速度也很低,因此進行一次磁盤操作會占用較多的時間,HFS+ 的時間分辨率為一秒,但當今的磁盤、處理器處理一次文件系統操作的時間遠小于一秒,因此所有主流磁盤文件系統的時間分辨率都是一至數百納秒級別的。
HFS+ 的元數據有全局鎖,同一時間只有一個進程可以訪問更新文件系統。在單核處理器連手機平板都較少見到的當今,這種設計顯得很幼稚。
HFS+ 亦沒有稀疏文件的支持。例如我們在 SQL 中建立了一個數據庫,SQL 分配了 10GB 的文件給這個數據庫,并且在文件頭和文件尾寫上一些字節的數據。而由于我們還沒有給這個數據庫添加新的數據,所以這 10GB 的文件除了頭尾外其他字節都為0。現代的文件系統基本都支持稀疏文件,也就是說,當處理這個數據庫操作時,事實上往磁盤寫入的數據只有那文件頭和文件尾的若干字節。而 HFS+ 則需要把那些 0 也寫上,因此會完整寫入 10GB 的數據,耗費長得多的時間。
此外,HFS+ 不具備元數據校驗功能、快照功能、寫入時復制功能、就地執行功能、邏輯卷管理功能等很多現代磁盤系統所具備的功能,也不能動態調整文件塊大小。這些功能的加入并不容易。
其中最要命的是,HFS+ 不像一些先進的文件系統,支持寫入時復制事務模型,也沒有快照和克隆。這使得用戶數據時時處于風險之中。例如由于因為斷電、內核崩潰等原因,文件系統上寫到一半的數據,小則導致個別文件損壞,大則導致整個文件系統崩潰。在生產領域,這樣不可靠的文件系統,很有可能帶來致命的災難。
正是由于上述這些原因,連我們介紹過的短視的 Linus Torvalds 都認為 HFS+ 是個垃圾文件系統。蘋果自然受不了這種侮辱,因此,干掉 HFS+ 勢在必行。用什么取代 HFS+ 呢?蘋果開始秘密研發下一代的文件系統。
(下)
由于各種缺點,干掉 HFS+ 勢在必行,然而用什么取代 HFS+ 呢?蘋果開始秘密研發下一代的文件系統——ZFS,然而在諸多因素的干擾下,Mac OS X 的 ZFS 支持卻只是曇花一現,未來文件系統之路將走向何方?
文件系統的新時代——ZFS
為了代替 HFS+,蘋果開始為研發下一代文件系統招兵買馬,準備大干一場。但這時 Sun 公司的工作讓蘋果的員工們為之一振。
2004 年,Sun 公司發表了其杰出的文件系統ZFS。這是一個 128 位的文件系統,本為 Solaris 操作系統開發,于 2005 年 10 月 31 日并入了 Solaris開發的主干原始碼。后成為一個使用 CDDL 協議條款授權的開源項目。
ZFS 是一個具有高存儲容量、文件系統與卷管理概念整合、嶄新的磁碟邏輯結構的輕量級文件系統,同時也是一個便捷的存儲池管理系統。
ZFS 的一個重大特點就是擁有大容量。ZFS 是一個 128 位的文件系統,這意味著它能存儲 1800 億億(18.4×1018)倍于當前 64 位文件系統的數據。ZFS 的設計如此超前以至于這個極限就當前現實而言可能永遠無法遇到。項目領導 Bonwick 曾說:“要填滿一個 128 位的文件系統,將耗盡地球上所有存儲設備,除非你擁有煮沸整個海洋的能量。”假設每秒鐘創建 1000 個新文件,達到 ZFS 文件數的極限需要約 9000 年。
此外,ZFS 的一個重要指導思想是不單單去做一個文件系統,而是實現一套完整的卷管理方案。不同于傳統文件系統需要駐留于單獨設備或者需要一個卷管理系統去使用一個以上的設備,ZFS 建立在虛擬的被稱為“zpools”的存儲池之上。每個存儲池由若干虛擬設備組成。這些虛擬設備可以是原始磁碟,也可能是一 RAID1 鏡像設備,或是非標準 RAID 等級的多磁碟組。于是 zpool 上的文件系統可以使用這些虛擬設備的總存儲容量。
有了卷管理方案后,ZFS 走得更遠,加入了快照和克隆等實用的文件系統功能。當 ZFS 寫新數據時,包含舊數據的塊被保留,磁盤只寫入修改過的那部分數據塊。所以快照的建立非常快,只存儲兩個快照間的數據差異,因此快照也是空間優化的。克隆指兩個獨立的文件系統共享一些列的塊。當任何一個克隆版本的文件系統被改變時,只創建改動的數據塊,因此非常快速,也占用少得多的空間。
而 ZFS 最大的貢獻在于它是第一個支持寫入時復制功能(COW,copy on write)的文件系統。所有文件系統中的塊都包括 256 位的校驗值。含有活動數據的塊從來不被覆蓋;而是分配一個新塊,并把修改過的數據寫在新塊上。所有與該塊相關的元數據塊都被重新讀、分配和重寫。因此,當一個數據寫入時發生了任何意外錯誤,原先的數據依然可以被訪問,且文件系統知道哪個操作出了錯誤而沒有完成。ZFS 的快照和克隆正是因此項技術而得以實現。
ZFS 對于用戶而言,界面友好。先前 Unix的卷管理非常煩瑣,FreeBSD 因此還建了一套宏偉的框架,給邏輯卷管理做深層次的抽象。而 ZFS 文件系統自帶卷管理方案,幾乎所有煩瑣復雜的操作都能在一兩條命令內完成,我用傳統的卷管理工具已有近十個年頭,第一次使用 ZFS 時,完全被其易用性震撼,所以我毫不猶豫地把手頭所有的服務器遷移到了 ZFS。
由于 ZFS 各種美好,加上其開源性質,所有的操作系統都想支持它。Solaris、OpenSolaris 項目一直作為標準實現供其他系統參考。Pawe Jakub Dawidek 把 ZFS 移到 FreeBSD,并在 2009 年進入了 FreeBSD 7,作為 FreeBSD 第七版最耀眼的三項功能之一(另一項功能是我們先前提到的 ULE,以及 Sun DTrace 的移植工作)。NetBSD 在 2009 年正式收納 ZFS。Linux 則麻煩得多,因為 Linux 內核的協議 GPL 是個和很多協議都水火不容的奇葩協議,ZFS 分發所采用的 CDDL 和 GPL 會產生沖突,所以一方面 FUSE 提供了用戶空間層面的支持;另一方面,由 Oracle 牽頭,專為 Linux 開發 Btrfs,事實上就是一個 ZFS 的山寨版,可惜折騰了幾年,Oracle 自己又把 Sun 收購了,且到我撰寫此文時 Btrfs 依然沒有正式的穩定版本發布。
曇花一現的 ZFS 夢
剛才提到,蘋果在招兵買馬,雇員工開發新一代的文件系統,而 Chris Emura(Apple CoreOS 的文件系統開發經理)及 Don Brady(先前提到,此人領導 HFS+ 的開發)兩個富有經驗的文件系統開發者卻被衣服一樣晾在了一邊無所事事。2006 年,剛剛提到的 Pawe Jakub Dawidek 正在往 FreeBSD 遷移 Sun 的 ZFS,這項工作立刻引起了 Chris Emura 及 Don Brady 的高度興趣。由于 ZFS 在 Unix 系統高度的可移植性,加上 Mac OS X 本就是 FreeBSD 的近親,閑得發慌的兩人立即打算往 Mac OS X 移植 ZFS。在 2007 年 4 月 6 日,FreeBSD 的移植宣告完成,等待合并進主干。一周后,兩位蘋果員工亦成功地完成了 Mac OS X 的移植。
蘋果一看兩人的 ZFS 的移植工作大有前途,立即跟進。2007 年的蘋果全球開發者大會上,蘋果讓 Chris Emura 及 Don Brady 舉辦了一場小型講話,介紹 Mac OS X 對 ZFS 的支持。這場講話先前并沒有在官方聲明中告示,但講話的報告廳依然擠滿了聽眾。隨后 ZFS 移植的源碼在 Mac OS Forge 公布。在最終版的 Mac OS X 10.5 帶有試驗性的 ZFS 只讀支持,以命令行方式提供。用戶可以掛載 ZFS 的存儲池,并對池中的文件系統進行讀取操作。
蘋果一直使移植并使用 Sun 的關鍵技術,除了 Java 以外,Mac OS X 10.5 的 Xcode 套件也加入了 DTrace 的支持,并提供了一個好用的圖形界面 Instruments 讓開發者更方便地調用 DTrace。ZFS 除了解決 HFS+ 的所有問題,提供安全可靠的文件系統基礎外,還可以簡化蘋果許多軟件的實現。例如前文提到的 Mac OS X 10.5 的 Time Machine,實現頗為煩瑣,依賴于給 HFS+ 提供新功能,功能層也需要增加很多的和備份相關的代碼。而 ZFS 默認就支持快照,將大大簡化 Time Machine 的實現,并使該功能更穩定可靠。事實上在 2008 年 11 月 25 日,Sun 發布了 OpenSolaris 2008.11 版,其中給 GNOME 的 Nautilus 增加了一個使用 ZFS 的快照功能的圖形界面插件名為 Time Slider,和蘋果的 Time Machine 提供了非常相近的功能,我在使用后感覺不錯。
因此在 WWDC 2008 上,Snow Leopard 被提出,其中一項很重要的賣點就是對 ZFS 的完整的讀寫支持。在 Mac OS X 的服務器版,蘋果也將提供一套圖形界面工具來方便維護人員管理 ZFS 存儲池。在當時的 Snow Leopard Server 主頁上,蘋果聲明 ZFS 將作為一項主推功能。
但好景不長,一年后的蘋果開發者大會時,ZFS 相關的內容被悄悄從任何公開的文檔、網站、發布會中撤下,沒有給出任何的理由。Mac OS Forge 上的 ZFS 代碼和頁面也被蘋果移除。外界有很多對此的猜測,但沒有任何猜測得到蘋果官方的或是哪怕離職員工的證實。
猜測之一是當時 Sun 剛被 Oracle 收購,而 Oracle 長期投資 ZFS 的競爭產品 Btrfs。因此蘋果覺得 ZFS 的前途不甚明朗。
猜測之二是 ZFS 的關鍵技術 Copy On Write 有專利問題,NetApp 聲稱他們擁有 COW 的專利因此在起訴 Sun,蘋果不想在當中冒風險。
猜測之三是 ZFS 和蘋果的 XNU 內核有協議沖突。我雖然不學法律,但我認為這個說法不完全對,因為 ZFS 和 DTrace 一樣,是以 CDDL 發布的開源軟件,既然 DTrace 可以無后顧之憂地加入到 XNU 中,ZFS 也沒有理由不可以。事實上,除了 Linux 這種少數使用 GPL 這類奇葩協議的內核,大多數系統的協議都不和 CDDL 沖突。FreeBSD 也好,Mac OS X 10.5 也罷,都把 ZFS 加入內核發布。
但事實上,如果把三種猜測并在一起,我們可以看到一個更全局的可能性:對于猜測之二,蘋果可能并非想使用 CDDL,而是想從 Sun 買下一個私有的協議,這樣一來,Sun 不但提供更好的技術支持,出了問題(比如猜測二中的專利問題)也可以讓 Sun 為自己背黑鍋。結果 Sun 可能和蘋果價格談不拢,加上猜測之一提到的 Sun 大勢已去,讓蘋果覺得還不如自己造個輪子來得方便。Sun 公司開發 ZFS 的主力 Jeff Bonwick 雖不能提供詳細的信息,但他基本證實了這種說法。
無論如何,Mac OS X的 ZFS 支持,如曇花一現般消失了。
未來文件系統之路走向何方
雖然 Mac OS X的 ZFS 支持被砍了,開源社區依然想繼續開發 Mac OS Forge 先前版本的移植。如 MacZFS 項目不遺余力地給 Mac OS X 10.5~10.7 提供 ZFS 讀寫支持。Don Brady 在蘋果將對 ZFS 的支持砍掉之后從工作了 20 多年的蘋果離職,開了一家名為 Ten’s Complement 的公司,該公司提供 Z-410,較 MacZFS 提供更新更穩定的移植。
不過,砍了 ZFS 后的蘋果目標也變得更清晰——和 Sun 的談判讓蘋果覺得與其支付高額的協議費,還不如雇人自己做個新的,再說了,作為比 Sun 大得多的 IT 公司,蘋果可以輕而易舉地搞個更強大的東西滅了它,因為 ZFS 其實也不如傳說中的那樣好。
首先,時代在進步。ZFS 之后,又有很多新的和文件系統相關的研究,如 Ohad Rodeh 的論文,即成為后來 BtrFS 實現的基礎,可能比 ZFS 做得更好。
其次,ZFS 是十年前開始設計的文件系統,但十年中,存儲工具已發生了重大的變化。ZFS 為傳統磁盤設計,但傳統磁盤的市場空間已不斷被 SSD、閃存的吞食。尤其是 MacBook Air 中使用的 Flash 存儲器便宜好用又小巧,可能將來會在 MacBook Pro 甚至 iMac 中得到更大的推廣。采用為傳統磁盤優化的 ZFS 就不顯得那么有吸引力。
最后,ZFS 和蘋果有不同的用戶群。ZFS 目標用戶是大企業的工作站和服務器。在那里,大容量的存儲空間、高級的卷管理顯得非常重要,但蘋果面對的基本都是個人用戶——先前蘋果還賣服務器,但后來 Xserve 都被蘋果砍了。有幾個個人用戶需要使用到 ZFS 這些高級的功能呢?更重要的,蘋果的主要利潤將移到 iPhone、iPod、iPad、Apple TV 這些小設備上,ZFS 需要占用大量的內存來實現文件系統操作,在這些小設備上,內存很少,ZFS 根本跑不起來。
蘋果非常清楚這些問題,工程師們現在一定在緊鑼密鼓地開發下一代文件系統。在 10.7 及 10.8 中,這套文件系統并未浮出水面,但一些細節值得留意。在 10.7 中,蘋果發布了 Core Storage,但并未聲張。這是一套邏輯卷管理工具,類似于前文提到的 FreeBSD 的 GEOM。這個版本的 File Vault 2 亦使用 Core Storage 重寫。可以看到雖然蘋果在上層不斷地淡化文件系統的概念,例如 iCloud 的發布和 iOS 中對于文件這一概念的故意忽略,但蘋果在底層文件系統上的動作越來越大,想必在將來,蘋果定會讓我們感到重大的驚喜。
x = ^{ printf (“hello world\n”);}
x ();
int spec = 4;
int (^MyBlock)(int) = ^(int aNum){
return aNum * spec;
};
spec = 0;
printf (“Block value is%d”,
MyBlock (4));
for (int i = 0; i < 1024; i++)
c[i]=a[i]+b[i];
__kernel add (float *a, float *b, float *c){
int i = get_global_id (0);
c[i]=a[i]+b[i];}
王越 《程序員》 2013-07-10 14:42:30
稱謂:
内容: