0.11核提供的記憶體管理函式大部分在memery.c中,我將其中的函式從功能上分為三類:記憶體的分配與釋放、頁異常處理和記憶體初始化。第一類主 要包括單個物理頁的操作和頁表的操作,單個物理頁的操作就是乙個物理頁的申請、對映和釋放;頁表操作主要是多個頁表的釋放、複製。第二類主要是處理缺頁異 常和寫保護異常的中斷處理函式。第三類就是乙個函式負責記憶體的初始化工作。
一、記憶體的分配與釋放
1、get_free_page():在主記憶體區中申請一空閒物理頁。
首先掃瞄mem_map,從末端向前尋找值為0的元素,找到後將它的值置成1,並根據這個元素的在mem_map中的索引值得到物理頁的位址,再將物理頁中的4k位元組清零,最後返回實體地址。
先判斷傳入的線性位址是否有效,即是否在4mb邊界上,然後就算出它所佔的頁目錄項的個數和第乙個目錄項的位址,接著從第乙個目錄項開始,對於可用的目錄 項(也就是p=1:存在對應的頁表)就根據目錄項得到頁表的位址,從而釋放頁表中的所有記錄著的物理頁(free_page)並將此頁表項清零,之後釋放 掉這個頁表本身所佔的物理頁並將它對應的頁目錄項清零。直到處理完最後乙個頁目錄項。最後重新整理tlb。
這個函式是fork乙個程序時候用到的,它讓子程序共享父程序的物理記憶體。在驗證了位址的邊界性之後,換算出頁目錄項表中的源目錄項起始位址和目標目錄項 的起始位址以及要複製的頁目錄項的個數。然後開始複製工作:首先申請一頁記憶體存放新頁表,然後設定對應的頁目錄項,再迴圈複製源頁表中各頁表項到新頁表中 (對於核心程序只複製前160項就行,因為核心模組不超過640k),並將各個頁表項設為唯讀,最後根據各個頁的實體地址在mem_map中將此頁對 應的元素的值加1(表示引用次數加1)。然後迴圈這樣的複製工作直到複製完所有的頁表。
也就是根據線性位址找到對應的頁表項,將這個頁表項中的值設為這個物理頁的實體地址。這個函式一般在get_free_page()後使用。在驗證了位址 有效性之後,先根據線性位址的高10位換算出頁目錄項的位址,在從頁目錄項中得到頁表位址,再根據線性位址的中間10位得到頁表項位址。最後將在這個頁表 項中設定它所對映的物理頁位址和一些頁資訊。
6、get_empty_page():get_free_page()和put_page()的結合。
二、頁異常處理相關函式
1、up_wp_page():取消指定頁表項對應的物理頁的寫保護。
這個函式是處理頁寫保護的情況。它首先檢查這個頁是否只被乙個程序使用(mem_map中對應的元素是1),如果是直接將它改為可寫,如果它被多個進 程使用,則申請乙個頁面,然後改寫頁表項:更新新物理頁的位址、設為可讀寫,接著將原物理頁的引用次數減1,最後複製原物理頁的內容到新物理頁中後重新整理 tlb。
2、do_wp_page():中斷處理函式:處理寫保護異常
根據線性位址得到頁表項位址,並把它作為引數呼叫up_wp_page()。
3、write_verify():檢查頁面是否可寫,如果不可寫複製頁面。
根據給定的線性位址得到頁表項,根據頁表項判斷對應的物理頁是否可寫,如果不可寫,則呼叫un_wp_page(),完成新頁面的複製。
當乙個程序與另乙個程序對應同乙個可執行程式的時候,可以讓乙個程序共享另乙個程序的物理記憶體。首先根據邏輯位址分別得到當前程序和目標程序的頁目錄項, 然後根據目標程序的頁目錄項中得到頁表從而得到頁表項,然後判斷這個頁表項對應的物理頁是否被修改過,如果沒被修改過,則表示可以被共享。接著得到當前進 程的要操作的頁表項,並將此頁表的內容設為剛才得到的目的程序頁表項的內容,最後將這兩個頁表項都設為唯讀。
5、share_page():共享頁面
找到與當前程序對應同乙個可執行程式的程序,然後呼叫try_to_share()進行頁面的共享。尋找這個程序的方法是先得到當前程序的對應的可執行程式的i節點,然後掃瞄整個task陣列,找到與當前程序i節點相同的程序。
6、do_no_page():中斷處理函式:缺頁處理
缺頁有兩種情況,一種是動態申請記憶體導致的缺頁,一種訪問程序**或者資料時候缺頁。先根據線性位址和當前程序的起始位址得到邏輯位址,判斷這個邏輯位址 是否在**段和資料段範圍之外,如果在這個範圍之外說明是在堆段中,則表示這是動態申請記憶體引起的缺頁,這個時候,用get_empty_page()就 可以解決問題了。如果在這個範圍之內,說明是反問程式的**或者資料引起的缺頁,整個時候,需要從磁碟的可執行程式中複製相應頁面到記憶體中:先申請一塊物 理記憶體頁,接著根據邏輯位址得到可執行檔案中對應的邏輯塊(每塊大小1kb)號,然後將連續的四個邏輯塊複製到新申請的物理頁中,在處理完一些無用資訊 (有可能讀入的4個邏輯塊中實際的有用資訊不足4kb)之後,完成物理頁到線性位址的對映。
三、記憶體的初始化:mem_init()
這個函式在main初始化的時候被呼叫的,前面已經說過linux對記憶體的管理主要是通過mem_map完成的,記憶體的初時話,主要就是對 mem_map進行初始化:就是將1m以上的記憶體空間中的主記憶體部分在mem_map對應的元素置為0,其它部分置位占用狀態。
附:0.11核記憶體管理中還有乙個檔案,page.s,這個檔案主要是頁異常引起中斷的中斷處理函式,具體的就是根據異常型別呼叫不同的處理函式:do_no_page()、do_wp_page()。
至此,linux0.11核的記憶體管理的學習,我打算告一段落,下面我計畫學習linxu的設配管理,主要是設配驅動。
Linux下記憶體管理函式
include void sbrk intptr t increment increment 0 獲取未分配前的記憶體首位址 也就是已經分配記憶體的尾位址 大於0 增加記憶體空間 小於0 釋放記憶體空間 返回值 未分配前的記憶體首位址,以位元組為單位。int brk void addr 它們背後維護...
記憶體管理詳解
來談談記憶體管理 首先知道記憶體管理是什麼 應用程式記憶體管理是在程式執行的時候合理的分配記憶體 分配記憶體時不會造成記憶體洩露等 與清除記憶體 銷毀乙個不用的程式,減少記憶體使用 在oc中有兩個管理記憶體的模式 mrr manual retain release 也被人稱作mrc manual r...
Linux程式設計C 記憶體管理之記憶體分配詳解
程式設計師們經常編寫記憶體管理程式,往往提心吊膽。如果不想觸雷,唯一的解決辦法就是發現所有潛伏的地雷並且排除它們,躲是躲不了的。本文的內容比一般教科書的要深入得多,讀者需細心閱讀,做到真正地通曉記憶體管理。記憶體分配方式 記憶體分配方式有三種 1 從靜態儲存區域分配。內存在程式編譯的時候就已經分配好...