|
楼主 |
发表于 2006-3-31 01:08:06
|
显示全部楼层
搞清楚了,发贴澄清一下.
1.内核初始化时,内核页目录进行初始化,初始化的结果是,把3g--3g+物理内存大小之间
线性地址线性的映射到物理地址(效果相当于直接减去3g就等于物理地址,但实际上还
是要通过cpu的mmu来映射,也就是要通过cr3寄存器,这是内核初始话时精心设置的,不
要怀疑其正确性,不信可以去读代码).也就是说,初始化过程中,0号进程的页面目录的
高256项能初始化的都初始化了(还有一些没有初始化,取决于物理内存大小,如果物理
内存只有512M,那么就只初始化其769--768+128项,后面的128项依然为空).
2.linux是通过do_fork来产生新的进程(或内核线程,本文暂不考虑它,实际上这个更简单)
在fork一个进程的时候,必须建立进程自己的内核页目录项(内核页目录项要与用户空间
的页目录放在同一个物理地址连续的页面上,所以不能共享,但所有进程的内核页表与进
程0共享).
这也就是为什么说所有的进程都享3g-4g的线性地址.
附:实际上有时会出现内核的页面目录的高256项和进程的pgd所指向的页面目录的高256
项不一致的情况(比方说在ioremap()或vmalloc()调用之后),接下来会解释.但是现在要
清楚的是此时的0号进程的内存映射是最新的(因为ioremap或vmalloc更新的是init_mm
的pgd所对应的内核页目录),我们需要做的事情是把其它进程的内核页目录更新,不过由
于现在就全部更新消耗太大,所以都采用的是"用的时候再说",出现缺页时再更新.
3.在vmalloc和ioremap的时候因为分配的是内核虚拟空间,所以要设置相应的页目录和
页表项.但是他们设置的都是0号进程对应的(也就是init_mm对应的页面映射目录或表),
别的进程的内核页面目录可能并无映射,这时当该进程进行系统调用转入内核态时就
可能发生缺页故障(这句话我还要斟酌).当一个进程在内核空间发生缺页故障的时候,
就要通过0号进程的页目录来同步本进程的内核页目录,实际上就是拷贝0号进程的
内核页目录到本进程中(内核页表与进程0共享,故不需要复制).
这样的结果就是所有进程的内核页面目录都和0号进程"几乎一样",不一样的部分会在
需要时建立映射. |
|