可執行檔案裝載與程序 動態鏈結

2022-08-16 18:03:16 字數 2477 閱讀 4868

我們知道,可執行檔案只有裝載到記憶體以後才能被cpu執行。要了解裝載的過程,就必須先了解程序的虛擬位址空間的概念。

一,程序虛擬位址空間的概念

1,程序和程式的區別

。。程式是靜態的概念,是未裝入記憶體的;程序是動態的概念,有時候也叫它「runtime」,是已經裝入記憶體並且跑了起來的。

2,程序虛擬位址空間

。。每個程式被執行起來以後,它將擁有自己獨立的虛擬位址空間,其大小由計算機的硬體平台決定,具體說是由cpu的位數決定的,如32位決定了虛擬位址空間的大小為:0到2^32-1,即4gb虛擬空間的大小。64位即為0到2^64-1,即17 179 869 184gb。  

以32位機為例,4gb的虛擬位址空間其中有1gb被作業系統占用,剩下的3gb中,又有一些其他用途的空間不能被使用,所以程序可以使用的也就只有不到3gb。

二,裝載的方式

程式執行所需要的指令和資料都必須在記憶體中才能夠正常執行,但是很多情況下,程式所需要的記憶體數量總是大於物理記憶體的數量。這個時候就需要新增記憶體,然而記憶體是昂貴的。因此人們想出了動態裝入這麼個辦法。

動態裝載,就是將程式常用的部分駐留在記憶體中,而將一些不太常用的資料存放在磁碟裡面。

動態裝載有兩種經典的方式:一是覆蓋裝入;二是頁對映。

1》覆蓋裝入

因為覆蓋裝入目前已經漸漸被淘汰了,我們在此只簡單的描述一下,如果乙個程式,主模組為main,main需要呼叫a、b這兩個子模組,三個模組的大小分別為 1024、512、256(位元組),若將其全部裝入記憶體,則需要1792個位元組。其中a和b無依賴關係(即兩者無相互呼叫),但是如果採用覆蓋裝入的方法,則如圖

當main呼叫a模組時,裝入a模組,不裝入b模組;當呼叫b模組時,裝入b模組,覆蓋掉a模組。因此可以節省256的空間。但是裝入覆蓋操作很花費時間,若是有很多模組,相互依賴關係一多,這種時間上的浪費是很巨大的。

如下,a和b無相互呼叫。c和d無相互呼叫,e和f無相互呼叫。當然,a、c、d與b、e、f無呼叫。但是main要呼叫e就必須有b。就跟樹的結構一樣,main是根結點。a、b是main的子結點,c、d是a的子結點,e、f是b的子結點。樹間不可相互呼叫。

當main已經呼叫了c,接著需要呼叫e,則需要把c和b從磁碟讀入記憶體,並且需要覆蓋掉a和c,這樣一定很慢。總之,覆蓋裝入是一種典型的以時間換空間的方法。

2》頁對映

頁對映的思想是將記憶體和所以磁碟中的資料和指令按照「頁(page)」為單位劃分成若干頁,以後所有的裝載和操作的單位就是頁。

假設有一32位的機器,16kb的記憶體,每個頁大小為4k位元組,則共有4個頁。假設乙個程式總共有32kb的指令和資料。很明顯,一次性不能全部裝入到記憶體,因此得採用動態裝入的方法。

程式                               記憶體

左側是將程式被分出來的8個頁,右側是記憶體被分的4個頁。假設程式開始時入口位址在p0,這時作業系統發現p0並不在記憶體中,,於是將f0分配給p0,並且將p0的內容裝入f0;執行一段時間後,程式需要用到p5,於是作業系統就將p5裝進f1;接著,當用到p3、p6時,作業系統就將它們分別裝入f2、f3。到現在,記憶體的頁已經全部被用到了,這時如果需要裝入p4,就必須覆蓋掉乙個頁,則就涉及到演算法的問題了,比如按照fifo,將f0頁上的p0覆蓋掉,。又或者按照lur,將用的最少次數的頁覆蓋掉。

我們知道,裝載的過程其實就是將乙個靜態的程式轉成乙個動態的程序的過程,我們反過來學習一下程序是如何建立的,就可以明白裝載究竟都幹了些什麼了。

程序的建立:

建立乙個程序,然後裝載相應的可執行檔案並且執行。

以上過程需要三步:

1,建立乙個獨立的虛擬位址空間。

此處的建立虛擬位址空間並不是真正的空間,而是建立對映函式所需要的相應的資料結構,比如頁表,它存著虛擬空間和物理空間的聯絡。

2,讀取可執行檔案頭並且建立虛擬空間與可執行檔案的對映關係。

當程式發生頁錯誤時,作業系統 將從物理記憶體中分配乙個物理頁,然後將該」缺頁「從磁碟中讀取到記憶體中,再設定缺頁的虛擬頁和物理頁的對映關係,這樣程式才得以正常執行。設定缺頁的虛擬頁和物理頁的對映關係(資料結構)是裝載的核心。

3,將cpu的指令暫存器設定成可執行檔案的入口位址,啟動執行。

作業系統通過設定cpu的指令暫存器將控制權轉交給了程序,由此程序開始執行。(此過程中,作業系統可看做是執行了一條跳轉指令,直接調到可執行檔案的入口位址。也就是elf標頭檔案的入口位址中去。)

關於動態鏈結,動態鏈結是為了解決靜態鏈結出現的空間浪費和更新困難而被提出的,簡單來說,就是不對那些組成程式的目標檔案進行鏈結,等到程式要執行時才進行鏈結。

動態鏈結的基本思想是把程式按照模組拆分成各個相對獨立部分,在程式執行時才將它們鏈結在一起形成乙個完整的程式。

可執行檔案裝載進記憶體

程式裝載面臨的挑戰 可執行程式載入後占用的記憶體空間應該是連續的。寫好的 變成了指令之後,是一條一條順序執行的就可以了 不能讓程式自己規定在記憶體中載入的位置,因為可能你想要的記憶體位址已經被其他載入了的程式占用了。虛擬記憶體位址 指令裡用到的記憶體位址 物理記憶體位址 實際在記憶體硬體裡面的空間位...

Linux下ELF可執行檔案裝載與執行

1 建立子程序 核心建立task struct資料結構,繼承父程序的虛擬位址空間 virtual memory space,vms 2 呼叫execve 系統呼叫執行指定的elf檔案 1 呼叫核心態函式sys execve 動態申請乙個linux binprm資料結構,並用elf可執行檔案的資料填充...

第六章 可執行檔案的裝載與程序 (總結)

6.1 程序虛擬位址空間 可能通過判斷c語言程式中指標所佔的空間來計算虛擬位址空間的大小,一般c語言指標大小的倍數與虛擬空間的位數相同,如32位平台下的指標為32位。6.2裝載的方式 1 覆蓋裝入 overlay 2 頁對映 paging 是虛擬儲存機制的一部分,現在用的較多。有一些演算法來排程哪些...