012核心的記憶體管理

2021-03-03 22:43:08 字數 2248 閱讀 4560

記憶體的。10月的最後一天,核心也應該告一段落了,接下來的是**。接下來要對這次的核心**檢視進行總結。

這次檢視**是從10月20日開始的。直接跳過了boot和setup。從main函式開始。

這次檢視的主線是0.12linux核心的記憶體管理,也就是核心是如何使用記憶體的。以下的順序就是按照記憶體的使用順序總結的。

一, 記憶體初始化。

在談到記憶體初始化的時候,就不得不先考慮0.12核心是如何使用記憶體的。0.

12最大可使用16mb的記憶體。其中分為四個部分,1)核心**,2)高速緩衝區,3)視訊記憶體,4)主儲存區。當記憶體大於12mb的時候,那麼記憶體從4mb開始就是主儲存區。

這裡的主儲存區就是用來分配給程序的記憶體。

在核心中定義了乙個字元陣列unsigned char mem_map [ paging_pages ]。

其中每個大於4mb的記憶體頁都會在mem_map有一項。當對應項為0時,表示記憶體是空閒的。在初始化的時候,每一項都被初始化為0.

二, iret命令,task0開始執行。

move_to_user_mode這是乙個巨集定義。使用彙編**實現的。這個**中有乙個iret。

在這個iret執行後。cpu的特權級從ring0跳轉到ring3.各暫存器的值被修改為tss中的值。

宣告了task0執行開始。task0做的第一件事情,就是呼叫fork系統呼叫。用來建立task1.

task1和task0的**包括堆疊實質上是一樣的。所以對於記憶體的影響不大。

三, task1中的init函式

在task1中呼叫了init函式。這個函式比較重要。初始化了硬碟等。

但我們現在把精力放在記憶體上,所以這些先略過。init函式也建立了乙個程序。這個程序執行了乙個shell程式。

建立過程同樣也是fork。但是新建立出的程序執行了乙個execve系統呼叫。這個系統呼叫使得這個新建立出的程序與task完全不同。

接下來我們看看如何不同。

execve把新建立的程序所有的頁表都清空。並且修改程序的存放的eip,修改eip指向要執行程式的程式入口。這個程式入口時程式在編譯的時候指定好的。

然後這個時候給新程序的線性位址的最後乙個頁分配記憶體。用來存放給這個程序傳進去的引數,如果這些引數大於4kb那麼會繼續為新程序分配記憶體頁。當然也是從後面開始分配。

引數一共有3個,argc,argv,和engv。這3個引數也就是我們寫main函式最常見到的那3個引數(哈哈,是由execve這個系統呼叫傳入進去的)。寫好引數後execve就返回了。

等新程序再次獲得cpu的時候,就會執行新的**了。在這裡是乙個bash程式。

execve執行之後。新程序的記憶體是什麼樣子呢??這個很重要。

在0.12linux中乙個程序的線性位址是0-64mb.現在新程序除了線性位址最後的幾個頁面由於要存放argc,argv,和engv。

已經分配了物理記憶體。其他的線性位址都沒有被指定物理頁面。如果此時新程序從eip開始執行會發生什麼??

不錯,這個時候會發生缺頁中斷。因為這個時候線性位址並沒有對應到物理記憶體。bash的可執行**也沒有調入記憶體。

那麼缺頁中斷所要做的。就是把bash的可執行**讀入到記憶體。並且把有可執行程式**的記憶體。

與發生缺頁中斷的頁面進行對應。這樣我們的bash程式就會開始執行啦。

四, 記憶體不足時?來swap_out

當系統中的主記憶體已經全部用光的時候。就會呼叫swap_out函式。把記憶體頁放到硬碟中。

swap交換分割槽的原理是這樣的,在編譯核心的時候,會指定swap的裝置號。或者是一塊軟盤。或者是硬碟的乙個分割槽。

當核心啟動後會初始化swap_bitmap這麼乙個結構。這是乙個指標。初始化後。

指向乙個空的記憶體頁面。並把所有位清零。以後每一位都就對應乙個外存上面的頁面。

當全為1的時候。說明交換分割槽已經滿了。當記憶體已經滿了,需要選擇乙個頁面被交換出去的時候。

注意如果這個頁面是被修改過的。那麼需要被交換到外存中。否則直接置這個記憶體頁為空閒。

因為沒有發生修改的頁面時沒有被swap的必要的。反正都是從外存中取。

五, 記憶體中的高速緩衝區。

當發生缺頁中斷和使用交換分割槽的時候。我們涉及到了外存。但它們倆個實現的方法是不一樣的。缺頁中斷時通過高速緩衝區過度了以下。而交換分割槽直接就是外存和主記憶體進行的。

那麼高速緩衝區又是什麼???

整個0.12系統在與外存打交道的時候。除了交換分割槽swap沒有使用高速緩衝區。

其他的時候都使用了高速緩衝區。例如缺頁中斷,讀取檔案。高速緩衝區分為資料頭,和資料區。

乙個資料頭對應乙個資料區。核心通過資料頭的狀態來判斷這個資料區是否可用。

linux記憶體管理精華

核心初始化 核心建立好核心頁目錄頁表資料庫,假設物理記憶體大小為 則建立了這樣的虛位址和實體地址的線性對應關係 核心建立乙個陣列,陣列和物理頁面系列完全是線性對應,用來管理該物理頁面狀態,每個物理頁面的虛位址儲存在中 核心建立好乙個將沒有使用的物理頁面對應的放入其中,已經使用的就不用放入了 核心模組...

安卓的記憶體管理機制

1.系統會對程序的重要性進行評估,並將重要性以 oom adj 這個數值表示出來,賦予各個程序 系統會根據 oom adj 來判斷需要結束哪些程序,一般來說,oom adj 的值越大,該程序被系統選中終止的可能就越高 2.前台程式的 oom adj 值為0,這意味著它不會被系統終止,一旦它不可訪問後...

Linux系統的記憶體管理技巧總結

1mem map paging pages 陣列為什麼不直接從主儲存區開始記錄,而從1m開始記錄,然後又把1m到主儲存區之間的內容置為100 3哪些地方需要執行重新整理頁變換緩衝 invalidate 函式實現 3.1free page tables 3.2copy page tables 3.3u...