linux-0.11 内存研究 (三)


一个系统中可以同时存在多个页目录表,而在某个时刻只有一个页目录表可用。
当前的页目录使用CPU的寄存器CR3来确定的,它存储着当前页目录表的物理内存地址。
0.11内核只使用了一个页目录表。

图中的存在位(P):当CPU试图使用一个页表项进行地址转换时,如果此时任意一个页表项的P=0,则处理器就会发出页异常信号。
此时缺页中断异常处理程序就可以把所请求的页加入到物理内存中,并且导致异常的指令会被重新执行。

已访问(A)和已修改(D)位用于提供有关页使用的信息。除了页目录项中的已修改位,这些位有硬件置位,但不复位。
页目录项和页表项的区别在于页表项有个已写位(D),而页目录项没有。
在对一页内存进行读或写操作之前,CPU将设置相关的目录和二级页表项的A位。
在向一个二级页表项所涵盖的地址进行写操作之前,CPU将设置该二级页表项的D位。
当所需求的内存超出实际物理内存量时,内存管理程序就可以使用这些位来确定哪些页可以从内存中取走,以腾出空间。
内存管理程序还需负责检测和复位这些位。

---------------------------------------------------------------
关于写时复制:
在内核代码空间(线性地址 < 1MB)执行fork()来创建进程时,并没有采用写时复制技术。
一次当进程0(idle进程)在内核空间创建进程1(init进程)时将使用同一段代码和数据段。
但由于进程1复制的页表项也是只读的,因此当进程1需要执行堆栈(写)操作时才会引起页面异常,
从而在这种情况下内存管理程序才会在主内存区中为该进程分配内存。如下图所示:


---------------------------------------------------------------




---------------------------------------------------------------
下面是0.12内核的copy_page_tables代码,和0.11相比,主要变化就是方框中的,其对应的汇编代码在右边,在JPC中跑bochs编译出的版本,打0xC459,0xC47E断点,都没有断住,没跑到这里。
但是根据以前的记录,自己编的版本跑到了。


--------------------------------------------------------------- OK,目前0.11内核路线分析如下:

上篇: linux-0.11 内存研究 (二) 下篇: build linux0.12-编译器优化引发的问题