《linux 内核完全剖析》上帝为什么是右移20,而不是22! dir = (

在memory.c里面有这么一段代码。为了其中的一句话,让我内牛满面啊!

dir = (unsigned long *) ((from>>20) & 0xffc)

int free_page_tables(unsigned long from,unsigned long size){    unsigned long *pg_table;    unsigned long * dir, nr;    if (from & 0x3fffff)        panic("free_page_tables called with wrong alignment");    if (!from)        panic("Trying to free up swapper memory space");    size = (size + 0x3fffff) >> 22;    dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */    for ( ; size-->0 ; dir++) {        if (!(1 & *dir))            continue;        pg_table = (unsigned long *) (0xfffff000 & *dir);        for (nr=0 ; nr<1024 ; nr++) {            if (*pg_table) {                if (1 & *pg_table)                    free_page(0xfffff000 & *pg_table);                else                    swap_free(*pg_table >> 1);                *pg_table = 0;            }            pg_table++;        }        free_page(0xfffff000 & *dir);        *dir = 0;    }    invalidate();    return 0;}

搞定这段代码如果分页机制不过关,是不能真正领悟其精髓的

<注释>的讲80×86的时候有讲分页机制

http://blog.csdn.net/cinmyheart/article/details/24354735

Moder operating system 讲的memory management

http://blog.csdn.net/cinmyheart/article/details/24888847

dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */

from是个线性地址,如果右移22bit,那么刚好可以得到目录号,wait!有一个极具“陷阱” 的概念,我看了两本书上都没有讲,MOS不讲还情有可原,理论高度比较好,但是<注释> 没讲,让我觉得有点坑爹了。

花了好长时间才理清楚

这里的31~22 bit存放的是页目录的目录号,主内存区这部分必须从1开始,不能从0开始,换句话说,就是目录号(注意这个概念),他是从1开始的,而不是0

目录号和指向页目录的指针,之间有一个联系,这个联系基于一个事实,就是系统初始化完成之后,地址0x00开始存放的是内存页目录表GDT!

那么页目录号对应页目录地址的话,仅仅只需要把页目录号左移两位,或者,右移20位,并且& 0xffc 那么就可以得到指向页目录的指针(不指向内核段内存页目录表)

那么最小的页目录号是1,对应的地址就是0x0004(在这之前的4个表供内核使用,即指向内核的4M区域)

注意,右移22位即可得到页目录号,而右移20位并且&0xffc再强制转换成指针,即可得到指向主内存区域的页表目录指针!

即使爬到最高的山上,一次也只能脚踏实地地迈一步。

《linux 内核完全剖析》上帝为什么是右移20,而不是22! dir = (

相关文章:

你感兴趣的文章:

标签云: