√ 每個技術專題都配備大量圖、表和代碼實例,力求將復雜的機制以簡潔的形式表達出來。
√ 提供了一個小巧且跨平台的C/C++運行庫MiniCRT,綜合展示了與運行庫相關的各種技術。
√ 能將程序的編譯和運行過程所涉及的各種技術全面地串連起來介紹的,至今尚未有先例。
√ 覆蓋Windows和Linux兩個平台,詳述應用程序在編譯、鏈接和運行時所發生的各種事項。
√ 學習研究他人的代碼是枯燥而耗時的,先行者的經驗能避免重複勞動,直指經驗和關鍵。
√ 學會編程“易筋經”,可以開發操作系統、編譯器,甚至是開發一種新的程序設計語言。
√ 由一個很小很簡單的問題或示例入手,層層剝開、深入挖掘,探究每個機制“怎麼做”。
√ 務必理解“為什麼這樣做”,力求深入淺出、圖文並茂,盡力把每一步細節呈現給讀者。
本書主要介紹系統軟件的運行機制和原理,涉及在Windows和Linux兩個系統平臺上,一個應用程序在編譯、鏈接和運行時刻所發生的各種事項,包括:代碼指令是如何保存的,庫文件如何與應用程序代碼靜態鏈接,應用程序如何被裝載到內存中并開始運行,動態鏈接如何實現,C/C++運行庫的工作原理,以及操作系統提供的系統服務是如何被調用的。每個技術專題都配備了大量圖、表和代碼實例,力求將復雜的機制以簡潔的形式表達出來。本書最后還提供了一個小巧且跨平臺的C/C++運行庫MiniCRT,綜合展示了與運行庫相關的各種技術。
本書對裝載、鏈接和庫進行了深入淺出的剖析,并且輔以大量的例子和圖表,可以作為計算機軟件專業和其他相關專業大學本科高年級學生深入學習系統軟件的參考書。同時,還可作為各行業從事軟件開發的工程師、研究人員以及其他對系統軟件實現機制和技術感興趣者的自學教材。
這是一本深人闡述鏈接、裝載和庫等問題的出色圖書,讀來讓人愉悅,你從巾可以清晰地了解程序的前世今生,徹底理解敲人的代碼如何變成程序任系統中運行。通讀本書不管對於開發還是trouble shootin9都會很有幫助。建議每一位希望從事系統開發、或希望更實務地理解操作系統和編譯器、或不滿足於只寫代碼的出色程序員都擁有這樣一本書。
——鄒飛,趨勢科技(中國)研發中心專業軟件要程師
本書從大處著眼,小處著手,以通俗易懂的語言,深入淺出地對系統軟件的底層形成機制進行條分縷析,正合藥山禪師所謂“高高山頂立,深深海底行”。循著作者的思緒一路走來,有如醍醐灌頂。暢快淋漓。非常高興有預覽此書初稿的寶貴機會,我在瀏覽書稿和查核相關資料的過程中,學到了很多以前未知或知之不深的內容。
——馮亮,阿里巴巴(中國)網絡技術有限公司運維部系統架構師
作者序1
兩年前,甲子跟我提起,他在考慮寫一本講述計算機程序基本工作原理的書,由於代碼背後的許多細節現在難以找到完整而又實用的資料,因此,系統性地講述這些技術要素一定非常有意義。這是我非常感興趣的話題,因為最近幾年來,我每次給學生講課或作技術報告時,經常會提到程序背後的一些細節知識,而當有人請我推荐一些參考資料時,我很難想得出有什麼恰當的參考書可供學習。我自己也曾想過要寫一點這方面的書,只是一直下不了決心做這件事情。甲子的提議讓我意識到,寫這樣一本書的機會來了。於是,我們認真規劃了書的選題。按我的建議,這應該是三卷本的書,每卷獨立,合起來成一體系。第一卷是基礎篇,介紹程序的基本運行過程,即是您現在看到的這本書。其他兩卷還需要時日和機緣。
在過去兩年中,我曾經以“Inside Windows Programs”為題在多所高校作過報告,旨在介紹Windows程序背後的一些支撐技術。對於正在學習計算機或軟件專業的學生,或者正在從事軟件開發的工程師們,我認為理解這些支撐技術是很有必要的。試想,即使一個簡單的“Hello World!”程序,也依賴於背後的輸入輸出庫(或流庫)及系統提供的模塊,這種依賴性已經成為現代軟件在操作系統環境下運行的一個必要條件。然而,有關這些支撐技術的系統性資料卻少而又少,雖然Internet上並不缺乏任何一方面的細節信息,但是,能將程序的編譯和運行過程所涉及的各種技術全面地串連起來介紹的,卻尚未有先例。
甲子曾經在2006年夏天跟我實習過兩個月,他幫我搭建了一個在Windows已有體系結構下將交換空間重定向到遠程機器物理內存的原型系統。完成這一系統並非易事,而且甲子事前並無Windows內核編程經驗,但是,他憑藉紮實的計算機系統軟件功底,成功地打通了從頁面錯誤(page fault)異常例程到遠程機器內存管理器之間的數據通路。在這一段實習經歷中,我不僅看到了他駕馭代碼和系統的能力,也感受到他做事認真負責的態度。因此,當他提出要寫一本介紹程序基礎的書時,我認為他是非常合適的人選。考慮到寫書的艱鉅性,他推薦石凡同學加入進來,這才有了我們三個人的組合。我原先擔心寫作的進度,畢竟寫這樣一本書需要大量的時間投入。幸運的是,在甲子和石凡的不懈努力下,這本書終於面市了。
本書講解的內容,涉及在Windows和Linux兩個系統平台上,一個應用程序在編譯、鏈接和運行時刻所發生的各種事項,包括:代碼指令是如何保存的,庫文件如何與應用程序代碼靜態鏈接,應用程序如何被裝載到內存中並開始運行,動態鏈接如何實現,C/C++運行庫如何工作,以及操作系統提供的系統服務是如何被調用的。每個技術專題都配備了大量圖示和代碼實例,力求將復雜的機制以簡潔的形式表達出來。本書最後還提供了一個小巧且跨平台的C/C++運行庫MiniCRT,綜合展示了與運行庫相關的各種技術。
關於寫作這本書的功勞,我不敢掠美。在創作之初,包括擬定提綱及甄選內容方面,我跟甲子有過認真而細緻的討論;在寫作過程中,我對甲子和石凡的初稿提出過一些建議,尤其在表述方面,同時我也協助他們與編輯進行了溝通和交流。對於正文的內容,我並無實質性的貢獻,但基於我對甲子和石凡兩位年輕人的了解,我相信他們自身的技術實踐功底,以及足夠的技術闡釋能力。我期待這本書能夠真正地提升程序員的自我修養,讓程序員總是生活在“知其然,更知其所以然”的代碼曼妙中。
最後,我要感謝這本書的四位編輯,他們是何艷、方舟、劉鐵鋒和陳元玉,謝謝他們為這本書付出的努力。還要感謝博文視點團隊的負責人周筠女士,謝謝她給予兩位年輕作者的扶持和關愛。
潘愛民
2009年2月於北京微軟
作者序2
兩年前,我在浙江大學的一著名BBS的C++板塊上擔任版主,而俞甲子則是板上的資深版友(以及前版主)。那時候我對鏈接裝載、運行庫等內容比較感興趣,自己摸索著在博客上寫了一篇關於鏈接的入門文章,而這就是一切的開始。
我猜想俞甲子可能對寫這麼一本書早有想法,看到我的文章正好找到了同路人。他找到了我和潘愛民老師,我們一拍即合,就開始了這長達兩年的寫作歷程。考慮到當時俞甲子已經在鏈接部分有了相當的積累,因此我不得不放棄我最有興趣的一部分轉而在運行環境上做文章。我把glibc和msvcrt的源代碼翻了個底朝天,了解到了許多平時不可能接觸到的內幕和技術細節。事實上,這基本是一個現學現賣的過程,我一邊學習著新的知識,一邊把新知識組織整理寫成文字。讀者在看某些章節的時候,會發現這些章節的講解過程就是一個源代碼的挖掘過程,這實際上也就是我的學習過程。學習研究他人的代碼是枯燥而耗時的,我很高興能夠做這樣一個先行者,將我的經驗寫進書裡,讓讀者能夠避免重複勞動,直接獲得其中的經驗和關鍵技術。
本書所講的內容不是活躍在當今IT舞台上的高新技術,也不是雄踞計算機某個領域的王牌霸主,而是默默服務於所有計算機應用的掃地僧。也許閱讀本書不能夠直接在平時學習工作中的生產力上得到體現,但了解計算機的台前幕後會對讀者產生潛移默化的影響。當你的程序無法啟動的時候,你可能會在腦海裡多設想一種可能性;當你的代碼鏈接失敗的時候,你可能會更快地意識到問題的所在;當你的程序發生非法操作的時候,你可能不至於面對微軟的錯誤報告毫無頭緒。有人總愛用“時效性”評價當今的IT技術。彷彿一項技術的生存期就只有幾年。我不能說這樣的想法是錯誤的,如今的技術的確在飛速地更替和發展。但是本書所講的技術,大多是成型在十年前,乃至二十年前,它們是整個計算機行業技術的根本,也幾乎是現在所有計算機應用的基礎。在當今的計算機技術發生根本性變革之前,這些技術還將繼續存在並保持活力。
我很榮幸能夠有機會和讀者分享這些技術,但寫作水平有限(我在語文課上歷來不是個好學生),最終在文字和結構上頗有缺憾,只能在這裡說一聲抱歉。在這裡要感謝我小學、初中和高中的語文老師,謝謝你們當初對我的教導,儘管最終可能辜負了你們的希望。感謝潘老師、博文視點的編輯及所有支持我們的朋友們,謝謝你們對我們的幫助。最後要感謝我的父母,沒有你們,我永遠不可能走到今天這一步。
石凡
2009年2月於杭州
作者序3
CPU體系結構、彙編、C語言(包括C++)和操作系統,永遠都是編程大師們的護身法寶,就如同少林寺的《易筋經》,是最為上乘的武功;學會了《易筋經》,你將無所不能,任你創造武功;學會了編程“易筋經”,大師們可以任意開發操作系統、編譯器,甚至是開發一種新的程序設計語言! ——佚名
唸書的時候,作為標準的愛好技術的宅男,每天掃一遍各大高校BBS的技術版面,基本好比一日三餐一樣平常。我對計算機技術方面的口味很雜,從彙編版到C++到Linux內核開發、Linux應用開發、遊戲開發、網絡、編程語言、體系結構、移動開發、開源閉源我都會參上一腳。
我始終認為技術優劣取決於需求,與很多持有“編程語言血統論”的程序開發者不同,我不認為C++或Java本身有什麼直接可比性,或者OOP與函數式編程誰優誰劣,我始終堅持認為作為開發者,MOP(Market/Money Oriented Programming)才是唯一不變的編程範式。於是我往往不參與那些技術、平台、語言教派之間的宗教戰爭,這種論戰基本上每週都會有,我很佩服論戰各方見多識廣、旁徵博引、高屋建瓴的論斷,但我往往只是灌灌水調節一下思緒。相反,我很關註一些與語言、平台等相對獨立的基本的系統概念方面的問題,這些問題比較具體,也比較實用,比如:為什麼程序是從main開始執行? “malloc分配的空間是連續的嗎?”“PE/ELF文件裡面存的是什麼?”“我想寫一個不需要操作系統可以直接在硬件上跑的程序該怎麼做?”“目標文件是什麼?鏈接又是什麼?”“為什麼這段程序鏈接時報錯?”“句柄到底是什麼東西?”這些問題看似很簡單但實際上有很多值得深入挖掘的地方,比如第一個問題圍繞著main函數執行前後可以延伸出一大堆問題:程序入口、運行庫初始化、全局/靜態對象構造析構、靜態和動態鏈接時程序的初始化和裝載等。我們把這些問題歸結起來,發現主要是三個很大的而且連貫的主題,那就是“鏈接、裝載和庫”。
事實上,現在市面上和網絡上能找到的計算機技術方面的書籍和資料中,什麼都很齊全,唯獨關於這三個主題的討論十分稀缺,即使能找到一些也是猶如殘缺的典籍,不僅不完整而且很多已經過時了。關於現在通用的Windows和Linux平台的鏈接、裝載及PE/ELF文件的詳細分析,實在很少見。這個領域中,最為完整、也最為權威的莫過於John R. Levine的《Linkers & Loaders》,這本書我也前前後後通讀了好幾遍,雖然它對鏈接和裝載方面的描述較為完整,但是過於理論化,對於實際的系統機制描述則過於簡略。
我始終認為對於一個問題比較好的描述方式,是由一個很小很簡單的問題或示例入手,層層剝開深入挖掘,不僅探究每個機制“怎麼做”,而且要理解它們“為什麼這樣做”,力求深入淺出、圖文並茂,盡力把每一步細節都呈現給讀者。這是我一貫的想法,也是我們在本書中努力試圖達到的效果。 第一次有想寫這樣一本書的念頭是在2006年底,當時我正在念研一,想起未來還有一年多漫長而又相對空閒的研究生生涯,覺得寫一本這樣的書大概是比較好的“消遣活動”。於是我第一時間想到了在微軟研究院實習時的導師潘愛民老師,潘老師在寫作技術書籍方面有很深的功底和豐富的經驗。我把想法告訴潘老師以後,他十分支持,於是我又找到了當時剛好保送研究生、時間上也相對充裕的石凡,我們三個都對這個選題十分感興趣,可謂一拍即合。
當時也沒多想,以為寫書大概也就跟BBS發帖連載差不多吧。一旦寫起來才發現自己完全輕視了寫書的工作量。書中的每一個章節、每一個小段、每一個例子甚至每一個用詞有時候都要斟酌很久,生怕用得不恰當誤導了讀者。 “誤人子弟”這四個字罪名可不輕,大有推出午門斬首五遍以儆效尤之過。寫書的時間的確很倉促,雖然我們都是在讀研時寫的,按理說相對於已經工作的作者來講,已經是有很多閒餘的時間了,但還是經常手忙腳亂。想到以前看書看到作者寫的序裡,經常使用“時間倉促,水平有限”的話,推想作者不過是出于謙虛不免要客套一下。現在輪到自己寫序了,終於感覺到了這八個字的分量。即使到現在已近完稿,我們還是心裡十分忐忑,因為還有不少地方的確寫得不夠完善。也聽到了很多第一批讀者的反饋意見,很多建議都正中這本書的軟肋,我們也根據大家的意見又一次進行了修改,這已經是反反复复的第N次修訂了。
這本書前前後後花了兩年多的時間一直沒有完稿,由於截稿時間快到了,我們才終於定稿,因為實在沒有辦法做到完美,只能向無限接近完美努力。最後,我們在“著”和“編著”之間猶豫了很久,想到本書凝聚了我們很多的心血,還是誠惶誠恐地寫上了“著”字,權當給自己壯膽了。我們也相信,本書雖然沒做到完美,但是它一定會給你帶來一些你以前想看、想了解而又找不到的東西。或者以前在編程過程中困惑了你很久,但始終沒有找到解釋的問題,當在本書中終於找到答案且大呼“原來如此!”時,我們也就很欣慰了!
關於本書的書名筆者們也討論了很久,徵詢過很多意見,最終還是決定用“程序員的自我修養”作為書名,將“鏈接、裝載與庫”作為副標題。書名源自於俄羅斯的演員斯坦尼斯拉夫斯基創作的《演員的自我修養》,作者為了寫這本書前前後後修改了三十年之久,臨終前才同意不再修改,拿去出版。使用這個書名一方面是本書的內容的確不是介紹一門新的編程語言或展示一些實用的編程技術,而是介紹程序運行背後的機制和由來,可以看作是程序員的一種“修養”;另一方面是向斯坦尼斯拉夫斯基致敬,向他對作品精益求精的精神致敬。
在本書的創作過程中,很多人對我們的支持和幫助難以言表。這裡我要感謝博文視點的幾位編輯何艷、方舟、劉鐵鋒和陳元玉等,他們為本書付出了很多心血;特別要感謝博文視點的周筠老師,這本書能夠面世離不開她的支持和努力。另外也要感謝浙江大學的張曉龍博士,他為本書提出了很多建議,並且貢獻了“DLL HELL”一節。
俞甲子
2009年2月於杭州
第1部分 簡介
第1章 溫故而知新
1.2 萬變不離其宗
計算機是個非常廣泛的概念,大到佔用數層樓的用於科學計算的超級計算機,小到手機上的嵌入式芯片都可以被稱為計算機。雖然它們的外形、結構和性能都千差萬別,但至少它們都有“計算”這個概念。在本書裡面,我們將計算機的範圍限定在最為流行、使用最廣泛的PC機,更具體地講是採用兼容x86指令集的32位CPU的個人計算機。原因很簡單:因為筆者手上目前只有這種類型的計算機可供操作和實驗,不過相信90%以上的讀者也是,所以在這一點上我們很快能達成共識。其實選擇具體哪種平台並不是最關鍵的,雖然各種平台的軟硬件差別很多,但是本質上它們的基本概念和工作原理都是一樣的,只要我們能夠掌握一種平台上的技術,那麼其他的平台都是大同小異的,很輕鬆地可以舉一反三。所以我們相信,只有你能夠深刻地理解x86平台下的系統軟件背後的機理,當有一天你需要在MIPS指令集的嵌入式平台上做開發,或者需要為64位的Windows或tinux開發應用程序的時候,你很快就能找到它們之間的相通之處。
撇開計算機硬件中紛繁複雜的各種設備、芯片及外圍接口等,站在軟件開發者的角度看,我們只須抓住硬件的幾個關鍵部件。對於系統程序開發者來說,計算機多如牛毛的硬件設備中,有三個部件最為關鍵,它們分別是中央處理器CPU、內存和I/O控制芯片,這三個部件幾乎就是計算機的核心了;對於普通應用程序開發者來說,他們似乎除了要關心CPU以外,其他的硬件細節基本不用關心,對於一些高級平台的開發者來說(如Java、.NET或腳本語言開發者),連CPU都不需要關心,因為這些平台為它們提供了一個通用的抽象的計算機,他們只要關心這個像的計算機就可以了。
……
大陸出版品因裝訂品質及貨運條件與台灣出版品落差甚大,除封面破損、內頁脫落等較嚴重的狀態,其餘商品將正常出貨。
特別提醒:部分書籍附贈之內容(如音頻mp3或影片dvd等)已無實體光碟提供,需以QR CODE 連結至當地網站註冊“並通過驗證程序”,方可下載使用。
無現貨庫存之簡體書,將向海外調貨:
海外有庫存之書籍,等候約45個工作天;
海外無庫存之書籍,平均作業時間約60個工作天,然不保證確定可調到貨,尚請見諒。
為了保護您的權益,「三民網路書店」提供會員七日商品鑑賞期(收到商品為起始日)。
若要辦理退貨,請在商品鑑賞期內寄回,且商品必須是全新狀態與完整包裝(商品、附件、發票、隨貨贈品等)否則恕不接受退貨。