記憶體管理機制

2021-08-31 12:49:41 字數 3490 閱讀 3041

記憶體管理是乙個作業系統必不可少 . 並且 . 非常重要的一環 .linux 的成功 . 和它優秀的記憶體管理聯絡非常密切 . 因為乙個系統的高效性慾穩定性往往決定於它的記憶體管理機制 . 我項很多人吃過 dos 下 640k 的苦吧 .

前面我們介紹了 386 保護模式 . 從今天起我們將在此基礎上 , 分析 linux 的虛擬儲存管理 , 對每個程式設計師來說 . 他們都希望有無窮大的快速的記憶體 , 然而 , 現階段是不可能的 , 況且 , 無窮大與快速本身就可能矛盾

為了解決無窮大 .linux 引入了虛擬儲存系統 , 為了解決快速 ,linux 引入了 cache , 交換機制等等 , 以使的儲存系統 , 在容量上接近硬碟 , 速度上接近 cache.( 當然 , 我認為這是儲存系統的實際目的 ).

linux 的記憶體管理採取的是分頁機制 . 它的設計目的是時分復用 .linux 可同時處理 256 個任務 ( 這應該與某個變數來定義 , 一時想不起來 ). 同時它採用了兩級飽和機制來分別核心程序與使用者程序 .

相反 , 使用者程序 , 在使用者空間的定址是通過所使用者頁目錄中的指標得到使用者的頁表 . 並通過頁表的指標直接指向相應的物理記憶體 .

linux 虛擬記憶體的實現 , 需要幾種不同的機制來實現 :

位址對映機制

記憶體的分配與**

請頁機制

交換機制

記憶體共享機制

在具體的讀原始碼之前 . 我們先根據我們以前學過的作業系統知識 . 和 c 語言等知識 . 來考慮一下 , 這幾個機制如何實現 . 現自己設計一下 . 在看別人是怎樣實現的 . 找到自己想不到 . 或者對效率空間有損的地方 . 這樣才有進步 . 我不止一次的說 . 作業系統的某一部分 , 就起實現來說 , 非常簡單 . 它的難點是如何將大量的功能整合出乙個 kernerl.

位址對映機制 , 說白了 , 就是在虛擬記憶體與物理記憶體上的乙個橋梁 . 它要做的事情可能就是通過幾個不同的表 . 把虛擬位址轉換成實體地址 , 把實體地址轉化虛擬位址 .

我們以前說過 . 因為有系統與使用者之分 , 它必須也要有不同的資料結構 . 為了解決速度等問題 . 它會有乙個硬體的緩衝區

對於它的資料結構 . 我們可以先想一下 . 如虛擬位址的資訊 , 虛擬位址在那個區域等等

至於請頁機制 , 更好理解 . 因為 linux 是頁式儲存的 . 因此必然會存在空白頁和使用頁 . 既然是頁 . 就必然會存在頁溢位 . 頁無效 ( 是不是在 win98 下經常出現類似錯誤 , 當然 linux 的記憶體管理不可能和 windows 一樣 , 可基本道理相同 ). 因此 . 在每乙個頁出錯 . 或者該頁存不下多餘的資料時 . 就要要求核心分配新的頁面

同時 . 當時用 fork() 產生乙個新的程序時 . 也需要分配新的葉面 . 這一部分大概講的就是程序如何向內和描述自己需要怎麼樣的和多少頁

在我們學習 << 資料結構 >> 是我們學了 , 很多記憶體分配方式 , 如首次擬和 . 最佳擬和 , 最差擬和等等 . 但是我們可以想象 .linux 大概不會用他們 . 那就一定是夥伴系統了 . 因此我們可以對於夥伴系統的分配 , **的基本演算法 . 回想一下 . 這樣在讀者一部分原始碼時 , 回有意象不到的收穫 .

至於交換機制 . 我們也可以現想一想 . 記憶體中總與很多使用者的頁 . 如果這些也已經把所有的頁都用完了 . 再分配時必須把其中的某些頁釋放 . 釋放那些頁 , 需要考慮 . 如最近不用頁 . 近期少用頁 , 等等都可以在考慮之中 .

這個演算法 , 大概就是計算記憶體中使用的頁 , 什麼時候可以換處 . 說白了就是為所有的使用頁計算乙個 」 權 」, 而這個 」 權 」 就決定了他什麼時候被釋放以換如它的內容 . 需要想的是對於經常使用的頁 . 可以把它放入 cahe.( 儘管這一部分對程式設計師是透明的 , 但我們應該理解他的原理 ).

最後的一部分共享記憶體 , 我想和我門初學 linux 程式設計時 , 程序通訊裡面的共享記憶體沒有區別 . 大概也就是在它的資料結構中加入可以允許不同程序訪問的 tag 就行了 .

以上 , 只是我們對 linux 的記憶體管理機制的猜測 , 需要我們做的工作就是具體的讀原始碼 . 更正不正確的猜想 . 同時學習別人的實際思路 .

從下篇日記開始 . 我們將分別講解這幾部分的實現

位址的對映機制

位址的對映機制

, 主要完成主存 . 輔存 . 和虛存之間的關聯 . 包括磁碟檔案到虛存的對映和虛存與記憶體的對映關係 . 為了虛擬儲存和程序排程相一致 .linux 採用可一系列的資料結構 , 和乙個硬體快取 (tlb) 來實現位址對映機制 .

mm_strut 用來描述程序的快取 .

struct mm_struct

; 他描述了乙個程序的頁目錄 , 有關程序的上下文資訊 . 以及資料 . ** . 堆疊的啟示結束位址 . 還有虛擬儲存取得數目 . 以及排程儲存用的鍊錶指標 . 他的參差比較高

較高層次的 vm_area-struct 是描述程序的虛擬位址區域 . 他形成乙個算相鍊錶 . 按虛位址下降排列 . 這樣當核心需要在乙個給定程序頁上執行給定操作時 . 客從雙向列表中找到該項 . 在世想有關頁的處理 . 如 . 頁錯誤 . 頁換出等等

他的具體結構如下 :

struct vm_area_struct ;

而 page 結構 則是對物理頁進行描述的乙個資料結構 , 他不是乙個真正的物理頁 . 而只不過是描述了乙個物理頁的內容和框架 . 作了邏輯頁的乙個標誌 ;. 他的標誌域定義了這個頁在進行的操作 . 鏈域則定義了乙個雙項鍊表 . 時的頁框 . 可以很容易的查詢到 . 為實際物理記憶體的使用直到方便

他的具體結構如下

typedef struct page mem_map_t;

所有的 page 結構將都被轉入乙個叫做 mem_map 的陣列中 .

當乙個程序執行時 , 他的**段和資料段將都會被調入記憶體 . 如果它使用了共享庫 . 共享客的內容也將貝雕如記憶體 . 程序執行時 . 系統首先分配乙個 vm_area_struct 給程序 . 並將這各程序鏈結到虛擬記憶體的連標中去 . 這是根據程序的可執行影像中的資訊 . 吧資料段和客運行**非配記憶體 . 新分配的記憶體必須和程序已有的記憶體鏈結起來才能應用 . 這樣聚會出現頁故障 . 系統利用了請頁機制來避免對物理記憶體的過分使用 . 但程序訪問的虛存不在當前的物理記憶體時 , 這時系統會將需要的頁調入記憶體 . 同時修改程序的頁表 . 用來標誌虛擬頁是否在物理記憶體中 .

因此 , 系統用了較複雜的資料結構來跟蹤程序的虛擬位址 . 在 task_struct 中包含乙個指向 mm_struct 結構的指標 . 程序的 mm_struct 中則包含了程序可執行影像的頁目錄指標 pgd. 還包含了指向 vm_area_struct 的幾個指標 , 每個 vm_area_struct 包含乙個程序的虛擬位址區域 .

乙個程序有多個 vm_area_stuct 結構 .linux 要經常對程序分配 .. 或調整 vm_area_struct . 這樣對 vm_area_stuct 的查詢效率 . 對系統很有影像 . 所以在這裡將所有的 vm_area_struct 形成了乙個查詢效率較高的平衡二叉樹結構 .

我個人認為 , 在整個 linux 核心中這個地方 . 資料結構是最複雜的 . 如果把這一部分肯下來以後 , 整個核心便開始清晰了

記憶體管理機制

記憶體管理 jvm將記憶體分成三大主要區域 堆,棧,方法區,用來儲存資料。堆 堆中主要儲存引用型別物件,給成員變數分配空間。棧 jvm在執行程式時,在棧中會為每乙個方法都提供儲存空間叫棧幀,用來儲存方法中的區域性變數。方法區 用來儲存jvm載入的位元組碼檔案的資訊 類的資訊 包含類的方法,方法只有乙...

iOS 記憶體管理機制

學習要點 1.reference counting 引用計數機制 2.了解mrc apc和gc 3.autoreleasepool 執行機制 4.如何避免 retain cycle reference counting 引用計數機制 cocoa 上基本的記憶體管理機制就是引用計數,通過乙個 refe...

Android 記憶體管理機制

無意中在miui看到的文章,感覺不錯,轉了過來。原文如下 這種設計本來就是乙個非常好的設計,下次啟動程式時,會更快,因為不需要讀取介面資源。android系統這樣的設計不僅非常適合移動終端的需要,而且減少了系統崩潰的可能,確保了系統的穩定性。老想著清理記憶體的同學完全是因為被塞班或者windows毒...