程式的載入

2021-07-09 14:04:33 字數 2097 閱讀 7701

當乙個程式使用fork()建立了乙個子程序時候,這個子程序共享父程序的**和資料,所以通常再用exec()載入執行另乙個新程式,此時子程序的**、資料(包括堆、棧)將完全被新程式替換掉,並在子程序中開始執行新程式,這個過程就是新程序的載入,下面就以0.11核的exec()函式為基礎說一下linux新程序的載入過程是怎樣的。

想到新程序的載入,很自然的就會想到這樣乙個思路:載入什麼,載入到哪,怎麼載入。下面就順著這個思路一起了解一下linux新程序的載入過程。

一、載入什麼

大家知道,linux中可以直接執行的檔案是二進位制可執行檔案和shell指令碼檔案,那麼新程式的載入和執行就是對這兩種檔案進行載入和執行。

二、載入到哪

程式是在物理記憶體執行的,之前我已經提到,乙個程序在記憶體中主要占用的幾個部分,分別是**段、資料段、bss,棧,堆,引數。其中,**、資料、bss的內容是可執行檔案中對應的內容,引導程式並不是把它們的內容從可執行程式中填充到記憶體中,而是將它們的資訊(基位址、長度等)更新到程序控制塊(task_struct)中,當cpu第一次實際定址執行的時候,就會引起缺頁中斷,作業系統再將實際的內容從可執行檔案中複製內容到物理記憶體中。堆的內容是程式執行中動態分配的,所以引導程式只是將它的起始位址更新到程序控制塊中,執行過程中遇到動態分配記憶體的操作的時候再在物理記憶體分配實際的頁。引數區在新程序載入的時候要存入環境變數和命令列引數列表。棧在程式載入時候存入的內容就是環境引數列表和命令列引數列表的指標和命令列引數的個數。

線性位址空間

環境引數列表

命令列引數列表

環境引數列表指標

命令列引數列表指標

命令列引數個數

……………

堆疊增長區

bss 資料

** 引數棧堆

sp                                         資料段/**段/堆疊段基位址

三、如何載入

下面就說一下新程式載入並執行的具體過程,具體是以0.11核的exec.c檔案的內容為基礎的。 1)

申請物理頁,

填充引數

引數的填充要分兩種情況,一種是檔案是shell指令碼檔案,這個時候不但要把shell檔案的命令列引數填充進去,還要解析shell檔案頭資訊,將要傳入shell程式的引數也要填充到某部分物理記憶體內,這樣引數區中命令列引數列表的長度就加長了:shell程式引數列表。之後,把shell程式作為新的可執行程式,重新啟動載入過程。另一種情況就是二進位制的可執行檔案,這個時候就把環境引數和命令列引數填充到某部分物理記憶體就行了。這步之後,就會得到引數頁的頁指標(這些頁在物理記憶體中)乙個二進位制檔案(包括shell程式本身)的記憶體i節點。 2)

清理工作:

關閉指定的開啟的檔案;復位協處理器標誌;釋放頁目錄項和頁表項。 3)

更新ldt:

4)建立引數列表用的物理頁與邏輯位址的對應關係

就是將儲存引數列表的那些物理頁利用頁表對映到程序邏輯位址空間的最上面的部分,具體做法就是根據邏輯位址計算出頁目錄項表中頁表項的位置,從而找到(新建)頁表,再在頁表中建立頁與實體地址的對應關係。

建立了對應關係,就相當於把引數列表填充到了程序位址空間中了。 5)

在棧(使用者棧)中建立參數列指標表:

程序空間的最上面是引數列表,在它的下面就是棧,棧中要存三個資料:環境引數列表指標、使用者引數列表指標、命令列引數個數。 6)

更新task_struct中**段、資料段、堆段的尾值;更新堆疊開始指標值;重新設定使用者id和組id。 7)

更改上層程序(呼叫exec的程序)的堆疊內容,使ip指向新程序的**開始處:

ex.a_entry;使棧指標指向新程序的棧頂,也就是存放命令列引數的地方。由於新程序的**段、資料段、堆疊段的段選擇符和原來程序都是一樣的,都是指向ldt[2]處,所以不必更改棧中cs、fs、ss的值。

以上就是exec的具體工作過程,當它返回的時候,從棧中彈處的新程序的**位址和堆疊位址,也就轉向了新程式進行執行,當然,前面說過,此時**段核資料段中是沒有內容的,cpu是採用「按需載入」的機制。

附:可以看出,這裡的「載入」是廣義的,不但有「複製」的意思,也有「設定」的意思。引數是從記憶體(命令列引數、環境引數)或者可執行檔案中(shell指令碼中的shell引數)複製到記憶體中的;程式的**段、資料段則是在段描述符中設定它們的段資訊,並沒有實際把能內容複製進來。

Java程式的載入過程

public class myclass extends myclassfather unstatic u new unstatic final unstaticfinal uf new unstaticfinal static static final staticfinal sf new sta...

java程式載入過程

public class myclass extends myclassfather unstatic u new unstatic final unstaticfinal uf new unstaticfinal static static final staticfinal sf new sta...

c c 程式載入過程

c c 程式編譯流程 預處理 編譯 彙編 鏈結 1.預處理 預處理相當於根據預處理指令組裝新的c c 程式。經過預處理,會產生乙個沒有巨集定義,沒有條件編譯指令,沒有特殊符號的輸出檔案,這個檔案的含義同原本的檔案無異,只是內容上有所不同。1.讀取c c 源程式,對其中的偽指令 以 開頭的指令 進行處...