现在的位置: 首页 > 综合 > 正文

linux内核学习笔记【一】临时内核页表 Provisional kernel Page Tables

2013年10月13日 ⁄ 综合 ⁄ 共 1890字 ⁄ 字号 评论关闭

最近开始学习linux内核,看了《深入理解linux内核》,开始写点学习收获。内核版本为2.6.11  

  临时全局目录(provisional page global directory)是在内核编译过程中静态初始化的,而临时页表是由startup_32()汇编语言函数(定义于arch/i386/kernel/head.S)初始化的。临时页全局目录放在swapper_pg_dir变量中,swapper_pg_dir有1024个项,但是如果只是初始化前8MB的话,只需要用到两个目录项。临时页表在pg0变量处开始存放,紧接在内核未初始化的数据段。(_end符号后面)。通过查看/boot/System.map,可以找到swapper_pg_dir的地址,例如0xc047d000
(抄了某位前辈的数据,由于不知道原始作者是谁,就先在这声明下。这个数据是编译时产生的所以,因机器而异,后面的数据同此处)。pg0的线性地址为0xc04f4000
。之后我们进入代码:  

复制代码
 1     movl $(pg0 - __PAGE_OFFSET), %edi  
 2     /* move pg0 - __PAGE_OFFSET = c04f4000-c0000000=4f4000 => edi 
 3        相当于第一个页表项的初始物理地址        */
 4     movl $(swapper_pg_dir - __PAGE_OFFSET), %edx  
 5     /* c047d000 - c0000000 = 47d000 => edx 
 6            相当于第一个页目录项的初始物理地址         */
 7     movl $0x007, %eax            
 8     /* 0x007 = PRESENT+RW+USER 
 9            这里为什么要加7呢,因为无论是页表项还是页目录项的前20位是物理地址,后12位为状态字
10            这里的加7实际上就是将后三位也就是PRESENT,RW,USER三位置为    */
11 10:
12     leal 0x007(%edi),%ecx            
13     /* Create PDE entry 
14        由于这里是设置页目录项的,所以将页表项的第一项物理地址+7
15        如果带入我们之前的值的话,ecx = 4f4007即页表项的第一项的物理地址,
16        加上PRESENT,RW,USER三个标志位    */
17     movl %ecx,(%edx)            
18     /* Store identity PDE entry 
19        将4f4007存储到edx中 即swapper_pg_dir[0]也就是47d000这个地址    */
20     movl %ecx,page_pde_offset(%edx)        
21     /* Store kernel PDE entry 
22        将4f4007存储到内核的页表空间中 即swapper_pg_dir[0x300]也就是c047d000这个地址*/
23     addl $4,%edx
24     /* swapper_pg_dir指针向下移动一个entry,也就是4个字节*/
25     movl $1024, %ecx
26     /* 初始化计数器,循环1024次,也就是1024个页表*/
27 11:
28     stosl
29     /* 把eax中的内容放入edi指向的物理地址中,然后edi+4。
30        edi指向的地址为pg0的地址,之前eax赋值为7,所以pg0的第一项也就是地址4f4000的值为00000007*/
31     addl $0x1000,%eax
32     /* 移动指针到下一个页的地址,因为一个页的大小为4096,即0x1000个字节 */
33     loop 11b
34     /* 经过循环将pg0的1024个表项都进行赋值 */
35     /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
36     /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
37     leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
38     /* INIT_MAP_BEYOND_END = 128k,文件中定义的。也就是目前pg0的指针+128k内核空间+7是否被全部映射(<ebp),
39        如果没有呗全部映射,则跳到10,再映射4MB空间。*/
40     cmpl %ebp,%eax
41     jb 10b
42     movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
43     /* 如果映射完成,则将gp0末尾地址赋值给init_pg_tables_end*/
复制代码

简单的画了个图

终于搞明白了这个临时内核页表是怎么建立的了,明天继续。。。

http://www.cnblogs.com/lazygunner/archive/2011/11/08/2241699.html

 

抱歉!评论已关闭.