天天看點

可執行程式加載到記憶體的過程

在linux中,程式的加載,涉及到兩個工具,linker 和loader。linker主要涉及動态連結庫的使用,loader主要涉及軟體的加載。

1、  exec執行一個程式

2、  elf為現在非常流行的可執行檔案的格式,它為程式運作劃分了兩個段,一個段是可以執行的代碼段,它是隻讀,可執行;另一個段是資料段,它是可讀寫,不能執行。

3、  loader會啟動,通過mmap系統調用,将代碼端和資料段映射到記憶體中,其實也就是為其配置設定了虛拟記憶體,注意這時候,還不占用實體記憶體;隻有程式執行到了相應的地方,核心才會為其配置設定實體記憶體。

4、  loader會去查找該程式依賴的連結庫,首先看該連結庫是否被映射進記憶體中,如果沒有使用mmap,将代碼段與資料段映射到記憶體中,否則隻是将其加入程序的位址空間。這樣比如glibc等庫的記憶體位址空間是完全一樣。

是以一個2m的程式,執行時,并不意味着為其配置設定了2m的實體記憶體,這與其運作了的代碼量,與其所依賴的動态連結庫有關。

運作過程中連結動态連結庫與編譯過程中連結動态庫的差別。

我們調用動态連結庫有兩種方法:一種是編譯的時候,指明所依賴的動态連結庫,這樣loader可以在程式啟動的時候,來所有的動态連結映射到記憶體中;一種是在運作過程中,通過dlopen和dlfree的方式加載動态連結庫,動态将動态連結庫加載到記憶體中。

這兩種方式,從程式設計角度來講,第一種是最友善的,效率上影響也不大,在記憶體使用上有些差别。

第一種方式,一個庫的代碼,隻要運作過一次,便會占用實體記憶體,之後即使再也不使用,也會占用實體記憶體,直到程序的終止。

第二中方式,庫代碼占用的記憶體,可以通過dlfree的方式,釋放掉,傳回給實體記憶體。

這個差别主要對于那些壽命很長,但又會偶爾調用各種庫的程序有關。如果是這類程序,建議采用第二種方式調用動态連結庫。

mmap()和vma相關和底層的驅動相關

如果使用者的空間映射到虛拟記憶體大塊的映射 用mmap

驅動需要做一個簡單的線性的裝置記憶體映射, 到一個使用者位址空間, remap_pfn_range 幾乎是所有你做這個工作真正需要做的. 下列的代碼從 drivers/char/mem.c 中得來, 并且顯示了這個任務如何在一個稱為 simple ( simple implementation mapping pages with little enthusiasm)的典型子產品中進行的.

如你所見, 重新映射記憶體隻不過是調用 remap_pfn_rage 來建立必要的頁表.

------------------越是喧嚣的世界,越需要甯靜的思考------------------

合抱之木,生于毫末;九層之台,起于壘土;千裡之行,始于足下。

積土成山,風雨興焉;積水成淵,蛟龍生焉;積善成德,而神明自得,聖心備焉。故不積跬步,無以至千裡;不積小流,無以成江海。骐骥一躍,不能十步;驽馬十駕,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓無爪牙之利,筋骨之強,上食埃土,下飲黃泉,用心一也。蟹六跪而二螯,非蛇鳝之穴無可寄托者,用心躁也。

繼續閱讀