您的位置:首页 > 运维架构 > Linux

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

2014-11-24 09:07 961 查看
/*
*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表示操作成功
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐