《程序員的自我修養(yǎng):鏈接、裝載與庫(kù)》主要介紹系統(tǒng)軟件的運(yùn)行機(jī)制和原理,涉及在Windows和Linux兩個(gè)系統(tǒng)平臺(tái)上,一個(gè)應(yīng)用程序在編譯、鏈接和運(yùn)行時(shí)刻所發(fā)生的各種事項(xiàng),包括:代碼指令是如何保存的,庫(kù)文件如何與應(yīng)用程序代碼靜態(tài)鏈接,應(yīng)用程序如何被裝載到內(nèi)存中并開(kāi)始運(yùn)行,動(dòng)態(tài)鏈接如何實(shí)現(xiàn),C/C++運(yùn)行庫(kù)的工作原理,以及操作系統(tǒng)提供的系統(tǒng)服務(wù)是如何被調(diào)用的。每個(gè)技術(shù)專題都配備了大量圖、表和代碼實(shí)例,力求將復(fù)雜的機(jī)制以簡(jiǎn)潔的形式表達(dá)出來(lái)。本書(shū)最后還提供了一個(gè)小巧且跨平臺(tái)的C/C++運(yùn)行庫(kù)MiniCRT,綜合展示了與運(yùn)行庫(kù)相關(guān)的各種技術(shù)。
《程序員的自我修養(yǎng):鏈接、裝載與庫(kù)》對(duì)裝載、鏈接和庫(kù)進(jìn)行了深入淺出的剖析,并且輔以大量的例子和圖表,可以作為計(jì)算機(jī)軟件專業(yè)和其他相關(guān)專業(yè)大學(xué)本科高年級(jí)學(xué)生深入學(xué)習(xí)系統(tǒng)軟件的參考書(shū)。同時(shí),還可作為各行業(yè)從事軟件開(kāi)發(fā)的工程師、研究人員以及其他對(duì)系統(tǒng)軟件實(shí)現(xiàn)機(jī)制和技術(shù)感興趣者的自學(xué)教材。
帶領(lǐng)你探索深層次的自己,走進(jìn)新的程序世界!
眾多讀者學(xué)者讀過(guò)后愛(ài)不釋手,傾情推薦!
《程序員的自我修養(yǎng):鏈接、裝載與庫(kù)》裝幀優(yōu)雅精美,在京東取得不錯(cuò)銷(xiāo)量!
本書(shū)深入淺出地對(duì)系統(tǒng)軟件的底層形成機(jī)制進(jìn)行條分縷析,真正提升程序員的自我修養(yǎng)。
兩年前,甲子跟我提起,他在考慮寫(xiě)一本講述計(jì)算機(jī)程序基本工作原理的書(shū),由于代碼背后的許多細(xì)節(jié)現(xiàn)在難以找到完整而又實(shí)用的資料,因此,系統(tǒng)性地講述這些技術(shù)要素一定非常有意義。這是我非常感興趣的話題,因?yàn)樽罱鼛啄陙?lái),我每次給學(xué)生講課或作技術(shù)報(bào)告時(shí),經(jīng)常會(huì)提到程序背后的一些細(xì)節(jié)知識(shí),而當(dāng)有人請(qǐng)我推薦一些參考資料時(shí),我很難想得出有什么恰當(dāng)?shù)膮⒖紩?shū)可供學(xué)習(xí)。我自己也曾想過(guò)要寫(xiě)一點(diǎn)這方面的書(shū),只是一直下不了決心做這件事情。甲子的提議讓我意識(shí)到,寫(xiě)這樣一本書(shū)的機(jī)會(huì)來(lái)了。于是,我們認(rèn)真規(guī)劃了書(shū)的選題。按我的建議,這應(yīng)該是三卷本的書(shū),每卷獨(dú)立,合起來(lái)成一體系。第一卷是基礎(chǔ)篇,介紹程序的基本運(yùn)行過(guò)程,即是您現(xiàn)在看到的這本書(shū)。其他兩卷還需要時(shí)日和機(jī)緣。
在過(guò)去兩年中,我曾經(jīng)以“Inside Windows Programs”為題在多所高校作過(guò)報(bào)告,旨在介紹Windows程序背后的一些支撐技術(shù)。對(duì)于正在學(xué)習(xí)計(jì)算機(jī)或軟件專業(yè)的學(xué)生,或者正在從事軟件開(kāi)發(fā)的工程師們,我認(rèn)為理解這些支撐技術(shù)是很有必要的。試想,即使一個(gè)簡(jiǎn)單的“Hello World!”程序,也依賴于背后的輸入輸出庫(kù)(或流庫(kù))及系統(tǒng)提供的模塊,這種依賴性已經(jīng)成為現(xiàn)代軟件在操作系統(tǒng)環(huán)境下運(yùn)行的一個(gè)必要條件。然而,有關(guān)這些支撐技術(shù)的系統(tǒng)性資料卻少而又少,雖然Internet上并不缺乏任何一方面的細(xì)節(jié)信息,但是,能將程序的編譯和運(yùn)行過(guò)程所涉及的各種技術(shù)全面地串連起來(lái)介紹的,卻尚未有先例。
甲子曾經(jīng)在2006年夏天跟我實(shí)習(xí)過(guò)兩個(gè)月,他幫我搭建了一個(gè)在Windows已有體系結(jié)構(gòu)下將交換空間重定向到遠(yuǎn)程機(jī)器物理內(nèi)存的原型系統(tǒng)。完成這一系統(tǒng)并非易事,而且甲子事前并無(wú)Windows內(nèi)核編程經(jīng)驗(yàn),但是,他憑借扎實(shí)的計(jì)算機(jī)系統(tǒng)軟件功底,成功地打通了從頁(yè)面錯(cuò)誤(page fault)異常例程到遠(yuǎn)程機(jī)器內(nèi)存管理器之間的數(shù)據(jù)通路。在這一段實(shí)習(xí)經(jīng)歷中,我不僅看到了他駕馭代碼和系統(tǒng)的能力,也感受到他做事認(rèn)真負(fù)責(zé)的態(tài)度。因此,當(dāng)他提出要寫(xiě)一本介紹程序基礎(chǔ)的書(shū)時(shí),我認(rèn)為他是非常合適的人選?紤]到寫(xiě)書(shū)的艱巨性,他推薦石凡同學(xué)加入進(jìn)來(lái),這才有了我們?nèi)齻(gè)人的組合。我原先擔(dān)心寫(xiě)作的進(jìn)度,畢竟寫(xiě)這樣一本書(shū)需要大量的時(shí)間投入。幸運(yùn)的是,在甲子和石凡的不懈努力下,這本書(shū)終于面市了。
本書(shū)講解的內(nèi)容,涉及在Windows和Linux兩個(gè)系統(tǒng)平臺(tái)上,一個(gè)應(yīng)用程序在編譯、鏈接和運(yùn)行時(shí)刻所發(fā)生的各種事項(xiàng),包括:代碼指令是如何保存的,庫(kù)文件如何與應(yīng)用程序代碼靜態(tài)鏈接,應(yīng)用程序如何被裝載到內(nèi)存中并開(kāi)始運(yùn)行,動(dòng)態(tài)鏈接如何實(shí)現(xiàn),C/C++運(yùn)行庫(kù)如何工作,以及操作系統(tǒng)提供的系統(tǒng)服務(wù)是如何被調(diào)用的。每個(gè)技術(shù)專題都配備了大量圖示和代碼實(shí)例,力求將復(fù)雜的機(jī)制以簡(jiǎn)潔的形式表達(dá)出來(lái)。本書(shū)最后還提供了一個(gè)小巧且跨平臺(tái)的C/C++運(yùn)行庫(kù)MiniCRT,綜合展示了與運(yùn)行庫(kù)相關(guān)的各種技術(shù)。
關(guān)于寫(xiě)作這本書(shū)的功勞,我不敢掠美。在創(chuàng)作之初,包括擬定提綱及甄選內(nèi)容方面,我跟甲子有過(guò)認(rèn)真而細(xì)致的討論;在寫(xiě)作過(guò)程中,我對(duì)甲子和石凡的初稿提出過(guò)一些建議,尤其在表述方面,同時(shí)我也協(xié)助他們與編輯進(jìn)行了溝通和交流。對(duì)于正文的內(nèi)容,我并無(wú)實(shí)質(zhì)性的貢獻(xiàn),但基于我對(duì)甲子和石凡兩位年輕人的了解,我相信他們自身的技術(shù)實(shí)踐功底,以及足夠的技術(shù)闡釋能力。我期待這本書(shū)能夠真正地提升程序員的自我修養(yǎng),讓程序員總是生活在“知其然,更知其所以然”的代碼曼妙中。
最后,我要感謝這本書(shū)的四位編輯,他們是何艷、方舟、劉鐵鋒和陳元玉,謝謝他們?yōu)檫@本書(shū)付出的努力。還要感謝博文視點(diǎn)團(tuán)隊(duì)的負(fù)責(zé)人周筠女士,謝謝她給予兩位年輕作者的扶持和關(guān)愛(ài)。
潘愛(ài)民
2009年2月于北京微軟
七、作者序2
兩年前,我在浙江大學(xué)的一著名BBS的C++板塊上擔(dān)任版主,而俞甲子則是板上的資深版友(以及前版主)。那時(shí)候我對(duì)鏈接裝載、運(yùn)行庫(kù)等內(nèi)容比較感興趣,自己摸索著在博客上寫(xiě)了一篇關(guān)于鏈接的入門(mén)文章,而這就是一切的開(kāi)始。
我猜想俞甲子可能對(duì)寫(xiě)這么一本書(shū)早有想法,看到我的文章正好找到了同路人。他找到了我和潘愛(ài)民老師,我們一拍即合,就開(kāi)始了這長(zhǎng)達(dá)兩年的寫(xiě)作歷程?紤]到當(dāng)時(shí)俞甲子已經(jīng)在鏈接部分有了相當(dāng)?shù)姆e累,因此我不得不放棄我最有興趣的一部分轉(zhuǎn)而在運(yùn)行環(huán)境上做文章。我把glibc和msvcrt的源代碼翻了個(gè)底朝天,了解到了許多平時(shí)不可能接觸到的內(nèi)幕和技術(shù)細(xì)節(jié)。事實(shí)上,這基本是一個(gè)現(xiàn)學(xué)現(xiàn)賣(mài)的過(guò)程,我一邊學(xué)習(xí)著新的知識(shí),一邊把新知識(shí)組織整理寫(xiě)成文字。讀者在看某些章節(jié)的時(shí)候,會(huì)發(fā)現(xiàn)這些章節(jié)的講解過(guò)程就是一個(gè)源代碼的挖掘過(guò)程,這實(shí)際上也就是我的學(xué)習(xí)過(guò)程。學(xué)習(xí)研究他人的代碼是枯燥而耗時(shí)的,我很高興能夠做這樣一個(gè)先行者,將我的經(jīng)驗(yàn)寫(xiě)進(jìn)書(shū)里,讓讀者能夠避免重復(fù)勞動(dòng),直接獲得其中的經(jīng)驗(yàn)和關(guān)鍵技術(shù)。
本書(shū)所講的內(nèi)容不是活躍在當(dāng)今IT舞臺(tái)上的高新技術(shù),也不是雄踞計(jì)算機(jī)某個(gè)領(lǐng)域的王牌霸主,而是默默服務(wù)于所有計(jì)算機(jī)應(yīng)用的掃地僧。也許閱讀本書(shū)不能夠直接在平時(shí)學(xué)習(xí)工作中的生產(chǎn)力上得到體現(xiàn),但了解計(jì)算機(jī)的臺(tái)前幕后會(huì)對(duì)讀者產(chǎn)生潛移默化的影響。當(dāng)你的程序無(wú)法啟動(dòng)的時(shí)候,你可能會(huì)在腦海里多設(shè)想一種可能性;當(dāng)你的代碼鏈接失敗的時(shí)候,你可能會(huì)更快地意識(shí)到問(wèn)題的所在;當(dāng)你的程序發(fā)生非法操作的時(shí)候,你可能不至于面對(duì)微軟的錯(cuò)誤報(bào)告毫無(wú)頭緒。有人總愛(ài)用“時(shí)效性”評(píng)價(jià)當(dāng)今的IT技術(shù)。仿佛一項(xiàng)技術(shù)的生存期就只有幾年。我不能說(shuō)這樣的想法是錯(cuò)誤的,如今的技術(shù)的確在飛速地更替和發(fā)展。但是本書(shū)所講的技術(shù),大多是成型在十年前,乃至二十年前,它們是整個(gè)計(jì)算機(jī)行業(yè)技術(shù)的根本,也幾乎是現(xiàn)在所有計(jì)算機(jī)應(yīng)用的基礎(chǔ)。在當(dāng)今的計(jì)算機(jī)技術(shù)發(fā)生根本性變革之前,這些技術(shù)還將繼續(xù)存在并保持活力。
我很榮幸能夠有機(jī)會(huì)和讀者分享這些技術(shù),但寫(xiě)作水平有限(我在語(yǔ)文課上歷來(lái)不是個(gè)好學(xué)生),最終在文字和結(jié)構(gòu)上頗有缺憾,只能在這里說(shuō)一聲抱歉。在這里要感謝我小學(xué)、初中和高中的語(yǔ)文老師,謝謝你們當(dāng)初對(duì)我的教導(dǎo),盡管最終可能辜負(fù)了你們的希望。感謝潘老師、博文視點(diǎn)的編輯及所有支持我們的朋友們,謝謝你們對(duì)我們的幫助。最后要感謝我的父母,沒(méi)有你們,我永遠(yuǎn)不可能走到今天這一步。
石凡
2009年2月于杭州
八、作者序3
CPU體系結(jié)構(gòu)、匯編、C語(yǔ)言(包括C++)和操作系統(tǒng),永遠(yuǎn)都是編程大師們的護(hù)身法寶,就如同少林寺的《易筋經(jīng)》,是最為上乘的武功;學(xué)會(huì)了《易筋經(jīng)》,你將無(wú)所不能,任你創(chuàng)造武功;學(xué)會(huì)了編程“易筋經(jīng)”,大師們可以任意開(kāi)發(fā)操作系統(tǒng)、編譯器,甚至是開(kāi)發(fā)一種新的程序設(shè)計(jì)語(yǔ)言!
——佚名
念書(shū)的時(shí)候,作為標(biāo)準(zhǔn)的愛(ài)好技術(shù)的宅男,每天掃一遍各大高校BBS的技術(shù)版面,基本好比一日三餐一樣平常。我對(duì)計(jì)算機(jī)技術(shù)方面的口味很雜,從匯編版到C++到Linux內(nèi)核開(kāi)發(fā)、Linux應(yīng)用開(kāi)發(fā)、游戲開(kāi)發(fā)、網(wǎng)絡(luò)、編程語(yǔ)言、體系結(jié)構(gòu)、移動(dòng)開(kāi)發(fā)、開(kāi)源閉源我都會(huì)參上一腳。
我始終認(rèn)為技術(shù)優(yōu)劣取決于需求,與很多持有“編程語(yǔ)言血統(tǒng)論”的程序開(kāi)發(fā)者不同,我不認(rèn)為C++或Java本身有什么直接可比性,或者OOP與函數(shù)式編程誰(shuí)優(yōu)誰(shuí)劣,我始終堅(jiān)持認(rèn)為作為開(kāi)發(fā)者,MOP(Market/Money Oriented Programming)才是唯一不變的編程范式。于是我往往不參與那些技術(shù)、平臺(tái)、語(yǔ)言教派之間的宗教戰(zhàn)爭(zhēng),這種論戰(zhàn)基本上每周都會(huì)有,我很佩服論戰(zhàn)各方見(jiàn)多識(shí)廣、旁征博引、高屋建瓴的論斷,但我往往只是灌灌水調(diào)節(jié)一下思緒。相反,我很關(guān)注一些與語(yǔ)言、平臺(tái)等相對(duì)獨(dú)立的基本的系統(tǒng)概念方面的問(wèn)題,這些問(wèn)題比較具體,也比較實(shí)用,比如:
為什么程序是從main開(kāi)始執(zhí)行?
“malloc分配的空間是連續(xù)的嗎?”
“PE/ELF文件里面存的是什么?”
“我想寫(xiě)一個(gè)不需要操作系統(tǒng)可以直接在硬件上跑的程序該怎么做?”
“目標(biāo)文件是什么?鏈接又是什么?”
“為什么這段程序鏈接時(shí)報(bào)錯(cuò)?”
“句柄到底是什么東西?”
這些問(wèn)題看似很簡(jiǎn)單但實(shí)際上有很多值得深入挖掘的地方,比如第一個(gè)問(wèn)題圍繞著main函數(shù)執(zhí)行前后可以延伸出一大堆問(wèn)題:程序入口、運(yùn)行庫(kù)初始化、全局/靜態(tài)對(duì)象構(gòu)造析構(gòu)、靜態(tài)和動(dòng)態(tài)鏈接時(shí)程序的初始化和裝載等。我們把這些問(wèn)題歸結(jié)起來(lái),發(fā)現(xiàn)主要是三個(gè)很大的而且連貫的主題,那就是“鏈接、裝載和庫(kù)”。
事實(shí)上,現(xiàn)在市面上和網(wǎng)絡(luò)上能找到的計(jì)算機(jī)技術(shù)方面的書(shū)籍和資料中,什么都很齊全,唯獨(dú)關(guān)于這三個(gè)主題的討論十分稀缺,即使能找到一些也是猶如殘缺的典籍,不僅不完整而且很多已經(jīng)過(guò)時(shí)了。關(guān)于現(xiàn)在通用的Windows和Linux平臺(tái)的鏈接、裝載及PE/ELF文件的詳細(xì)分析,實(shí)在很少見(jiàn)。這個(gè)領(lǐng)域中,最為完整、也最為權(quán)威的莫過(guò)于John R. Levine的《Linkers & Loaders》,這本書(shū)我也前前后后通讀了好幾遍,雖然它對(duì)鏈接和裝載方面的描述較為完整,但是過(guò)于理論化,對(duì)于實(shí)際的系統(tǒng)機(jī)制描述則過(guò)于簡(jiǎn)略。
我始終認(rèn)為對(duì)于一個(gè)問(wèn)題比較好的描述方式,是由一個(gè)很小很簡(jiǎn)單的問(wèn)題或示例入手,層層剝開(kāi)深入挖掘,不僅探究每個(gè)機(jī)制“怎么做”,而且要理解它們“為什么這樣做”,力求深入淺出、圖文并茂,盡力把每一步細(xì)節(jié)都呈現(xiàn)給讀者。這是我一貫的想法,也是我們?cè)诒緯?shū)中努力試圖達(dá)到的效果。
第一次有想寫(xiě)這樣一本書(shū)的念頭是在2006年底,當(dāng)時(shí)我正在念研一,想起未來(lái)還有一年多漫長(zhǎng)而又相對(duì)空閑的研究生生涯,覺(jué)得寫(xiě)一本這樣的書(shū)大概是比較好的“消遣活動(dòng)”。于是我第一時(shí)間想到了在微軟研究院實(shí)習(xí)時(shí)的導(dǎo)師潘愛(ài)民老師,潘老師在寫(xiě)作技術(shù)書(shū)籍方面有很深的功底和豐富的經(jīng)驗(yàn)。我把想法告訴潘老師以后,他十分支持,于是我又找到了當(dāng)時(shí)剛好保送研究生、時(shí)間上也相對(duì)充裕的石凡,我們?nèi)齻(gè)都對(duì)這個(gè)選題十分感興趣,可謂一拍即合。
當(dāng)時(shí)也沒(méi)多想,以為寫(xiě)書(shū)大概也就跟BBS發(fā)帖連載差不多吧。一旦寫(xiě)起來(lái)才發(fā)現(xiàn)自己完全輕視了寫(xiě)書(shū)的工作量。書(shū)中的每一個(gè)章節(jié)、每一個(gè)小段、每一個(gè)例子甚至每一個(gè)用詞有時(shí)候都要斟酌很久,生怕用得不恰當(dāng)誤導(dǎo)了讀者!罢`人子弟”這四個(gè)字罪名可不輕,大有推出午門(mén)斬首五遍以儆效尤之過(guò)。寫(xiě)書(shū)的時(shí)間的確很倉(cāng)促,雖然我們都是在讀研時(shí)寫(xiě)的,按理說(shuō)相對(duì)于已經(jīng)工作的作者來(lái)講,已經(jīng)是有很多閑余的時(shí)間了,但還是經(jīng)常手忙腳亂。想到以前看書(shū)看到作者寫(xiě)的序里,經(jīng)常使用“時(shí)間倉(cāng)促,水平有限”的話,推想作者不過(guò)是出于謙虛不免要客套一下,F(xiàn)在輪到自己寫(xiě)序了,終于感覺(jué)到了這八個(gè)字的分量。即使到現(xiàn)在已近完稿,我們還是心里十分忐忑,因?yàn)檫有不少地方的確寫(xiě)得不夠完善。也聽(tīng)到了很多第一批讀者的反饋意見(jiàn),很多建議都正中這本書(shū)的軟肋,我們也根據(jù)大家的意見(jiàn)又一次進(jìn)行了修改,這已經(jīng)是反反復(fù)復(fù)的第N次修訂了。
這本書(shū)前前后后花了兩年多的時(shí)間一直沒(méi)有完稿,由于截稿時(shí)間快到了,我們才終于定稿,因?yàn)閷?shí)在沒(méi)有辦法做到完美,只能向無(wú)限接近完美努力。最后,我們?cè)凇爸焙汀熬幹敝g猶豫了很久,想到本書(shū)凝聚了我們很多的心血,還是誠(chéng)惶誠(chéng)恐地寫(xiě)上了“著”字,權(quán)當(dāng)給自己壯膽了。我們也相信,本書(shū)雖然沒(méi)做到完美,但是它一定會(huì)給你帶來(lái)一些你以前想看、想了解而又找不到的東西;蛘咭郧霸诰幊踢^(guò)程中困惑了你很久,但始終沒(méi)有找到解釋的問(wèn)題,當(dāng)在本書(shū)中終于找到答案且大呼“原來(lái)如此!”時(shí),我們也就很欣慰了!
關(guān)于本書(shū)的書(shū)名筆者們也討論了很久,征詢過(guò)很多意見(jiàn),最終還是決定用“程序員的自我修養(yǎng)”作為書(shū)名,將“鏈接、裝載與庫(kù)”作為副標(biāo)題。書(shū)名源自于俄羅斯的演員斯坦尼斯拉夫斯基創(chuàng)作的《演員的自我修養(yǎng)》,作者為了寫(xiě)這本書(shū)前前后后修改了三十年之久,臨終前才同意不再修改,拿去出版。使用這個(gè)書(shū)名一方面是本書(shū)的內(nèi)容的確不是介紹一門(mén)新的編程語(yǔ)言或展示一些實(shí)用的編程技術(shù),而是介紹程序運(yùn)行背后的機(jī)制和由來(lái),可以看作是程序員的一種“修養(yǎng)”;另一方面是向斯坦尼斯拉夫斯基致敬,向他對(duì)作品精益求精的精神致敬。
在本書(shū)的創(chuàng)作過(guò)程中,很多人對(duì)我們的支持和幫助難以言表。這里我要感謝博文視點(diǎn)的幾位編輯何艷、方舟、劉鐵鋒和陳元玉等,他們?yōu)楸緯?shū)付出了很多心血;特別要感謝博文視點(diǎn)的周筠老師,這本書(shū)能夠面世離不開(kāi)她的支持和努力。另外也要感謝浙江大學(xué)的張曉龍博士,他為本書(shū)提出了很多建議,并且貢獻(xiàn)了“DLL HELL”一節(jié)。
俞甲子
2009年2月于杭州
第1部分 簡(jiǎn)介
第1章 溫故而知新
1.1 從HELLO WORLD 說(shuō)起
1.2 萬(wàn)變不離其宗
1.3 站得高,望得遠(yuǎn)
1.4 操作系統(tǒng)做什么
1.5 內(nèi)存不夠怎么辦
1.6 眾人拾柴火焰高
1.7 本章小結(jié)
第2部分 靜態(tài)鏈接
第2章 編譯和鏈接
2.1 被隱藏了的過(guò)程
2.2 編譯器做了什么
2.3 鏈接器年齡比編譯器長(zhǎng)
2.4 模塊拼裝——靜態(tài)鏈接
2.5 本章小結(jié)
第3章 目標(biāo)文件里有什么
3.1 目標(biāo)文件的格式
3.2 目標(biāo)文件是什么樣的
3.3 挖掘SIMPLESECTION.O
3.4 ELF 文件結(jié)構(gòu)描述
3.5 鏈接的接口——符號(hào)
3.6 調(diào)試信息
3.7 本章小結(jié)
第4章 靜態(tài)鏈接
4.1 空間與地址分配
4.2 符號(hào)解析與重定位
4.3 COMMON 塊
4.4 C++相關(guān)問(wèn)題
4.5 靜態(tài)庫(kù)鏈接
4.6 鏈接過(guò)程控制
4.7 BFD 庫(kù)
4.8 本章小結(jié)
第5章 WINDOWS PE/COFF
5.1 WINDOWS 的二進(jìn)制文件格式PE/COFF 134
5.2 PE 的前身——COFF
5.3 鏈接指示信息
5.4 調(diào)試信息
5.5 大家都有符號(hào)表
5.6 WINDOWS 下的ELF——PE
5.7 本章小結(jié)
第3部分 裝載與動(dòng)態(tài)鏈接
第6章 可執(zhí)行文件的裝載與進(jìn)程
6.1 進(jìn)程虛擬地址空間
6.2 裝載的方式
6.3 從操作系統(tǒng)角度看可執(zhí)行文件的裝載
6.4 進(jìn)程虛存空間分布
6.5 LINUX 內(nèi)核裝載ELF 過(guò)程簡(jiǎn)介
6.6 WINDOWS PE 的裝載
6.7 本章小結(jié)
第7章 動(dòng)態(tài)鏈接
7.1 為什么要?jiǎng)討B(tài)鏈接
7.2 簡(jiǎn)單的動(dòng)態(tài)鏈接例子
7.3 地址無(wú)關(guān)代碼
7.4 延遲綁定(PLT)
7.5 動(dòng)態(tài)鏈接相關(guān)結(jié)構(gòu)
7.6 動(dòng)態(tài)鏈接的步驟和實(shí)現(xiàn)
7.7 顯式運(yùn)行時(shí)鏈接
7.8 本章小結(jié)
第8章 LINUX 共享庫(kù)的組織
8.1 共享庫(kù)版本
8.2 符號(hào)版本
8.3 共享庫(kù)系統(tǒng)路徑
8.4 共享庫(kù)查找過(guò)程
8.5 環(huán)境變量
8.6 共享庫(kù)的創(chuàng)建和安裝
8.7 本章小結(jié)
第9章 WINDOWS 下的動(dòng)態(tài)鏈接
9.1 DLL 簡(jiǎn)介
9.2 符號(hào)導(dǎo)出導(dǎo)入表
9.3 DLL 優(yōu)化
9.4 C++與動(dòng)態(tài)鏈接
9.5 DLL HELL
9.6 本章小結(jié)
第4部分 庫(kù)與運(yùn)行庫(kù)
第10章 內(nèi)存
10.1 程序的內(nèi)存布局
10.2 棧與調(diào)用慣例
10.3 堆與內(nèi)存管理
10.4 本章小結(jié)
第11章 運(yùn)行庫(kù)
11.1 入口函數(shù)和程序初始化
11.2 C/C++運(yùn)行庫(kù)
11.3 運(yùn)行庫(kù)與多線程
11.4 C++全局構(gòu)造與析構(gòu)
11.5 FREAD 實(shí)現(xiàn)
11.6 本章小結(jié)
第12章 系統(tǒng)調(diào)用與API
12.1 系統(tǒng)調(diào)用介紹
12.2 系統(tǒng)調(diào)用原理
12.3 WINDOWS API
12.4 本章小結(jié)
第13章 運(yùn)行庫(kù)實(shí)現(xiàn)
13.1 C 語(yǔ)言運(yùn)行庫(kù)
13.2 如何使用MINI CRT
13.3 C++運(yùn)行庫(kù)實(shí)現(xiàn)
13.4 如何使用MINI CRT++
13.5 本章小結(jié)
附錄A
A.1 字節(jié)序(BYTE ORDER)
A.2 ELF 常見(jiàn)段
A.3 常用開(kāi)發(fā)工具命令行參考
索引
第1部分 簡(jiǎn)介
第1章 溫故而知新
1.2 萬(wàn)變不離其宗
計(jì)算機(jī)是個(gè)非常廣泛的概念,大到占用數(shù)層樓的用于科學(xué)計(jì)算的超級(jí)計(jì)算機(jī),小到手機(jī)上的嵌入式芯片都可以被稱為計(jì)算機(jī)。雖然它們的外形、結(jié)構(gòu)和性能都千差萬(wàn)別,但至少它們都有“計(jì)算”這個(gè)概念。在本書(shū)里面,我們將計(jì)算機(jī)的范圍限定在最為流行、使用最廣泛的PC機(jī),更具體地講是采用兼容x86指令集的32位CPU的個(gè)人計(jì)算機(jī)。原因很簡(jiǎn)單:因?yàn)楣P者手上目前只有這種類(lèi)型的計(jì)算機(jī)可供操作和實(shí)驗(yàn),不過(guò)相信90%以上的讀者也是,所以在這一點(diǎn)上我們很快能達(dá)成共識(shí)。其實(shí)選擇具體哪種平臺(tái)并不是最關(guān)鍵的,雖然各種平臺(tái)的軟硬件差別很多,但是本質(zhì)上它們的基本概念和工作原理都是一樣的,只要我們能夠掌握一種平臺(tái)上的技術(shù),那么其他的平臺(tái)都是大同小異的,很輕松地可以舉一反三。所以我們相信,只有你能夠深刻地理解x86平臺(tái)下的系統(tǒng)軟件背后的機(jī)理,當(dāng)有一天你需要在MIPS指令集的嵌入式平臺(tái)上做開(kāi)發(fā),或者需要為64位的Windows或tinux開(kāi)發(fā)應(yīng)用程序的時(shí)候,你很快就能找到它們之間的相通之處。
撇開(kāi)計(jì)算機(jī)硬件中紛繁復(fù)雜的各種設(shè)備、芯片及外圍接口等,站在軟件開(kāi)發(fā)者的角度看,我們只須抓住硬件的幾個(gè)關(guān)鍵部件。對(duì)于系統(tǒng)程序開(kāi)發(fā)者來(lái)說(shuō),計(jì)算機(jī)多如牛毛的硬件設(shè)備中,有三個(gè)部件最為關(guān)鍵,它們分別是中央處理器CPU、內(nèi)存和I/O控制芯片,這三個(gè)部件幾乎就是計(jì)算機(jī)的核心了;對(duì)于普通應(yīng)用程序開(kāi)發(fā)者來(lái)說(shuō),他們似乎除了要關(guān)心CPU以外,其他的硬件細(xì)節(jié)基本不用關(guān)心,對(duì)于一些高級(jí)平臺(tái)的開(kāi)發(fā)者來(lái)說(shuō)(如Java、.NET或腳本語(yǔ)言開(kāi)發(fā)者),連CPU都不需要關(guān)心,因?yàn)檫@些平臺(tái)為它們提供了一個(gè)通用的抽象的計(jì)算機(jī),他們只要關(guān)心這個(gè)象的計(jì)算機(jī)就可以了。
……