[rCore學習筆記 027]地址空間

来源:https://www.cnblogs.com/chenhan-winddevil/p/18417761
-Advertisement-
Play Games

寫在前面 本隨筆是非常菜的菜雞寫的。如有問題請及時提出。 可以聯繫:[email protected] GitHhub:https://github.com/WindDevil (目前啥也沒有 引言 兜兜轉轉又是新的一章的開始,還是首先要看官方手冊里的理論介紹和內容. 這裡主要還是提綱挈領地摘抄裡面 ...


寫在前面

本隨筆是非常菜的菜雞寫的。如有問題請及時提出。

可以聯繫:[email protected]

GitHhub:https://github.com/WindDevil (目前啥也沒有

引言

兜兜轉轉又是新的一章的開始,還是首先要看官方手冊里的理論介紹和內容.

這裡主要還是提綱挈領地摘抄裡面的部分內容,在下麵用更小的標題表現.

本章目的

本章展現了操作系統為實現“理想”而要擴展的一系列功能:

  • 通過動態記憶體分配,提高了應用程式對記憶體的動態使用效率
  • 通過頁表的虛實記憶體映射機制,簡化了編譯器對應用的地址空間設置
  • 通過頁表的虛實記憶體映射機制,加強了應用之間,應用與內核之間的記憶體隔離,增強了系統安全
  • 通過頁表的虛實記憶體映射機制,可以實現空分復用 (提出,但沒有實現)

需求

在大多數應用(也就是應用開發者)的視角中,它們會獨占一整個 CPU 和特定(連續或不連續)的記憶體空間。當然,通過上一章的學習,我們知道在現代操作系統中,出於公平性的考慮,我們極少會讓獨占 CPU 這種情況發生。所以應用自認為的獨占 CPU 只是內核想讓應用看到的一種 幻象 (Illusion) ,而 CPU 計算資源被 時分復用 (TDM, Time-Division Multiplexing) 的實質被內核通過恰當的抽象隱藏了起來,對應用不可見。

與之相對,我們目前還沒有對記憶體管理功能進行進一步拓展,僅僅是把程式放到某處的物理記憶體中。在記憶體訪問方面,所有的應用都直接通過物理地址訪問物理記憶體,這使得應用開發者需要瞭解繁瑣的物理地址空間佈局,訪問記憶體也很不方便。在上一章中,出於任務切換的需要,所有的應用都在初始化階段被載入到記憶體中並同時駐留下去直到它們全部運行結束。而且,所有的應用都直接通過物理地址訪問物理記憶體。

這會帶來以下問題:

  • 首先,內核提供給應用的記憶體訪問介面不夠透明,也不好用。由於應用直接訪問物理記憶體,這需要它在構建的時候就清楚所運行電腦的物理記憶體空間佈局,還需規劃自己需要被載入到哪個地址運行。為了避免衝突可能還需要應用的開發者們對此進行協商,這顯然是一件在今天看來不夠通用且極端麻煩的事情。
  • 其次,內核並沒有對應用的訪存行為進行任何保護措施,每個應用都有電腦系統中整個物理記憶體的讀寫權力。即使應用被限制在 U 特權級下運行,它還是能夠造成很多麻煩:比如它可以讀寫其他應用的數據來竊取信息或者破壞其它應用的正常運行;甚至它還可以修改內核的代碼段來替換掉原本的 trap_handler 函數,來挾持內核執行惡意代碼。總之,這造成系統既不安全、也不穩定。
  • 再次,目前應用的記憶體使用空間在其運行前已經限定死了,內核不能靈活地給應用程式提供的運行時動態可用記憶體空間。比如一個應用結束後,這個應用所占的空間就被釋放了,但這塊空間無法動態地給其它還在運行的應用使用。

解決方案

為了簡化應用開發,防止應用胡作非為,本章將更好地管理物理記憶體,並提供給應用一個抽象出來的更加透明易用、也更加安全的訪存介面,這就是基於分頁機制的虛擬記憶體。站在應用程式運行的角度看,就是存在一個從“0”地址開始的非常大的可讀/可寫/可執行的地址空間(Address Space),而站在操作系統的角度看,每個應用被局限在分配給它的物理記憶體空間中運行,無法讀寫其它應用和操作系統所在的記憶體空間。

硬體支持

實現地址空間的第一步就是實現分頁機制,建立好虛擬記憶體和物理記憶體的頁映射關係。此過程需要硬體支持,硬體細節與具體CPU相關,涉及地址映射機制等,相對比較複雜。

需要思考的問題

總體而言,我們需要思考如下問題:

  • 硬體中物理記憶體的範圍是什麼?
  • 哪些物理記憶體空間需要建立頁映射關係?
  • 如何建立頁表使能分頁機制?
  • 如何確保 OS 能夠在分頁機制使能前後的不同時間段中都能正常定址和執行代碼?
  • 頁目錄表(一級)的起始地址設置在哪裡?
  • 二級/三級等頁表的起始地址設置在哪裡,需要多大空間?
  • 如何設置頁目錄表項/頁表項的內容?
  • 如果要讓每個任務有自己的地址空間,那每個任務是否要有自己的頁表?
  • 代表應用程式的任務和操作系統需要有各自的頁表嗎?
  • 在有了頁表之後,任務和操作系統之間應該如何傳遞數據?

體驗環節

經典切換代碼到第四章分支,然後一舉運行:

cd ~/App/rCore-Tutorial-v3
git checkout ch4
cd os
make run

這裡註意如果不能切換到ch4很有可能是因為沒丟棄或者保存分支,嘗試使用git checkout .指令.

運行結果:

[rustsbi] RustSBI version 0.3.1, adapting to RISC-V SBI v1.0.0
.______       __    __      _______.___________.  _______..______   __
|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|
[rustsbi] Implementation     : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name      : riscv-virtio,qemu
[rustsbi] Platform SMP       : 1
[rustsbi] Platform Memory    : 0x80000000..0x88000000
[rustsbi] Boot HART          : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000f02
[rustsbi] Firmware Address   : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)
[kernel] Hello, world!
.text [0x80200000, 0x8020c000)
.rodata [0x8020c000, 0x80210000)
.data [0x80210000, 0x80266000)
.bss [0x80266000, 0x80577000)
mapping .text section
mapping .rodata section
mapping .data section
mapping .bss section
mapping physical memory
mapping memory-mapped registers
[kernel] back to world!
remap_test passed!
init TASK_MANAGER
num_app = 7
power_3 [10000/300000]
power_3 [20000/300000]
power_3 [30000/300000]
power_3 [40000/300000]
power_3 [50000/300000]
power_3 [60000/300000]
power_3 [70000/300000]
power_3 [80000/300000]
power_3 [90000/300000]
power_3 [100000/300000]
power_3 [110000/300000]
power_3 [120000/300000]
power_3 [130000/300000]
power_3 [140000/300000]
power_3 [150000/300000]
power_3 [160000/300000]
power_3 [170000/300000]
power_3 [180000/300000]
power_3 [190000/300000]
power_3 [200000/300000]
power_3 [210000/300000]
power_3 [220000/300000]
power_3 [230000/300000]
power_3 [240000/300000]
power_3 [250000/300000]
power_3 [260000/300000]
power_3 [270000/300000]
power_3 [280000/300000]
power_3 [290000/300000]
power_3 [300000/300000]
3^300000 = 612461288(MOD 998244353)
Test power_3 OK!
[kernel] Application exited with code 0
power_5 [10000/210000]
power_5 [20000/210000]
power_5 [30000/210000]
power_5 [40000/210000]
power_5 [50000/210000]
power_5 [60000/210000]
power_5 [70000/210000]
power_5 [80000/210000]
power_5 [90000/210000]
power_5 [100000/210000]
power_5 [110000/210000]
power_5 [120000/210000]
power_5 [130000/210000]
power_5 [140000/210000]
power_5 [150000/210000]
power_7 [10000/240000]
power_7 [20000/240000]
power_7 [30000/240000]
power_7 [40000/240000]
power_7 [50000/240000]
power_7 [60000/240000]
power_7 [70000/240000]
power_7 [80000/240000]
power_7 [90000/240000]
power_7 [100000/240000]
power_7 [110000/240000]
power_7 [120000/240000]
power_7 [130000/240000]
power_7 [140000/240000]
power_7 [150000/240000]
power_7 [160000/240000]
power_7 [170000/240000]
power_7 [180000/240000]
power_7 [190000/240000]
power_7 [200000/240000]
power_7 [210000/240000]
power_7 [220000/240000]
power_7 [230000/240000]
power_7 [240000/240000]
7^240000 = 304164893(MOD 998244353)
Test power_7 OK!
[kernel] Application exited with code 0

load_fault APP running...

Into Test load_fault, we will insert an invalid load operation...
Kernel should kill this application!
[kernel] PageFault in application, bad addr = 0x0, bad instruction = 0x100c0, kernel killed it.

store_fault APP running...

Into Test store_fault, we will insert an invalid store operation...
Kernel should kill this application!
[kernel] PageFault in application, bad addr = 0x0, bad instruction = 0x100c0, kernel killed it.
Test sbrk start.
origin break point = 17000
one page allocated,  break point = 18000
try write to allocated page
write ok
10 page allocated,  break point = 22000
11 page DEALLOCATED,  break point = 17000
try DEALLOCATED more one page, should be failed.
Test sbrk almost OK!
now write to deallocated page, should cause page fault.
[kernel] PageFault in application, bad addr = 0x17000, bad instruction = 0x1124a, kernel killed it.
power_5 [160000/210000]
power_5 [170000/210000]
power_5 [180000/210000]
power_5 [190000/210000]
power_5 [200000/210000]
power_5 [210000/210000]
5^210000 = 527227302(MOD 998244353)
Test power_5 OK!
[kernel] Application exited with code 0
Test sleep OK!
[kernel] Application exited with code 0
All applications completed!

本章框圖

這裡需要和上一章的框圖進行對比才能知道本章做了什麼改進.

這是本章框圖:

這是上章框圖:

可以看到的不同分為兩個部分:

  1. 硬體需求不同
  2. 系統架構不同

硬體需求

觀察框圖,可以看到本章的框圖中要求:

  1. CPU with MMU 要求 CPU 含有MMU,也即記憶體管理單元(Memory Management Unit)是電腦硬體的一部分,主要負責處理記憶體管理和虛擬地址到物理地址的轉換。
  2. MEM with PageTable,要求記憶體支持頁表,Page Table 是操作系統用於管理虛擬記憶體的一種數據結構,它記錄了虛擬地址與物理地址之間的映射關係。Page Table 需要硬體支持,特別是 MMU(Memory Management Unit)來實現虛擬地址到物理地址的快速轉換。

總而言之就是需要MMU.

系統架構

本章框圖中增加了:

  1. APP層和OS層的跳板Trampline
  2. 每個APP的地址空間
  3. 內核的地址空間
  4. 物理頁幀分配

等功能.

這裡摘自官方手冊:

在具體實現上,擴展了 TaskManager 的管理範圍,每個 Task 的上下文 Task Context 還包括該任務的地址空間,在切換任務時,也要切換任務的地址空間。新增的記憶體管理模塊主要包括與內核中動態記憶體分配相關的頁幀分配、堆分配,以及表示應用地址空間的 Apps MemSets 類型和內核自身地址空間的 Kernel MemSet類型。 MemSet 類型所包含的頁表 PageTable 建立了虛實地址映射關係,而另外一個 MemArea 表示任務的合法空間範圍。

建議

代碼的閱讀順序參考官方手冊.

這裡代碼繁多,尤其是涉及到記憶體的變換之後就會面臨對前面所有的數據結構的大範圍的重寫,對trap的處理和對__switch的重構.

建議多看代碼,多理清問題,這樣才能順利度過這最難的一章.


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

-Advertisement-
Play Games
更多相關文章
  • 下載 nvm 點擊進入 nvm git 倉庫下載 nvm windows 用戶點擊 exe 文件進行下載。 下載完畢之後點擊安裝包進行安裝 檢查是否安裝成功 打開windows 控制欄輸入 nvm -v 檢查是否安裝成功 使用 nvm 下載 node.js 打開控制欄輸入 nvm install l ...
  • 大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是恩智浦i.MXRT系列MCU的ROM啟動日誌。 關於 i.MX RT 啟動問題解決的文章,痞子衡寫過非常多,其中大部分都是具體到某一類啟動設備下的具體問題分析,比較依賴經驗,這些經驗當然是非常有用的。此外也有一篇 《啟動失敗先查看SRC ...
  • 1、概述 操作系統一般都是安裝在硬碟內的,硬碟是一種存儲數據的介質,U 盤同樣也是一種存儲數據的介質,因此也可以把操作系統安裝進 U 盤裡。 因為大部分 U 盤的性能比較差,不能流暢地運行完整版的操作系統,所以只能安裝精簡了大部分功能、只保留基本運行環境的簡化版操作系統(即 PE )。 PE 是 W ...
  • 1.基礎工具安裝 ①Ubuntu虛擬機下交叉編譯工具鏈安裝 香橙派5Pro為Arm64位架構,因此需要安裝g++-aarch64-linux-gnu以及gcc-aarch64-linux-gnu(有其它交叉編譯器,本文以此編譯器為例) 更新軟體源 sudo apt update sudo apt u ...
  • -- 痞子衡維護的 NXP-MCUBootUtility 工具距離上一個大版本(v5.3.0)發佈過去一年了,期間痞子衡也做過三個版本更新,但不足以單獨介紹。這一次痞子衡為大家帶來了全新重要版本v6.3.x,這次更新主要是想和大家特別聊聊 ROM 啟動日誌這個特性的支持。 一、v6.0 - v6.3 ...
  • #老師給的文件是jdk1.8版本,所以我這邊寫的也是8的腳本 輸入命令:mkdir –p /export/data #放置相關的數據文件 輸入命令mkdir –p /export/servers #軟體的安裝目錄 輸入命令:mkdir –p /export/software 上傳文件jdk-8u24 ...
  • ladp服務搭建 用戶名:cn=admin,dc=test,dc=com 密碼:123456 1)軟體安裝yum install openldap openldap-clients openldap-servers -y2)配置 OpenLDAP Servervim /etc/openldap/sl ...
  • liwen01 2024.09.16 前言 802.11 無線 WiFi 網有三類幀:數據幀、管理幀、控制幀。與有線網相比,無線 WiFi 網會複雜很多。大部分應用軟體開發對 WiFi 的控制幀和管理幀瞭解得並不多,因為它們在物理層和數據鏈路層就已經被處理了,上層應用很少能感知到。 一般是在設備出現 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...