温故而知新,几个点,有必要记一下:


1. 在执行C语言对应的程序前(boot loader),汇编部分(entry.S)已经设置好了ebp & esp。如此,C语言执行函数时即有了栈环境。



2. 内存管理是黑魔法…

分段机制(segment)无法取消,即使分页机制(paging)开启依然作用。变化只是从初始的-0xF000 0000变为了0x0;

为什么是256M? 不知道和bochs有关?不过如果物理内存是1个G的话,初始的段offset就不是-0xF000 0000而该是-0xC000 0000;


pgdir_walk()一直比较困扰我…因为涉及到stack variable,segment offset,physical address,virtual address,还涉及到段基址以及MMU自动的地址转换。我一度很分裂…而且现在依然不是很清醒…说一下理解:

分页机制开始前,因为segment offset是-0xF000 0000,所以地址我们首先手动的对其进行KADDR转换,接下来系统会自动为该虚地址+(offset=-0xF000 0000),得到其物理地址并访问;

分页机制启动后,segment offset重置为0。仍然需要进行KADDR的转换是因为页目录的映射关系,参看之前的映射Map all of physical memory at KERNBASE


3.1 进程:将执行状态(Trapframe)与地址空间(virtual address)结合在一起(补一句,EFLAG, CR0 ~ CR3真是存了不少东西)

加载映像image的时候(就是load .text, .data segment时),记得要切换page dir,因为…你需要加载到自己的地址空间,而非操作系统的地址空间。


vpt是在kern/entry.S里设置的,对应于每个进程。vpt[0]对应virtual address page entry [0], … vpt[N]对应page entry[N]。

这个神奇的映射关系来源于env_setup_vm里的语句e->env_pgdir[PDX(VPT)]  = e->env_cr3 | PTE_P | PTE_W;

至于怎么解析…假设访问page entry[0],对应vpt[0]。vpt[0]其实就是VPT的地址0xefc0 0000 –> 1110 1111 1100 0000 0000… 

@step1, 取前10bit获得其page table对应的physical address,发现竟然映射回了pgdir。

@step2, 接下来取中间的10bit,此时对应到pgdir[0],也即头一份的page table的物理地址;

@step3, 取最后的12bit(这里最后2bit应该都是0,所以其实是对齐于4字节的),取到page table[0]。就是页表的第一项…mission complete, vpt[0]对应于page table entry[0]得证。

希望分析的对,内存真是黑魔法…

3.2 Interrupt & Exception: 

印象比较深的就是page fault对应的处理是在用户态进行的:在内核态时设置好返回用的Trapframe,通过env_run跳转到用户态;在专门的stack上处理该exception;

Copy-on-Write, COW, COW, COW…milk…milk…


4.1 fork

parent与child拥有相同的Trapframe(eip应该是指向系统调用的下一条指令的地址,又即系统调用返回后的第一条指令),以及相同的virtual address。不同的是,child的env属性中eax(作为返回值)以及status(NOT_RUNNABLE)被修改了。所以二者会在同一地址返回,但因为eax不同,进而进入不同的执行分支。


4. 2  IPC

传值(int)与page映射。在内核态进行判断。


5. File System

根目录的相关内容存在SuperBlock中,方便查找。

文件内容映射到内存中,整整3GB的内存空间。读写基本都还是与内存打交道。


6. Shell

duppage, pipe, 等。


补:

pageref的使用貌似就是操作系统的Objc的reference count;

dev与file/pipe的关系,分明就是C的面向对象的实现;


以上。