Linux核心原始碼分析 記憶體管理(一 分頁機制)

2021-08-02 08:54:09 字數 2321 閱讀 3232

linux系統中分為幾大模組:程序排程、記憶體管理、程序通訊、檔案系統、網路模組;各個模組之間都有一定的聯絡,就像蜘蛛網一樣,所以這也是為什麼linux核心那麼難理解,因為不知道從**開始著手去學習。很多人會跟著系統上電啟動 bios-->bootsect-->setup-->head-->main-->.....來學習,但是最後會發現當你在看main的時候你必須知道其他模組大概工作情況,要不然根本不知道為什麼要這麼做(也許其中的c**和彙編你都能看懂,但真正含義其不知道)。注意下:下面的blog中涉及到的作業系統都是選擇0.11版的linux系統;

所幸的是我最開始入手選擇了記憶體管理,而記憶體管理和其他模組聯絡就相對小一些(沒看完其他模組,但感覺和其他模組聯絡不是很大),只有頁面中斷和程序那兩個模組有些關係。好了,現在開始介紹下記憶體管理模組了(其實也是梳理下我的知識點)。

最開始的地方是在head彙編中,如果看boot中那三個彙編的應該記得(那三個彙編還是比較重要的)。首先是分頁機制,在cr0的第31位(pg位)置1表示開啟分頁機制,順便也介紹下其他幾個控制暫存器:cr1保留,沒用;cr2 用來記錄頁面異常時線性位址(不懂沒關係,後面會介紹);cr3 當前cpu使用的頁目錄表的位址(有此可見系統中不僅僅只有乙個頁目錄表,但是在某一時刻有效的頁目錄表只有乙個);當然有關頁面操作的前提是cr0的第31位必須開啟,也就是必須是在分頁機制開啟的時候那幾個控制暫存器才有效。

分頁機制最最基礎的就是把記憶體空間以4kb為單位分成多個頁。

在linux系統中全部記憶體分布情況為:

在setup彙編中已經把系統核心**從0x100000移動到從0位址開始的1mb位址內,再根據main函式中設定記憶體不超過16mb,所以這裡就拿16mb記憶體為例子;整個記憶體分布情況為:核心**及系統資料使用0~1mb ------ 快取記憶體使用1~4mb ------ 虛擬記憶體4mb~***(如果有虛擬記憶體)------ 主記憶體區***~16mb;具體的設定在main函式有,可以自己檢視下。如果大於16mb記憶體那麼就會限制只使用低16mb位址記憶體,大於16mb的記憶體將會廢掉;如果想使用大於16mb,那麼就要在main函式中和head彙編中修改下(具體修改就要自己動手了)

頁目錄表:由1024個目錄項組成,每個目錄項是4個位元組組成,目錄項中內容為頁表結構的起始位址前20位(因為頁表結構是2^12,所以低12位可以忽略)和該頁表的屬性組成;

頁表:頁表和頁目錄表和相似,都是由1024個表項組成,每個表項由4個位元組組成,頁表項中存放的內容為物理頁的起始位址的前20位(因為物理頁大小為 2^12,所以低12位可以忽略)和該物理頁面的屬性組成;

物理頁面:一般是在主記憶體區中以4kb的倍數為起始位址,大小為4kb的連續記憶體位址(這裡假設沒有虛擬記憶體);

表項:

若是頁目錄項:頁框位址中的前20位表示的是頁表的物理起始位址中的前20位(這裡有幾個重點的:1、表示的是頁表的實體地址,而不是線性位址,這兩個位址關係後面再分析;2、是起始位址,因為乙個頁表是4kb大小,所以乙個頁表就有4kb個位址(乙個位元組對於乙個位址嘛),而起始位址表示偏移量為0的位址;3、前20位,因為分頁機制中頁(不管是頁目錄還是頁表或者物理頁)都是以4kb的倍數為起始位址的,也就是說頁的起始位址的低12位全部為0,2^12 = 4kb);

若是頁表項:頁框位址中的前20位表示的是物理頁的物理起始位址中的前20位;

低12位則用來表示相應的頁的一些屬性:p == 是否存在(1 存在;0不存在 == 缺頁中斷);r/w == 是否可讀可寫(預設都是可讀的,1表示頁面可寫);u/s == 是否是超級使用者(這個到現在還沒有怎麼用到,1表示超級使用者);a == 是否訪問,d == 是否修改(這兩個位一般由硬體來處理); 

下面是頁目錄表、頁表、物理頁的巨集觀關係圖:

頁目錄項號(位址的高10位)+ 頁表項號(位址的12~21共10位)+ 物理頁內偏移量(位址的低12位)共同組成的;

根據轉換圖,分步驟來解釋下轉換情況:假設線性位址為  0x00c0 f0ef (我承認這個位址是提前設計好的,但僅僅只是為了方便計算,並不影響轉換工作)

5、最後把上一步得到的物理頁的起始位址加上線性位址中最後12位的頁內偏移值,就可以準確的定位到每個位元組上了;

若有不正確之處,望大家指正,共同學習!謝謝!!!

Linux核心 fork 原始碼分析

核心版本 linux 4.4.18 原始碼位置 這裡 接著 呼叫copy process 它設定了程序描述符以及子程序所需的任何其他核心資料結構。ftrace graph init task 初始化ftrace,核心追蹤函式呼叫。rt mutex init task 初始化鎖。copy creds ...

原始碼分析 Linux 核心工具Sparse

sparse誕生於2004年,是由linux之父開發的,目的就是提供乙個靜態檢查 的工具,從而減少linux核心的隱患。起始,在sparse之前已經有了乙個不錯的 靜態檢查工具 swat 只不過這個工具不是免費軟體,使用上有一些限制。所以linus自己開發了乙個靜態檢查工具。核心 中有乙個對spar...

linux核心原始碼目錄結構分析

注 本文是學習朱老師課程整理的筆記,基於linux2.6.35.7和九鼎x210bv3s開發板進行移植。arch。arch是architecture的縮寫。arch目錄下是好多個不同架構的cpu的子目錄,譬如arm這種cpu的所有檔案都在arch arm目錄下,x86的cpu的所有檔案都在arch ...