[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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...