深入理解計算機第七章

2022-08-31 11:33:09 字數 2879 閱讀 4592

在第七章鏈結中,鏈結可以在編譯時由經他編譯器完成,也可以在載入時和執行時由動態鏈結器來完成。鏈結器處理可以為目標檔案的二進位制檔案,它有三種不同的形式:可重定位和可執行和共享的。

靜態鏈結是由像gcc這樣的編譯驅動器呼叫的。

多個目標檔案可以被絨對映到儲存器中,並執行這個程式。

載入器將可執行檔案的內容對映到儲存器,並執行這個程式。

被編譯為位置無關**的共享庫可以載入到任何地方,也可以在執行時被多個程序共享。為了載入和鏈結和訪問共享庫的函式和資料,應用程式還可以在執行時使用動態的鏈結器。

(1)c預處理器:源程式main.c->ascii碼中間檔案main.i

(2)c編譯器:main.i->ascii碼組合語言檔案main.s

(3)c彙編器:main.s->可重定位目標檔案

2.執行鏈結器程式ld,將各種.o檔案以及必要的系統目標檔案組合起來,建立可執行檔案。

3.執行可執行檔案:./可執行檔案名字

4.外殼呼叫作業系統中載入器函式,拷貝可執行檔案中的**和資料到儲存器,將控制轉移到這個程式的開頭

1.以一組可重定位目標檔案和命令列引數作為輸入,生成乙個完全鏈結的可以載入和執行的可執行目標檔案作為輸出。

2.輸入的可重定位的目標檔案由各種不同的**和資料節組成。

3.指令在乙個節中,初始化的全域性變數在另乙個節中,而未初始化的變數又在另外乙個節中。

目標檔案定義和引用符號。符號解析的目的是將每個符號引用剛好和乙個符號定義聯絡起來。

編譯器和彙編器生成從位址0開始的餓**和資料節。鏈結器通過把每個符號定義與乙個儲存器位置聯絡起來,然後修改所有對這些符號的引用,使得它們指向這個儲存器位置,從而重定位這些節。

-編譯器和彙編器生成可重定位目標檔案(包括共享目標檔案)。鏈結器生成可執行目標檔案。從技術上來說,乙個目標模組就是乙個位元組序列,而乙個目標檔案就是乙個存放在磁碟檔案中的目標模組。

-編譯器和彙編器生成可重定義目標檔案(包括共享目標檔案)。鏈結器生成可執行目標檔案。

目標檔案三種形式:可重定位目標檔案,可執行目標檔案,共享目標檔案。

目標檔案格式:linux——可執行可連線(elf格式)

windows——可移植可執行格式(pe)

。elf頭(elf header)以乙個16位元組的序列開始,這個序列描述了生成該檔案的系統的字的大小和位元組順序。elf頭剩下的部分包含幫助鏈結器語法分析和解釋目標檔案的資訊。其中包括elf頭的大小、目標檔案的型別(如可重定位、可執行或是共享的)、機器型別(如ia32)、節頭部表的檔案偏移,以及節頭部表中的條目大小和數量。不同的節的位置和大小是由節頭部表描述的,其中目標檔案中每個節都有乙個固定大小的條目。

夾在elf頭和節頭部表之間的都是借。乙個典型的elf可重定位目標檔案包含下面幾個節:

每個可重定位目標模組m都有乙個符號表,包含m所定義和引用的符號的資訊。

1.有m定義並能被其他模組引用的全域性符號。全域性鏈結器對應於非靜態的c函式以及被定義為cstatic 屬性的全域性變數。

2.有其他模組定義並被模組m以引用的全域性符號——外部符號,對應於定義在其他模組中的c函式和變數

3.只被模組m定義和引用的本地符號。

在符號解析的階段,鏈結器從左到右按照它們在編譯器驅動程式命令列上出現的相同順序來掃瞄可重定位目標檔案和存檔檔案。在這次掃瞄中,鏈結器維持乙個可重定位目標檔案的集合e(這個集合中的檔案會被合併起來形成可執行檔案),乙個未解析的符號(即引用了但是尚未定義的符號)集合u,以及乙個在前面輸入檔案中已定義的符號集合d。初始時,e、u和d都是空的。

重定位有兩步組成:

1.重定位節和符號定義。在這一步中,鏈結器將所有相同型別的節合併為同一型別的新的聚合節。然後,鏈結器將執行時儲存器位址賦給新的聚合節,賦給輸入模組定義的每個節,以及賦給輸入模組定義的每個符號。當這一步完成時,程式中的每個指令和全域性變數都有唯一的執行時儲存器位址了。

2.重定位節中的符號引用。在這一步中,鏈結器修改**節和資料節中對每個符號的引用,使得它們指向正確的執行時位址。為了執行這一步,鏈結器依賴於稱為重定位條目的可重定位目標模組中的資料結構。

可執行目標檔案的格式類似於可重定位目標檔案的格式。elf頭部描述檔案的總體格式。它還包括程式的入口點,也就是當程式執行時要執行的第一條指令的位址。.text 、.rodata和.data 節和可重定位目標檔案中的節是相似的,除了這些節已經被重定位到它們最終的執行時儲存器位址以外。.init節定義了乙個小函式,叫做_init,程式的初始化**會呼叫它。

每個unix程式都有乙個執行時儲存器映像。例如:在32位linux系統中,**段總是從位址(0x8048000)處開始。資料段是在接下來的下乙個4kb對齊的位址處。執行時堆在讀/寫段之後接下來的第乙個4kb對齊的位址處,並童工呼叫malloc庫往上增長。還有乙個段是為共享庫保留的。使用者棧總是從最大的合法使用者位址開始,向下增長的(向低儲存器地方向增長)。從棧的上部開始的段是為作業系統駐留儲存器的部分(也就是核心)的**和資料保留的。

共享庫是致力與解決靜態庫缺陷的乙個現代創新產物。共享庫是乙個目標模組,在執行時,可以載入到任意的儲存器位址,並加乙個在儲存器中的程式鏈結起來。這個過程稱為動態鏈結,是由乙個叫做動態鏈結器的程式來執行的。共享庫也稱為共享目標,在unix系統中通常用.so字尾來表示。

-分發軟體

-構建高效能web伺服器

pic資料引用

pic函式呼叫

深入理解計算機系統 第七章 鏈結

這一章重讀讀了比較久。按照書裡參考文獻說明這一欄的說明,鏈結處在編譯器 計算機體系結構和作業系統的交叉點上,要求理解 生成 機器語言程式設計 程式例項化和虛擬儲存器。這一章和上一章的風格相去甚遠,上一章給我留下的就是不斷的計算 更優的計算,這一章記憶為主。現在重讀,感覺有些工具是可以記錄一下的。這一...

第七章 深入理解多型

1.黎克特制替換原則 在乙個軟體系統中,如果子類能替代父類出現的位置,而對整個軟體的功能沒有任何影響,那麼就稱為黎克特制替換原則 2.實現物件導向的多型性有哪幾種方法?總共有3種,第一種,虛方法實現多型,第二種 抽象方法實現多型 第三種 介面實現多型 目前為止,我們學了兩種 第一種 虛方法實現多型 ...

《深入理解計算機系統》第七章讀書筆記

前言 鏈結是將各種 和資料部分收集起來並組合成為乙個單一檔案的過程,這個檔案可被載入 或拷貝 到儲存器並執行。鏈結可以執行於編譯時,也就是在源 被翻譯成機器 時 也可以執行於載入時,也就是在程式被載入器載入到儲存器並執行時 甚至執行於執行時,由應用程式來執行。在早期的計算機系統中,鏈結是手動執行的。...