「BUAA OS Lab2」名词解释
变量和类型
Pde
和Pte
Page directory entry / Page table entry
声明:
1 | typedef u_long Pde; |
位置:include/mmu.h
Pde
表示一个一级页表项,Pde
表示一个二级页表项。二者本质为u_long
。
PDX
和PTX
Page Directory indeX / Page Table indeX
maxpa
maximum physical address
声明:
1 | u_long maxpa; |
位置:mm/pmap.c
最大物理地址+1,即$ [0,maxpa - 1] $范围内的所有整数所组成的集合等于物理地址的集合。
basemem
base memory
声明:
1 | u_long basemem; |
位置:mm/pmap.c
物理内存对应的字节数
npage
number of pages
声明:
1 | u_long npage; |
位置:mm/pmap.c
总物理页数,npage个Page
和npage个物理页面一一顺序对应,具体来说,npage个Page的起始地址为pages
,则pages[i]
对应从0
开始计数的第i
个物理页面,可以使用page2pa
和pa2page
相互转换。
extmem
extend memory
扩展内存的大小,在本实验中不涉及,置0。
end
声明:
1 | . = 0x80400000; |
1 | extend char end[]; |
位置:tools/scse0_3.lds
(声明)mm/pmap.c
(引用)
对应虚拟地址0x80400000
,由映射规则知对应物理地址0x00400000
,表明我们管理的物理空间 $ [0x00400000, maxpa - 1] $。又知道这段物理地址和虚拟地址 $ [0x80400000, 0x83fffff] $一一对应,因此虚拟地址被分配出去,代表对应的物理地址也被分配出去。
freemem
第一次调用mips_vm_init
函数将其赋值为end
即$ 0x80400000 $。其含义为 $ [0x80400000, freemem - 1 ]$的虚拟地址都已被分配。
LIST_ENTRY
位置:include/queue.h
1 |
|
本质上相当于一个工厂,生产一个type类型的链表结点结构体,其内容包含指向下一个结点的指针和指向上一个节点的下一个节点指针的指针。
举例来说,当我们调用typedef LIST_ENTRY(Page) Page_LIST_entry_t;
时候,事实上为:
1 | typedef struct { |
即,构造了一个类型名为Page_LIST_entry_t
,作为Page
结构体的链表项。
Page
位置:include/pmap.h
1 | struct Page { |
Page Directory与Page Table
第一级表称为页目录(Page Directory),第二级表称为页表(Page Table)。
PFN
Physical Frame Number
物理页框号
PPN
Physical Page Number
1 |
VPN
Virtual Page Number
LEAF
在汇编代码中定义不包含对其他函数调用的函数。
NESTED
在汇编代码中定义需要调用其他函数的函数。
END
在汇编代码中结束对函数的定义。
pp_link
定义在struct Page
中的变量,意为page pointer link
,是Page
的链表项。
pp_ref
定义在struct Page
中的变量,意为page pointer refference
,等于有多少虚拟页映射到该物理页。
PTE_V
valid
PTE_R
writable
BY2PG
BYtes to a PaGe
1 |
ULIM
User limit
1 |
小于ULIM的虚拟地址位于kuseg,紧挨着kuseg的是kseg0
PDMAP
Page Directory Map, bytes mapped by a page directory entry
1 |
UVPT
User VPT
1 |
UVPT = 0x7fc0,0000
UPAGES
User Pages
1 |
UPAGES = 0x7f80,0000
UENVS
User ENVS
1 |
UENVNS = 0x7f40,0000
函数和宏函数
mips_detect_memory()
返回值:void
位置:mm/pmap.c
对一些和内存管理相关的变量进行初始化,包括maxpa
,basemem
,npage
,extmem
。
mips_vm_init
返回值:void
位置:mm/pmap.c
mips virtual memory init
alloc(u_int n, u_int align, int clear)
返回值:static void *
位置:mm/pmap.c
分配n
字节空间并返回初始虚拟地址;同时保证align
(中文意思为’对齐’)可以整除初始虚拟地址;若clear
为真则将对应空间的值清零,否则不清零。
LIST_HEAD(name, type)
位置:include/queue.h
创建一个名称为name
链表的头部结构体,包含一个指向type
类型结构体的指针,指针可以指向链表的首个元素。在我们的实验中,pmap.h
中调用了LIST_HEAD(Page_list, Page);
。
1 |
|
当调用LIST_HEAD(Page_list, Page);
,实际上相当于:
1 | struct Page_list { |
LIST_ENTRY(type)
位置:include/queue.h
LIST_EMPTY(head)
位置:include/queue.h
1 |
判断头部结构体是否为空。
LIST_FIRST(head)
位置:include/queue.h
返回头部结构体head
对应的链表的首个元素。
1 |
LIST_INIT(head)
位置:include/queue.h
将头部结构体head
对应的链表初始化,等价于将首个元素清空。
1 |
|
LIST_NEXT(elm, field)
位置:include/queue.h
结构体elm
包含的名为field
的数据,类型是一个链表项LIST_ENTRY(type)
,返回其指向的下一个元素。
1 |
LIST_INSERT_AFTER(listelm, elm, field)
位置:queue.h
LIST_INSERT_HEAD(head, elm, field)
位置:queue.h
page_decref(struct Page *pp)
page_free
PDX(va)
位置:include/mmu.h
1 |
Page Directory Index,一级页表号,或一级页表项偏移量(指针加法即可)
获取虚拟地址va
的 $ 31 - 22 $ 位
PTX(va)
位置:include/mmu.h
1 |
Page Table Index,二级页表号,或二级页表项偏移量(指针加法即可)
获取虚拟地址va
的 $ 21 - 12 $ 位
PADDR(va)
Physical Address
返回虚拟地址va
对应的物理地址。要求va
ixu是kseg0的虚拟地址,因此只需要将最高位清零就可以得到对应的物理地址。
KADDR(pa)
Kernal Address(virtual)
返回物理地址pa
对应的kseg0
的虚拟地址
1 |
|
PTE_ADDR(pte)
Page Table Entry Address
PTE(和TLB中的EntryLo结构相同)结构如上图示
1 |
对于给定的pte项,将低12位清零,得到页框号(即页号)PFN(Page Frame Number)左移12位的结果即物理地址。
bzero
位置:init/init.c
将每一个字节清空。
bcopy
位置:init/init.c
从src
拷贝len
个字节到dst
1 | void bcopy(const void *src, void *dst, size_t len) |
boot_pgdir_walk
二级页表检索函数
返回值:Pte*
,返回指向检索到的二级页表页表项的指针。
返回一级页表基地址pgdir
对应的两级页表结构中,va
虚拟地址所在的二级页表项。
这一函数在内核启动过程中被调用。
1 | static Pte *boot_pgdir_walk(Pde *pgdir, u_long va, int create) |
boot_map_segment
返回值:void boot_map_segment(Pde *pgdir, u_long va, u_long size, u_long pa, int perm)
区间地址映射函数。将一级页表基地址pgdir对应的两级页表结构做区间地址映射,将虚拟地址空间 $ [va, va + size - 1] $ 映射到物理地址区间 $ [pa, pa + size - 1] $ 。由于按页映射,要求size
是页面大小的整数倍。设置页表项的权限位为perm
。函数调用了boot_pgdir_walk
,为Page
结构体和Env
结构体进行映射。
这一函数在内核启动过程中被调用。
pgdir_walk
boot_pgdir_walk
的非启动版本,允许失败。
int pgdir_walk(Pde *pgdir, u_long va, int create, Pte **ppte)
返回值:int
,为0则执行成功,否则返回一个失败码
page_insert
增加地址映射函数,将一级页表基地址pgdir
对应的两级页表结构中va
这一虚拟地址映射到内存控制块pp
对应的物理页面,并将页表项权限位设置为perm
。
int page_insert(Pde *pgddir, struct Page *pp, u_long va, u_int perm)
返回值:int
,成功执行时返回0,否则返回-E_NO_MEM
1 | int page_insert(Pde *pgdir, struct Page *pp, u_long va, u_int perm) |
page_lookup
struct Page *page_lookup(Pde *pgdir, u_long va, Pte **ppte)
返回值:struct Page *
返回一级页表及地址pgdir
对应的两级页表结构中va
这一虚拟地址映射对应的物理页面对应的内存控制块,并且将va的二级页表项存到ppte中。
1 | struct Page * |
page_remove
void page_remove(Pde *pgdir, u_long va)
取消地址映射函数
删除一级页表基地址pgdir
对应的两级页表结构中va
这一虚拟地址对应物理地址的映射。如果存在这样的映射,那么对应物理页面结构的引用次数会减少。
pageout
void pageout(int va, int context)
被动地址映射函数
一级页表基地址context
对应的两级页表结构中va
新增这一虚拟地址的映射,对应的物理页面通过函数page_alloc
获取而不特殊指定。
tlb_invalidate
void tlb_invalidate(Pde *pgdir, u_long va)
实现删除特定虚拟地址的映射。
当页表被修改时,需要调用该函数保证下次访问该虚拟地址时会诱发TLB重填以保证访存的正确性。
page2ppn
1 | page2ppn(struct Page *pp) |
利用Page和pages(Page )确定offset,类似Page数组的下标
page2pa
1 | static inline u_long page2pa(struct Page *pp) |
获得pp(大概为Page pointer)“下标”,左移页大小可得物理地址pa(physical address)。
pa2page
1 | pa2page(u_long pa) |
根据pa(physical address),
page_init
使用链表初始化宏对
page_free_list
初始化。将
freemem
圆整- 将
freemem
以下的页面标记为pp_ref =
表示已经使用过 - 将
freemem
以上的页面的pp_ref
清零并插入page_free_list
中表示为可用物理页面
page_alloc
返回值:int
,返回值不为0表明出现异常
page_alloc(struct Page **pp)
将page_free_list
空闲链表头部内存控制块对应的物理页面分配出去,将其从空闲链表中移除,并清空对应的物理页面,最后将pp
指向的空间赋值为这个内存控制块的地址。
在这之中,我们使用了LIST_EMPTY
判断空闲链表中是否还有页面;使用了LIST_FIRST
取出了page_free_list
对应的第一个页面;使用了LIST_REMOVE()
将这个页面从page_free_list
中移除;使用bzero
将页面初始化。
page2kva
1 | page2kva(struct Page *pp) |
page_decref
page_decref(struct Page *pp)
1 | void page_decref(struct Page *pp) { |
令pp
对应内存控制块的引用次数减少1。如果引用次数为0,会接着调用page_free
将对应的物理页面重新设置为空闲页面
page_free
page_free(struct Page *pp)
判断pp
指向内存控制块对应的物理页面引用次数是否为0
,如果是的话该物理页面为空闲页面,将其重新插入到page_free_list
ROUND
1 |
圆整,返回 $ \lceil\frac{a}{n} \rceil n $ ,要求 $ n $ 必须是 $ 2 $ 的非负整数次幂。
效果是将 $ a $ 向上圆整为 $ n $ 的整数倍。
ROUNDDOWN
1 | #define ROUNDDOWN(a, n) (((u_long)(a)) & ~((n)-1)) |
圆整,返回 $ \lfloor \frac{a}{n} \rfloor n $ ,要求 $ n $ 是 $ 2 $ 的非负整数次幂。
效果是将 $ a $ 向下圆整为 $ n $ 的整数倍。
This is copyright.