Specify language for visual improvement.
This commit is contained in:
parent
012434e9ee
commit
4699a9bf9a
|
@ -71,7 +71,7 @@ void main()
|
|||
|
||||
得到的主要汇编代码为:
|
||||
|
||||
```asm
|
||||
```x86asm
|
||||
movl count,%ecx
|
||||
movl value,%eax
|
||||
movl buf,%edi
|
||||
|
@ -106,7 +106,7 @@ asm("leal (%1,%1,4),%0"
|
|||
|
||||
这段代码到的主要汇编代码为:
|
||||
|
||||
```asm
|
||||
```x86asm
|
||||
movl x,%eax
|
||||
#APP
|
||||
leal (%eax,%eax,4),%eax
|
||||
|
|
|
@ -29,10 +29,10 @@ virt addr = phy addr + 0xC0000000
|
|||
|
||||
ucore
|
||||
的内存管理经常需要查找页表:给定一个虚拟地址,找出这个虚拟地址在二级页表中对应的项。通过更改此项的值可以方便地将虚拟地址映射到另外的页上。可完成此功能的这个函数是get\_pte函数。它的原型为
|
||||
```
|
||||
```c
|
||||
pte_t *get_pte (pde_t *pgdir, uintptr_t la, bool create)
|
||||
```
|
||||
下面的调用关系图可以比较好地看出get\_pte在实现上诉流程中的位置:
|
||||
下面的调用关系图可以比较好地看出get\_pte在实现上述流程中的位置:
|
||||
|
||||

|
||||
|
||||
|
@ -90,7 +90,7 @@ virt addr = linear addr + 0xC0000000 = phy addr + 2 * 0xC0000000
|
|||
```
|
||||
如何保证此时内核依然能够正常工作呢?其实只需让index为0的页目录项的内容等于以索引值为(KERNBASE>>22)的目录表项的内容即可。目前内核大小不超过
|
||||
4M (实际上是3M,因为内核从 0x100000开始编址),这样就只需要让页表在0\~4MB的线性地址与KERNBASE \~ KERNBASE+4MB的线性地址获得相同的映射即可,都映射到 0\~4MB的物理地址空间,具体实现在pmm.c中pmm\_init函数的语句:
|
||||
```
|
||||
```c
|
||||
boot_pgdir[0] = boot_pgdir[PDX(KERNBASE)];
|
||||
```
|
||||
实际上这种映射也限制了内核的大小。当内核大小超过预期的3MB
|
||||
|
@ -98,7 +98,7 @@ boot_pgdir[0] = boot_pgdir[PDX(KERNBASE)];
|
|||
|
||||
当执行完毕gdt\_init函数后,新的段页式映射已经建立好了,上面的0\~4MB的线性地址与0\~4MB的物理地址一一映射关系已经没有用了。
|
||||
所以可以通过如下语句解除这个老的映射关系。
|
||||
```
|
||||
```c
|
||||
boot_pgdir[0] = 0;
|
||||
```
|
||||
在page\_init函数建立完实现物理内存一一映射和页目录表自映射的页目录表和页表后,一旦使能分页机制,则ucore看到的内核虚拟地址空间如下图所示:
|
||||
|
|
|
@ -52,7 +52,7 @@ SECTIONS {
|
|||
virt addr - 0xC0000000 = linear addr = phy addr # 物理地址在0~4MB之内的三者映射关系
|
||||
```
|
||||
请注意`pmm_init`函数中的一条语句:
|
||||
```
|
||||
```c
|
||||
boot_pgdir[0] = boot_pgdir[PDX(KERNBASE)];
|
||||
```
|
||||
就是用来建立物理地址在0~4MB之内的三个地址间的临时映射关系`virt addr - 0xC0000000 = linear addr = phy addr`。
|
||||
|
|
|
@ -32,14 +32,14 @@ boot\_pgdir[PDX(VPT)] = PADDR(boot\_pgdir) | PTE\_P | PTE\_W;
|
|||
这些变量和语句有何特殊含义呢?其实vpd变量的值就是页目录表的起始虚地址0xFAFEB000,且它的高10位和中10位是相等的,都是10进制的1003。当执行了上述语句,就确保了vpd变量的值就是页目录表的起始虚地址,且vpt是页目录表中第一个目录表项指向的页表的起始虚地址。此时描述内核虚拟空间的页目录表的虚地址为0xFAFEB000,大小为4KB。页表的理论连续虚拟地址空间0xFAC00000\~0xFB000000,大小为4MB。因为这个连续地址空间的大小为4MB,可有1M个PTE,即可映射4GB的地址空间。
|
||||
|
||||
但ucore实际上不会用完这么多项,在memlayout.h中定义了常量
|
||||
```
|
||||
```c
|
||||
#define KERNBASE 0xC0000000
|
||||
#define KMEMSIZE 0x38000000 // the maximum amount of physical memory
|
||||
#define KERNTOP (KERNBASE + KMEMSIZE)
|
||||
```
|
||||
|
||||
表示ucore只支持896MB的物理内存空间,这个896MB只是一个设定,可以根据情况改变。则最大的内核虚地址为常量
|
||||
```
|
||||
```c
|
||||
#define KERNTOP (KERNBASE + KMEMSIZE)=0xF8000000
|
||||
```
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
**实现物理内存探测**
|
||||
|
||||
物理内存探测是在bootasm.S中实现的,相关代码很短,如下所示:
|
||||
```asm
|
||||
```x86asm
|
||||
probe_memory:
|
||||
//对0x8000处的32位单元清零,即给位于0x8000处的
|
||||
//struct e820map的成员变量nr_map清零
|
||||
movl $0, 0x8000
|
||||
movl $0, 0x8000
|
||||
xorl %ebx, %ebx
|
||||
//表示设置调用INT 15h BIOS中断后,BIOS返回的映射地址描述符的起始地址
|
||||
movw $0x8004, %di
|
||||
|
|
|
@ -6,7 +6,7 @@ ucore
|
|||
kernel各个部分由组成kernel的各个.o或.a文件构成,且各个部分在内存中地址位置由ld工具根据kernel.ld链接脚本(linker
|
||||
script)来设定。ld工具使用命令-T指定链接脚本。链接脚本主要用于规定如何把输入文件(各个.o或.a文件)内的section放入输出文件(lab2/bin/kernel,即ELF格式的ucore内核)内,
|
||||
并控制输出文件内各部分在程序地址空间内的布局。下面简单分析一下/lab2/tools/kernel.ld,来了解一下ucore内核的地址布局情况。kernel.ld的内容如下所示:
|
||||
```asm
|
||||
```
|
||||
/* Simple linker script for the ucore kernel.
|
||||
See the GNU ld 'info' manual ("info ld") to learn the syntax. */
|
||||
|
||||
|
@ -122,7 +122,7 @@ segment):指用来存放程序执行代码的一块内存区域。这部分
|
|||
extern char edata[], end[];
|
||||
```
|
||||
但搜寻所有源码文件\*.[ch],没有发现有这两个变量的定义。那这两个变量从哪里来的呢?其实在lab2/tools/kernel.ld中,可以看到如下内容:
|
||||
```asm
|
||||
```
|
||||
…
|
||||
.text : {
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
|
|
Loading…
Reference in New Issue