操作系统lab2实验总结——Part1
这是MIPS虚拟映射布局图,在接下来的实验中,我们需要特别注意的地址分别是kuseg和kseg0区,首先列出这两个区域的意义。
MIPS虚存映射布局
32位的MIPS CPU最大寻址空间为4GB(2^32字节),这4GB虚存空间被划分为四个部分:
kuseg (TLB-mapped cacheable user space, 0x00000000 - 0x7fffffff): 这一段是用户模式下可用的地址,大小为2G,也就是MIPS约定的用户内存空间。需要通过MMU进行虚拟地址到物理 地址的转换。
kseg0 (direct-mapped cached kernel space, 0x80000000 - 0x9fffffff): 这一段是内核地址,其内存虚存地址到物理内存地址的映射转换不通过MMU,使用时只需要将地址的最高位清零 (& 0x7fffffff), 这些地址就被转换为物理地址。也就是说,这段逻辑地址被连续地映射到物理内存的低端512M空间。对这段地址 的存取都会通过高速缓存(cached)。通常在没有MMU的系统中,这段空间用于存放大多数程序和数据。对于有 MMU 的系统,操作系统的内核会存放在这个区域。
kuseg中有三个大小为PDMAP(4MB)的区域,分别从0x7f400000开始是ENVS,PAGES和User VPT。需要注意的是PAGES和User VPT的关系:User VPT中存放了1024个页表,由于自映射的关系,这个页表里又包括了页目录的页表,每一个页表中又有1024个页表项。PAGES存放了48个页表,这48个页表映射的内容是16*1024个物理页框的结构体(struct Page)的物理内存。在lab2实验中,我们只用了boot_map_segment函数将PAGES的内容进行了映射,并没有操作User VPT的空间。
第一幅图将是我们理解整个mm/pmap.c的核心,接下来将按照init/init.c中的顺序进行逐一解释每个函数的细节和整体的启动布局。
1 //这是init/init.c里的函数调用顺序 2 mips_detect_memory(); 3 mips_vm_init(); 4 page_init();
一、mips_detect_memory()
1.代码块
1 void mips_detect_memory() 2 { 3 //in bytes 4 basemem = 64 * 1024 * 1024;//物理内存的大小为64MB-->26位 5 npage = 16 * 1024;//物理页框的个数 6 maxpa = basemem;//最大的物理地址 7 extmem = 0;//延申的空间 8 printf("Physical memory: %dK available, ", (int)(maxpa / 1024)); 9 printf("base = %dK, extended = %dK\n", (int)(basemem / 1024), 10 (int)(extmem / 1024)); 11 }
2.初始化一些内存相关的参数,意义写在注释里,不赘述。
二、mips_vm_init()
1.代码块
1 void mips_vm_init() 2 { 3 extern char end[]; 4 extern int mCONTEXT; 5 extern struct Env *envs; 6 7 Pde *pgdir; 8 u_int n; 9 10 /* Step 1 */ 11 pgdir = alloc(BY2PG, BY2PG, 1); 12 printf("to memory %x for struct page directory.\n", freemem); 13 mCONTEXT = (int)pgdir;//mCONTEXT是虚拟地址 14 15 boot_pgdir = pgdir; 16 17 /* Step 2*/ 18 pages = (struct Page *)alloc(npage * sizeof(struct Page), BY2PG, 1); 19 printf("to memory %x for struct Pages.\n", freemem); 20 21 n = ROUND(npage * sizeof(struct Page), BY2PG); 22 23 boot_map_segment(pgdir, UPAGES, n, PADDR(pages), PTE_R); 24 25 /* Step 3*/ 26 envs = (struct Env *)alloc(NENV * sizeof(struct Env), BY2PG, 1); 27 n = ROUND(NENV * sizeof(struct Env), BY2PG); 28 boot_map_segment(pgdir, UENVS, n, PADDR(envs), PTE_R); 29 30 printf("pmap.c:\t mips vm init success\n"); 31 }