JOS Lab2 Memory Management Part 3 & challenge
Part 3: Kernel Address Space
JOS 把處理器的32位地址空間劃分為兩部分。User Environment管理低地址的部分,Kernel則對高地址的部分保持控制。這種劃分比較的任意,大致是以inc/memlayout,h
中的ULIM
為劃分。
因為kernel和user memory在彼此的地址空間中存在,我們需要使用許可權位來讓使用者程式碼只能訪問使用者的地址空間。不然可能會導致寫入了核心程式碼而產生問題。
使用者態應當沒有許可權來訪問在ULIM
上的記憶體,kernel則應當擁有讀寫許可權。使用者態程式碼和核心都對[UTOP, ULIM)
的記憶體只擁有讀許可權,因為這部分是為了向使用者態暴露一部分核心只讀資料結構。UTOP
下面的地址空間則是留給使用者態使用的。
初始化核心地址空間
Exercise 5要求設定UTOP
以上的地址空間,補充完成mem_init()
中剩下內容。
//
// Map 'pages' read-only by the user at linear address UPAGES
// Permissions:
// - the new image at UPAGES -- kernel R, user R
// (ie. perm = PTE_U | PTE_P)
// - pages itself -- kernel RW, user NONE
// Your code goes here:
boot_map_region(kern_pgdir, UPAGES, PTSIZE, PADDR(pages), PTE_U);
//
// Use the physical memory that 'bootstack' refers to as the kernel
// stack. The kernel stack grows down from virtual address KSTACKTOP.
// We consider the entire range from [KSTACKTOP-PTSIZE, KSTACKTOP)
// to be the kernel stack, but break this into two pieces:
// * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory
// * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed; so if
// the kernel overflows its stack, it will fault rather than
// overwrite memory. Known as a "guard page".
// Permissions: kernel RW, user NONE
// Your code goes here:
boot_map_region(kern_pgdir, KSTACKTOP - KSTKSIZE, KSTKSIZE, PADDR(bootstack), PTE_W);
//
// Map all of physical memory at KERNBASE.
// Ie. the VA range [KERNBASE, 2^32) should map to
// the PA range [0, 2^32 - KERNBASE)
// We might not have 2^32 - KERNBASE bytes of physical memory, but
// we just set up the mapping anyway.
// Permissions: kernel RW, user NONE
// Your code goes here:
boot_map_region(kern_pgdir, KERNBASE, 0x10000000, 0, PTE_W);
然後make qemu
看看結果:
Physical memory: 131072K available, base = 640K, extended = 130432K
check_page_free_list() succeeded!
Fail to allocate a new page! Out of Free Physical Memory!
Fail to allocate a new page! Out of Free Physical Memory!
check_page_alloc() succeeded!
Fail to allocate a new page! Out of Free Physical Memory!
Fail to allocate a new page! Out of Free Physical Memory!
Fail to allocate a new page! Out of Free Physical Memory!
Fail to allocate a new page! Out of Free Physical Memory!
Fail to allocate a new page! Out of Free Physical Memory!
Fail to allocate a new page! Out of Free Physical Memory!
check_page() succeeded!
check_kern_pgdir() succeeded!
check_page_free_list() succeeded!
check_page_installed_pgdir() succeeded!
通過了所有測試。
在回答後面的問題之前,我們重新回過頭梳理一下這個lab究竟做了什麼事情,完成了怎樣的對映。
Review:
先來回顧一下各個函式究竟在幹什麼,特別關注操作物件及其地址情況。
boot_alloc
:
給定n
,在.bss end (0xf011A0000)
之上劃分一塊n
大小,按頁對齊的虛擬地址空間。
page_init
:
對虛擬地址[0xf011B000, 0xf015B000)
的pages
陣列根據實體記憶體的使用情況進行初始化,產生一個PageInfo
的空閒實體記憶體頁的連結串列。
page_alloc
:
給定alloc_flags
(決定分配的頁是否要清零),從PageInfo
的空閒實體記憶體頁的連結串列中找到代表空閒物理頁的PageInfo
結構體,並將這個結構體對應的虛擬記憶體頁根據alloc_flag
清零或不清零,返回指向這個結構體的指標。
page_free
:
將給定的PageInfo
結構體加入空閒連結串列中。這裡即不對實體記憶體做操作,也不對虛擬記憶體做操作,也不調整頁表項。
pgdir_walk
:
給定指向頁目錄的指標和虛擬地址,返回對應虛擬地址的頁表項的指標。這裡特別需要注意虛擬地址和實體地址的區分。拿到的頁目錄的指標是虛擬地址,得到的頁目錄項中包括了頁表的實體地址。需要先轉換成頁表的虛擬地址,然後訪問拿到對應的頁表項,再取出頁表項的虛擬地址,返回。
page_lookup
:
給定指向頁目錄的指標,一個虛擬地址,和一個指向頁表項指標的指標。首先查詢該虛擬地址對應的頁表項,如果不存在指向該頁表項的指標,或者該頁表項不是Present
返回NULL,否則傳入的雙重指標指向該頁表項的指標,返回指向對應該頁表項對應實體地址的PageInfo
結構體的指標,並且使虛擬地址對應的TLB無效。
page_remove
:
給定指向頁表項的指標,一個虛擬地址。先查詢並拿到虛擬地址對應的PageInfo
結構體和指向該虛擬地址對應頁表項的指標。減少對該物理頁的引用並清空該頁表項,相當於取消虛擬地址和其對應實體地址的對映。
page_insert
:
給定指向頁目錄的指標,一個代表物理頁的指向PageInfo
結構體的指標,和一個虛擬地址。先找到該虛擬地址對應的頁表項的指標,如果該指標存在且頁表項Present
,那麼我們先增加對給定物理頁的引用,使用page_remove
移除原有的對映(順序是針對corner case的考慮),拿到給定結構體代表的物理頁的實體地址,寫到給定虛擬地址對應的頁表項裡,並使該虛擬地址對應的TLB無效。
boot_map_region
:
給定指向頁目錄的指標,一個起始虛擬地址,一個起始實體地址,和地址空間大小以及許可權。取出虛擬地址對應的頁表項,把對應的實體地址和許可權寫進去。注意在註釋中說不需要增加相應物理頁的引用。(感謝GZZ同學解惑,我之前這裡還不是特別清楚為什麼不用引用計數增加,因為這裡並不是真正地分配了page,而僅僅是通過寫頁表完成了對映)
這裡看的時候還需要特別注意,KADDR
和page2kva
的區別,以及PADDR
和page2pa
的區別。前者是直接返回某個虛擬地址的實體地址或者是某個實體地址的虛擬地址,即加減KERNBASE
,而後者則是返回PageInfo
結構體對應的實體地址和虛擬地址。
我們再回去看mem_init()
,對映完成之後就是這麼個情況:
然後我們來回答一下剩下的問題:
2. (補坑)
3. 因為使用了許可權位,因為核心程式碼的許可權位標誌為supervisor level且Read-only access
4. 最多支援2G,因為RO PAGES 4096*1024 Byte 一個PageInfo
結構為8 Byte,一個物理頁4096 Byte,因此最多訪問4096 * 1024 / 8 * 1024 = 2GB
5. 最多可以放4MB的PageInfo
陣列,加上4KB的頁目錄,再加上4MB的頁表,一共8MB+4KB
6. 在jmp *%eax
之後。 因為我們之前在entrypgdir.c
裡面把[0x00000000, 0x00400000)
的虛擬地址對映到了[0x00000000, 0x00400000)
的實體地址。因為後面kern_pgdir
會被載入進來,低虛擬地址就不再使用了。
Challenge
(補坑)
相關文章
- Memory Management in RustRust
- Oracle Shared Pool Memory ManagementOracle
- dx12 memory management
- 12. 記憶體管理(Memory Management)記憶體
- Motivation & Challenge
- win10電腦藍屏終止程式碼memory management的解決方法Win10
- HITSC_3_Software Construction Process and Configuration ManagementStruct
- 2018 Mossad Challenge
- [Memory leak] 3. Garbage collection in Closure
- win10電腦藍色畫面終止程式碼memory management的解決方法Win10
- MIT-6.828-JOS-lab6:Network DriverMIT
- type challenge(easy 部分)
- The FLARE On Challenge題解
- MIT6.S081(2023 Fall) Lab2 & Lab3 總結MIT
- AMBF 之 surgical robotics challenge
- Customer Management
- Study Plan For Algorithms - Part3Go
- Datatable Scroller (Server Side) Part:3ServerIDE
- IDAPython 讓你的生活更滋潤 – Part 3 and Part 4Python
- MIT-6.828-JOS-lab5:File system, Spawn and ShellMIT
- mit6.828 - lab2筆記MIT筆記
- 疫情視覺化part3視覺化
- 8086 彙編學習 Part 3
- memory
- VDI/VDE 2643 Part3 2008:10
- [SwiftUI 100天] Bucket List - part3SwiftUI
- [part 3] 第一個 Django 應用Django
- 【Arranging an Appointment】Unit1 Part3APP
- 深入淺出Rust Future Part-3Rust
- python challenge 解題 第4關Python
- IJCAI-PRICAI 3D AI Challenge 2020: Instance Segmentation第二名方案AI3DSegmentation
- ASM(Automatic Storage Management)ASM
- Oracle Cluster Time ManagementOracle
- BMZCTF:memory
- golang pprof 監控系列(3) —— memory,block,mutex 統計原理GolangBloCMutex
- MIT6.S081 - Lab2: system callsMIT
- Lab2 - ADT&OOP 回顧總結OOP
- MIT6.828 Lab2 記憶體管理MIT記憶體