put_page

 1 //// 把一物理内存页面映射到线性地址空间指定处。
 2 // 或者说是把线性地址空间中指定地址address处的页面映射到主内存区页面page上。主
 3 // 要工作是在相关页面目录项和页表项中设置指定页面的信息。若成功则返回物理页面地
 4 // 址。在处理缺页异常的C函数do_no_page()中会调用此函数。对于缺页引起的异常,由于
 5 // 任何缺页缘故而对页表作修改时,并不需要刷新CPU的页变换缓冲(或称Translation Lookaside
 6 // Buffer - TLB),即使页表中标志P被从0修改成1.因为无效页表项不会被缓冲,因此当修改
 7 // 了一个无效的页表项时不需要刷新。再次就表现为不用调用Invalidate()函数。
 8 // 参数page是分配的主内存区中某一页面(页帧,页框)的指针;address是线性地址。
 9 unsigned long put_page(unsigned long page,unsigned long address)
10 {
11     unsigned long tmp, *page_table;
12 
13 /* NOTE !!! This uses the fact that _pg_dir=0 */
14 
15     // 首先判断参数给定物理内存页面page的有效性。如果该页面位置低于LOW_MEM(1MB)
16     // 或超出系统实际含有内存高端HIGH_MEMORY,则发出警告。LOW_MEM是主内存区可能
17     // 有的最小起始位置。当系统物理内存小于或等于6MB时,主内存区起始于LOW_MEM处。
18     // 再查看一下该page页面是否已经申请的页面,即判断其在内存页面映射字节图mem_map[]
19     // 中相应字节是否已经置位。若没有则需发出警告。
20     if (page < LOW_MEM || page >= HIGH_MEMORY)
21         printk("Trying to put page %p at %p\n",page,address);
22     if (mem_map[(page-LOW_MEM)>>12] != 1)
23         printk("mem_map disagrees with %p at %p\n",page,address);
24     // 然后根据参数指定的线性地址address计算其在也目录表中对应的目录项指针,并
25     // 从中取得二级页表地址。如果该目录项有效(P=1),即指定的页表在内存中,则从中
26     // 取得指定页表地址放到page_table 变量中。否则就申请一空闲页面给页表使用,并
27     // 在对应目录项中置相应标志(7 - User、U/S、R/W).然后将该页表地址放到page_table
28     // 变量中。
29     page_table = (unsigned long *) ((address>>20) & 0xffc);
30     if ((*page_table)&1)
31         page_table = (unsigned long *) (0xfffff000 & *page_table);
32     else {
33         if (!(tmp=get_free_page()))
34             return 0;
35         *page_table = tmp|7;
36         page_table = (unsigned long *) tmp;
37     }
38     // 最后在找到的页表page_table中设置相关页表内容,即把物理页面page的地址填入
39     // 表项同时置位3个标志(U/S、W/R、P)。该页表项在页表中索引值等于线性地址位21
40     // -- 位12组成的10bit的值。每个页表共可有1024项(0 -- 0x3ff)。
41     page_table[(address>>12) & 0x3ff] = page | 7;
42 /* no need for invalidate */
43     return page;
44 }

 

posted @ 2021-05-20 10:16  人生充满不确定性  阅读(790)  评论(0)    收藏  举报