Linux內核高端記憶體

来源:https://www.cnblogs.com/linhaostudy/archive/2019/03/03/10467992.html
-Advertisement-
Play Games

Linux內核地址映射模型 x86 CPU採用了段頁式地址映射模型。進程代碼中的地址為邏輯地址,經過段頁式地址映射後,才真正訪問物理記憶體。 段頁式機制如下圖。 Linux內核地址空間劃分 通常32位Linux內核地址空間劃分0~3G為用戶空間,3~4G為內核空間。註意這裡是32位內核地址空間劃分,6 ...


Linux內核地址映射模型

x86 CPU採用了段頁式地址映射模型。進程代碼中的地址為邏輯地址,經過段頁式地址映射後,才真正訪問物理記憶體。

段頁式機制如下圖。

image

Linux內核地址空間劃分

通常32位Linux內核地址空間劃分0~3G為用戶空間,3~4G為內核空間。註意這裡是32位內核地址空間劃分,64位內核地址空間劃分是不同的。

image

Linux內核高端記憶體的由來

當內核模塊代碼或線程訪問記憶體時,代碼中的記憶體地址都為邏輯地址,而對應到真正的物理記憶體地址,需要地址一對一的映射,如邏輯地址0xc0000003對應的物理地址為0x3,0xc0000004對應的物理地址為0x4,… …,邏輯地址與物理地址對應的關係為

物理地址 = 邏輯地址 – 0xC0000000

邏輯地址 物理記憶體地址
0xc0000000 0x0
0xc0000001 0x1
0xc0000002 0x2
0xc0000003 0x3
0xe0000000 0x20000000
0xffffffff 0x40000000 ??

假設按照上述簡單的地址映射關係,那麼內核邏輯地址空間訪問為0xc0000000 ~ 0xffffffff,那麼對應的物理記憶體範圍就為0x0 ~ 0x40000000,即只能訪問1G物理記憶體。若機器中安裝8G物理記憶體,那麼內核就只能訪問前1G物理記憶體,後面7G物理記憶體將會無法訪問,因為內核的地址空間已經全部映射到物理記憶體地址範圍0x0 ~ 0x40000000。即使安裝了8G物理記憶體,那麼物理地址為0x40000001的記憶體,內核該怎麼去訪問呢?代碼中必須要有記憶體邏輯地址的,0xc0000000 ~ 0xffffffff的地址空間已經被用完了,所以無法訪問物理地址0x40000000以後的記憶體。

顯然不能將內核地址空間0xc0000000 ~ 0xfffffff全部用來簡單的地址映射。因此x86架構中將內核地址空間劃分三部分:ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。ZONE_HIGHMEM即為高端記憶體,這就是記憶體高端記憶體概念的由來。

在x86結構中,三種類型的區域如下:

ZONE_DMA 記憶體開始的16MB

ZONE_NORMAL 16MB~896MB

ZONE_HIGHMEM 896MB ~ 結束

image

Linux內核高端記憶體的理解

前面我們解釋了高端記憶體的由來。 Linux將內核地址空間劃分為三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,高端記憶體HIGH_MEM地址空間範圍為0xF8000000 ~ 0xFFFFFFFF(896MB~1024MB)。那麼如內核是如何藉助128MB高端記憶體地址空間是如何實現訪問可以所有物理記憶體?

當內核想訪問高於896MB物理地址記憶體時,從0xF8000000 ~ 0xFFFFFFFF地址空間範圍內找一段相應大小空閑的邏輯地址空間,借用一會。借用這段邏輯地址空間,建立映射到想訪問的那段物理記憶體(即填充內核PTE頁面表),臨時用一會,用完後歸還。這樣別人也可以借用這段地址空間訪問其他物理記憶體,實現了使用有限的地址空間,訪問所有所有物理記憶體。如下圖。

image

例如內核想訪問2G開始的一段大小為1MB的物理記憶體,即物理地址範圍為0x80000000 ~ 0x800FFFFF。訪問之前先找到一段1MB大小的空閑地址空間,假設找到的空閑地址空間為0xF8700000 ~ 0xF87FFFFF,用這1MB的邏輯地址空間映射到物理地址空間0x80000000 ~ 0x800FFFFF的記憶體。映射關係如下:

邏輯地址 物理記憶體地址
0xF8700000 0x80000000
0xF8700001 0x80000001
0xF8700002 0x80000002
0xF87FFFFF 0x800FFFFF

Linux內核高端記憶體的劃分

內核將高端記憶體劃分為3部分:VMALLOC_START~VMALLOC_END、KMAP_BASE~FIXADDR_START和FIXADDR_START~4G。

image

對於高端記憶體,可以通過 alloc_page() 或者其它函數獲得對應的 page,但是要想訪問實際物理記憶體,還得把 page 轉為線性地址才行(為什麼?想想 MMU 是如何訪問物理記憶體的),也就是說,我們需要為高端記憶體對應的 page 找一個線性空間,這個過程稱為高端記憶體映射。

對應高端記憶體的3部分,高端記憶體映射有三種方式:

映射到”內核動態映射空間”(noncontiguous memory allocation)

這種方式很簡單,因為通過 vmalloc() ,在”內核動態映射空間”申請記憶體的時候,就可能從高端記憶體獲得頁面(參看 vmalloc 的實現),因此說高端記憶體有可能映射到”內核動態映射空間”中。

持久內核映射(permanent kernel mapping)

如果是通過 alloc_page() 獲得了高端記憶體對應的 page,如何給它找個線性空間?
內核專門為此留出一塊線性空間,從 PKMAP_BASE 到 FIXADDR_START ,用於映射高端記憶體。在 2.6內核上,這個地址範圍是 4G-8M 到 4G-4M 之間。這個空間起叫”內核永久映射空間”或者”永久內核映射空間”。這個空間和其它空間使用同樣的頁目錄表,對於內核來說,就是 swapper_pg_dir,對普通進程來說,通過 CR3 寄存器指向。通常情況下,這個空間是 4M 大小,因此僅僅需要一個頁表即可,內核通過來 pkmap_page_table 尋找這個頁表。通過 kmap(),可以把一個 page 映射到這個空間來。由於這個空間是 4M 大小,最多能同時映射 1024 個 page。因此,對於不使用的的 page,及應該時從這個空間釋放掉(也就是解除映射關係),通過 kunmap() ,可以把一個 page 對應的線性地址從這個空間釋放出來。

臨時映射(temporary kernel mapping)

內核在 FIXADDR_START 到 FIXADDR_TOP 之間保留了一些線性空間用於特殊需求。這個空間稱為”固定映射空間”在這個空間中,有一部分用於高端記憶體的臨時映射。

這塊空間具有如下特點:

(1)每個 CPU 占用一塊空間

(2)在每個 CPU 占用的那塊空間中,又分為多個小空間,每個小空間大小是 1 個 page,每個小空間用於一個目的,這些目的定義在 kmap_types.h 中的 km_type 中。

當要進行一次臨時映射的時候,需要指定映射的目的,根據映射目的,可以找到對應的小空間,然後把這個空間的地址作為映射地址。這意味著一次臨時映射會導致以前的映射被覆蓋。通過 kmap_atomic() 可實現臨時映射。

常見問題:

1、用戶空間(進程)是否有高端記憶體概念?

用戶進程沒有高端記憶體概念。只有在內核空間才存在高端記憶體。用戶進程最多只可以訪問3G物理記憶體,而內核進程可以訪問所有物理記憶體。

2、64位內核中有高端記憶體嗎?

目前現實中,64位Linux內核不存在高端記憶體,因為64位內核可以支持超過512GB記憶體。若機器安裝的物理記憶體超過內核地址空間範圍,就會存在高端記憶體。

3、用戶進程能訪問多少物理記憶體?內核代碼能訪問多少物理記憶體?

32位系統用戶進程最大可以訪問3GB,內核代碼可以訪問所有物理記憶體。

64位系統用戶進程最大可以訪問超過512GB,內核代碼可以訪問所有物理記憶體。

4、高端記憶體和物理地址、邏輯地址、線性地址的關係?

高端記憶體只和物理地址有關係,和線性地址、邏輯地址沒有直接關係。

5、為什麼不把所有的地址空間都分配給內核?

若把所有地址空間都給記憶體,那麼用戶進程怎麼使用記憶體?怎麼保證內核使用記憶體和用戶進程不起衝突?


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 沒有 docker 部署的程式是不完整的,在寫了 IIS/Centos/Supervisor 3篇托管介紹文章後,終於來到了容器化部署 ...
  • 這篇文章,我將帶領大家學習HTML Helper。【PS:上一篇-->5.ASP.NET MVC 中的Area【區域】是什麼】 HTML Helpers是用來創建HTML標簽進而創建HTML控制項的。HTML Helper僅僅是一個返回HTML字元串的方法。ASP.NET MVC 中有三種HTML H ...
  • 微軟拋棄了System.Data.OracleClient,在VS2012中使用 System.Data.OracleClient連接ORACLE資料庫就會出現異常,本文介紹了在VS2012中直接引用Oracle.ManagedDataAccess.dll庫文件連接訪問ORACLE資料庫。 ...
  • 大家好,這篇文章,我將向大家介紹ASP.NET MVC的模型視圖綁定,ASP.MVC的模型綁定分為兩種:一種是動態綁定【Dynamic Binding】;還有一種就是強類型綁定【Strongly typed binding】;【PS--上一篇文章:3.怎樣將ASP.NET MVC應用程式發佈到IIS ...
  • 大家好,上一篇對ASP.NET MVC 有了一個基本的認識之後,這一篇,我們來看下怎麼從頭到尾創建一個ASP.NET MVC 應用程式吧。【PS:返回上一篇文章:1.開始學習ASP.NET MVC】 第一步:開打VS2017,選擇【文件】-->【新建】-->【項目】,然後在彈出來的方框中,按照下麵的 ...
  • 調試機:win10 1809 虛擬機: win7 windbg屬性設置,在目標後面加上紫色字體參數: "D:\Program Files\Debugging Tools for Windows (x64)\windbg.exe" -b -k com:port=\\.\pipe\com_1,baud= ...
  • 我們常常為了一些軟體啟動的方便,將一些軟體的文件夾指定到系統的環境變數中,這樣就不需要到指定軟體的bin目錄,運行目錄下啟動(類似於JAVA,Python,Node等命令),直接Win+R、或者cmd直接就可以啟動,但是隨著一個個目錄的添加導致系統的環境變數超出了1024B,這時系統就會發出警告。 ...
  • 早在 20 世紀 70 年代,UNIX 系統是開源而且免費的。但是在 1979 年時,AT&T 公司宣 布了對 UNIX 系統的商業化計劃,隨之開源軟體業轉變成了版權式軟體產業,源代碼被當作 商業機密,成為專利產品,人們再也不能自由地享受科技成果。 於是在 1984 年,Richard Stallm ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...