《linux 内核完全剖析》上帝为什么是右移20,而不是22! dir = (unsigned long *) ((from>>20) & 0xffc)

在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;

}

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

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

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 = (unsigned long *) ((from>>20) & 0xffc),布布扣,bubuko.com

时间: 2024-10-11 06:33:14

《linux 内核完全剖析》上帝为什么是右移20,而不是22! dir = (unsigned long *) ((from>>20) & 0xffc)的相关文章

《linux 内核完全剖析》get_free_page(void)

get_free_page(void) 分析极其资料整理 实现在swap.c 里面 程序功能概述: 首先在内存映射字节位图中查找值为0的字节项,然后把对应物理内存页面清零,如果得到的页面地址值大于实际物理内存容量则重新寻找.如果没有找到空闲页面则去调用执行交换处理,并重新查找.最后返回空闲物理地址. 我一开始没能比较熟练的掌握嵌入式汇编,所以又把问题的难度拔高了...如果熟练的掌握嵌入式汇编的话,不至于被卡这么久 :"=a" (__res) :"0" (0),&qu

《linux 内核完全剖析》 keyboard.S 部分代码分析(key_map)

keyboard.S 部分代码分析(key_map) keyboard中间有这么一段,我一开始没看明白,究竟啥意思 key_map: .byte 0,27 .ascii "1234567890-=" .byte 127,9 .ascii "qwertyuiop[]" .byte 13,0 .ascii "asdfghjkl;'" .byte '`,0 .ascii "\\zxcvbnm,./" .byte 0,'*,0,32

《linux 内核完全剖析》 exit.c 代码分析笔记

exit.c 代码分析笔记 release 释放进程的函数release() 主要根据指定进程的任务数据结构指针,在任务数组中删除指定的进程指针,释放相关内存页,并立刻让内核重新调度进程的运行. void release(struct task_struct * p) //释放p指向的进程 { int i; if (!p) //常规检测p是否为0 return; if (p == current) { //不能把自己给释放了 printk("task releasing itself\n\r&q

《linux 内核完全剖析》chapter 13 内存管理 (不含swap.c)

内存管理(memory.c 和swap.s 部分) "倒着看" 先看memory management,很明显,前面各种阻力,都是因为涉及内存管理.不先看这个,我估计前面看了也是白看 我估算着理论打基础砸了差不多一个星期的时间在memory management上面了...感觉很有收获,是时候用实践(code)印证理论了! <modern operating system>讲内存管理那一章 http://blog.csdn.net/cinmyheart/article/de

《linux 内核完全剖析》 笔记 由逻辑地址转换成线性地址代码分析

一开始由这段代码引发的纠结 get_base(current->ldt[1]) 下面是各个相关的代码,摘自不同的header files... current是指向当前task的指针 struct desc_struct ldt[3]; struct desc_struct { unsigned long a,b; } ; #define _get_base(addr) ({unsigned long __base; __asm__("movb %3,%%dh\n\t" &quo

《linux 内核完全剖析》 include/asm/io.h

include/asm/io.h #define outb(value,port) __asm__ ("outb %%al,%%dx"::"a" (value),"d" (port)) //宏定义outb用汇编实现了在端口地址port处写入值value //使用的寄存器是al,一个byte长度,而端口port使用的是2byte长度地址来标记的寄存器,注意这里寄存器的使用 #define inb(port) ({ unsigned char _v;

《linux 内核完全剖析》 mktime.c

tm结构体的定义在time.h里面 struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; /* * linux/kernel/mktime.c * * (C) 1991 Linus Torvalds */ #include <time.h> /* * This isn't the libra

《linux 内核完全剖析》 void free_page() 分析

最近在做项目开发时用到了MySql数据库,在看了一些有关MySql的文章后,很快就上手使用了.在使用的过程中还是出现了一些问题,因为使用的是绿色免安装版的MySql所以在配置的时候出现了一些问题,该篇文章就主要针对MySql绿色版的配置及其使用进行讨论. 一.MySql概述 MySql数据库是有瑞典MySql AB公司开发,现在该公司被Oracle收购属于Oracle所有.同SQL Server类似,它也是基于关系型数据库的数据库管理系统,在Web应用方面MySQL是最好的RDBMS之一,因为它

《linux 内核完全剖析》 fork.c 代码分析笔记

fork.c 代码分析笔记 verifiy_area long last_pid=0; //全局变量,用来记录目前最大的pid数值 void verify_area(void * addr,int size) // addr 是虚拟地址 ,size是需要写入的字节大小 { unsigned long start; start = (unsigned long) addr; //把地址强制类型转换之后,赋值给start size += start & 0xfff; //取addr在当前虚拟地址中4