日期:2014-05-16  浏览次数:20986 次

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


#define PAGE_SIZE 4096

/* these are not to be changed without changing head.s etc */
#define LOW_MEM 0x100000
extern unsigned long HIGH_MEMORY;
#define PAGING_MEMORY (15*1024*1024)
#define PAGING_PAGES (PAGING_MEMORY>>12)
#define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
#define USED 100

extern unsigned char mem_map [ PAGING_PAGES ];

#define PAGE_DIRTY    0x40
#define PAGE_ACCESSED    0x20
#define PAGE_USER    0x04
#define PAGE_RW        0x02
#define PAGE_PRESENT    0x01



截取了一部分mm.h 的内容相当重要的说。。。。


PAGE_SIZE 定义了1页内存字节书。特别注意,高速缓冲块长度是1024 byte

LOW_MEM 机器物理内存1M

PAGING_MEMORY 15M 主内存区最多15M。。。其实这里如果内存大的话就应该会相应的变(个人推论,如有错误,欢迎指正!)

PAGING_PAGE 分页后的物理内存页面数,>>12 就是除以4M,每个页面的大小是4M,于是可以算得所有的页面数

MAP_NR(addr)得到指定内存地址映射页面号

USED 页面被占用号


mem_map 数组记录的值是每一个位,对应的页被引用的次数。 这里linux 0.12 采用了bits-map的策略


 

mem_map 数组记录的值是每一个位,对应的页被引用的次数。 这里linux 0.12 采用了bits-map的策略

关于bitmaps可以看 MOS的第三章的 Memory Management with Bitmaps (在检索目录里面有)

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



void free_page(unsigned long addr)

{

      if(addr <LOW_MEM) return; //如果addr是1M的内核模块映射页,那么是不能free掉的,free无效,主动return挂掉free_page

      if(addr>= HIGH_MEMORY)//我刚开始一直很纠结,不是很明白为什么HIGH_MEMORY会被定义成0这里》=0是干嘛。。。

          panic("tryingto free nonexistent page");

      addr-=LOW_MEM;

      addr>>=12;//右移12位,那么得到addr的页面数

      if(mem_map[addr]--)return;

/*我只能说这个后—太技巧了。如果当前mem_map[addr]== 0 那么这个页是个free page,if判断为假于是执行下面的语句,这时候实质上是试图free一个free page是错误的。如果mem_map[addr] >0 说明有进程占用这个page,那么返回,并-1 */

      mem_map[addr]=0;

      panic("tryingtofree free page");

}






一开始对HIGH_MEMORY有疑惑是因为没有找到HIGH_MEMORY被其他的数值赋值了,在mem_init里面



void mem_init(long start_mem, long end_mem)
{
    int i;

    HIGH_MEMORY = end_mem;
    for (i=0 ; i<PAGING_PAGES ; i++)
        mem_map[i] = USED;//把所有15M主内存区的mem_map 置为USED
    i = MAP_NR(start_mem);
    end_mem -= start_mem;
    end_mem >>= 12;//除以4M得到页数
    while (end_mem-->0)
        mem_map[i++]=0;//把扩展内存区的mem_map 置0,设置为空闲
}