Linux-0.11内核源码分析系列:内存管理free_page()与free_page_tables()函数分析

/*
 *Author  : DavidLin
 *Date    : 2014-11-22pm
 *Email   : linpeng1577@163.com or linpeng1577@gmail.com
 *world   : the city of SZ, in China
 *Ver     : 000.000.001
 *history :     editor      time            do
            1)LinPeng       2014-11-22      created this file!
            2)
*/

/*
 *释放addr对应的物理地址
 *free_page函数被free_page_tables()函数调用
 */
/*
 * Free a page of memory at physical address 'addr'. Used by
 * 'free_page_tables()'
 */
void free_page(unsigned long addr)
{
    if(addr < LOW_MEM) {                //如果是内核地址,直接退出
        return;                         //LOW_MEM = 1M,0-640KB是内核驻留区域
    }

    if(addr >= HIGH_MEMORY) {           //如果是最大物理地址之外,die
        panic("trying to free nonexistent page");
    }

    addr -= LOW_MEM;                    //获取主内存地址(以LOW_MEM处为起始0地址)
    addr >>= 12;                        //获取主内存管理数组偏移索引
                                        //mem_map是全局数组,用于管理主内存
    if(mem_map[addr]--) {               //首先执行if(mem_map[addr])判断,接着mem_map[addr]--
        return;                         //如果mem_map[addr] > 0,退出,表示物理页共享减一
    }
    mem_map[addr] = 0;                  //如果mem_map[addr] = 0,die
    panic("trying to free free page");
}



/*
 * 释放连续块,块必须4M对齐
 * exit()函数调用,相对的函数是copy_page_tables()
 */
/*
 * This function frees a continuos block of page tables, as needed
 * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks.
 */
int free_page_tables(unsigned long from, unsigned long size)
{
    unsigned long *pg_table;
    unsigned long *dir, nr;

    if(from & 0x3fffff) {               //4M对齐检测
        panic("free_page_tables called with wrong alignment");
    }

    if(!from) {                         //0地址是内核驻留地址,不允许释放
        panic("Trying to free up swapper memory space");
    }

    size = (size + 0x3fffff)>>22;       //如果是4.1M,size取整为2。

    dir  = (unsigned long *)((from>>20) & 0xffc); /* _pg_dir = 0 */
					//dir是页目录项,取线性地址高10位,
					//右移22位,因为每个目录项占4个字节,
					//所以>>22之后<<2
					//等于>>20

    for(; size-->0 ; dir++) {
        if(!(1 & *dir)) {               //如果页目录项未使用,跳过
            continue;
        }

        pg_table = (unsigned long *)(0xfffff000 & *dir);        //取页表项
        for(nr = 0; nr < 1024; nr++) {                          //每个页表项有1024个物理页
            if(1 & *pg_table) {                                 //位0等于1表示物理页有效
                free_page(0xfffff000 & *pg_table);              //释放物理页	
            }
            *pg_table = 0;                                      //页表项内容清零
            pg_table++;                                         //指向下一个页表					
        }
        free_page(0xfffff000 & *dir);                           //释放页表项
        *dir = 0;                                               //页目录项内容清零
    }
    invalidate();                                               //刷新高速缓存
    return 0;                                                   //返回0表示操作成功
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值