程序的鏈接與裝入


我們的代碼會經過下面這4個環節,從而形成最終文件 。(C語言為例)

預處理, 展開頭文件/宏替換/去掉注釋/條件編譯                      (test.i main .i)
編譯,    檢查語法,生成匯編                                                      ( test.s  main .s)
匯編,   匯編代碼轉換機器碼                                                         (test.o main.o)
鏈接     鏈接到一起生成可執行程序                                              a.out

  • 布局如下:

    給定地址 DS:SI = 0x0200:0x0230

    實模式下地址轉換

    0x0200 << 4 + 0x0230 = 0x02230

    保護模式下地址轉換

    由0x0200 = (0000 0010 0000 0000)2

    查找全局描述符表第64項描述符給出的分段基址,加上0x0230才是線性地址(若為分頁,則是物理地址

程序的編譯

由編譯程序將用戶源代碼編譯成cpu可執行的目標代碼(.o文件),產生了若干個目標模塊(即若干程序段)。

程序的裝入

由裝入程序將裝入模塊裝入內存,構造PCB,形成進程,開始運行(使用物理地址)。

1.絕對裝入方式

在編譯時,如果知道程序將駐留在內存的什么位置,那么,編譯程序將產生絕對地址的目標代碼。 絕對裝入程序按照裝入模塊中的地址,將程序和數據裝入內存。 裝入模塊被裝入內存后,由於程序中的邏輯地址與實際內存地址完全相同,故不須對程序和數據的地址進行修改。程序中所使用的絕對地址,既可在編譯或匯編時給出,也可由程序員直接賦予。

注:
由於內存划分為系統區和用戶區,程序實際在用戶區執行,故實際上程序的實際內存地址也有一定的增加,不可能像邏輯地址一樣從0開始。

  • 優點:使CPU執行目標代碼快

  • 缺點:(1)由於內存大小限制,能裝入內存並發執行的進程數大大減少

    ​ (2)編譯程序必須知道內存的當前空閑地址部分和其地址,並且把進程的不同程序段連續地存放起來,編譯非常復雜。

2.靜態地址重定位

絕對裝入方式只能將目標模塊裝入到內存中事先指定的位置。在多道程序環境下,編譯程序不可能預知所編譯的目標模塊應放在內存的何處,因此,絕對裝入方式只適用於單道程序環境

在多道程序環境下,所得到的目標模塊的起始地址通常是從 0 開始的,程序中的其它地址也都是相對於起始地址計算的。此時應采用可重定位裝入方式,根據內存的當前情況,將裝入模塊裝入到內存的適當位置。

靜態地址重定位:即在程序裝入對目標代碼裝入內存的過程中完成,是指在程序開始運行前,程序中指令和數據的各個地址均已完成重定位,即完成虛擬地址到內存地址映射。地址變換通常是在裝入時一次完成的,以后不再改變

  • 優點:無需硬件支持

  • 缺點:(1)程序重定位之后就不能在內存中搬動了;

    ​ (2)要求程序的存儲空間是連續的,不能把程序放在若干個不連續的區域中。

3.動態地址重定位

可重定位裝入方式可將裝入模塊裝入到內存中任何允許的位置,故可用於多道程序環境;但這種方式並不允許程序運行時在內存中移動位置。因為,程序在內存中的移動,意味着它的物理位置發生了變化, 這時必須對程序和數據的地址(是絕對地址)進行修改后方能運行。然而,實際情況是,在運行過程中它在內存中的位置可能經常要改變,此時就應采用動態運行時裝入的方式。

動態地址重定位:不是在程序執行之前而是在程序執行過程中進行地址變換。更確切的說,是把這種地址轉換推遲到程序真正要執行時才進行,即在每次訪問內存單元前才將要訪問的程序或數據地址變換成內存地址。動態重定位可使裝入模塊不加任何修改而裝入內存。為使地址轉換不影響指令的執行速度,這種方式需要一個重定位寄存器的支持。

優點:(1)目標模塊裝入內存時無需任何修改,因而裝入之后再搬遷也不會影響其正確執行,這對於存儲器緊縮、解決碎片問題是極其有利的;

​ (2)一個程序由若干個相對獨立的目標模塊組成時,每個目標模塊各裝入一個存儲區域,這些存儲區域可以不是順序相鄰的,只要各個模塊有自己對應的定位寄存器就行。

缺點:需要硬件支持。

程序的鏈接

根據外部訪問符號名表(如變量名、函數名等),將經過編譯或匯編 得到的一組目標模塊以及它們所需要的庫函數,裝配成一個完整的裝入模塊

1.靜態鏈接方式

下圖B和C都屬於外部調用符號,在將這幾個目標模塊裝配成一個裝入模塊時,須解決以下兩個問題:

(1)  對相對地址進行修改。

(2)  變換外部調用符號。

這種先進行鏈接所形成的一個完整的裝入模塊,又稱為可執行文件。通常都不再拆開它,要運行時可直接將它裝入內存。這種事先進行鏈接,以后不再拆開的鏈接方式,稱為靜態鏈接方式。

2.裝入時動態鏈接(所有的模塊都裝入內存 )

用戶源程序經編譯后所得的目標模塊,是在裝入內存時邊裝入邊鏈接的, 然后再按照上圖所示的方式來修改目標模塊中的相對地址。

優點:

(1) 、 便於修改和更新。對於經靜態鏈接裝配在一起的裝入模塊,如果要修改或更新其中的某個目標模塊,則要求重新打開裝入模塊。這不僅是低效的,而且有時是不可能的。若采用動態鏈接方式,由於各目標模塊是分開存放的,所以要修改或更新各目標模塊是件非常容易的事。
(2)、  便於實現對目標模塊的共享。在采用靜態鏈接方式時,每個應用模塊都必須含有其目標模塊的拷貝,無法實現對目標模塊的共享。但采用裝入時動態鏈接方式,OS則很容易將一個目標模塊鏈接到幾個應用模塊上,實現多個應用程序對該模塊的共享。

3.運行時動態鏈接(需要某個模塊時才裝入內存)

在許多情況下,應用程序在運行時,每次要運行的模塊可能是不相同的。但由於事先無法知道本次要運行哪些模塊,故只能是將所有可能要運行到的模塊都全部裝入內存,並在裝入時全部鏈接在一起。顯然這是低效的,因為往往會有些目標模塊根本就不運行。比較典型的例子是作為錯誤處理用的目標模塊,如果程序在整個運行過程中都不出現錯誤,則顯然就不會用到該模塊。

在執行過程中,當發現一個被調用模塊尚未裝入內存時,立即由OS去找到該模塊並將之裝入內存,把它鏈接到調用者模塊上。凡在執行過程中未被用到的目標模塊,都不會被調入內存和被鏈接到裝入模塊上,這樣不僅可加快程序的裝入過程,而且可節省大量的內存空間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM