Linux-0.11内核源码分析系列:内存管理get_empty_page()与put_page()函数分析
/*
*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)
*/
/*
* This function puts a page in memory at the wanted address.
* It returns the physical address of the page gotten, 0 if
* out of memory (either when trying to access page-table or
* page.)
*/
unsigned long put_page(unsigned long page,unsigned long address)
{
unsigned long tmp, *page_table;
/* NOTE !!! This uses the fact that _pg_dir=0 */
//页目录表从0地址开始是先决条件
if (page = HIGH_MEMORY)
printk("Trying to put page %p at %p\n",page,address);
//物理地址是主内存地址?否则发出警告
if (mem_map[(page-LOW_MEM)>>12] != 1)
printk("mem_map disagrees with %p at %p\n",page,address);
//检查主内存管理数组相应物理页索引值
//如果不是已经被申请次数为1
//的物理地址,发出警告
page_table = (unsigned long *) ((address>>20) & 0xffc);
//获取页目录项
//此处page_table代表页目录项
//页表是保存在页目录项中
//一个页目录项管理一个页表
//一个页表有1024个页表项
if ((*page_table)&1) //检查页表有效位P是否在内存中
page_table = (unsigned long *) (0xfffff000 & *page_table);
//页目录项所保存的页表有效
//获取页表
//将页表值存入页目录项,所以31-21位不清零
//此处page_table代表页表
else { //页目录项所保存的页表无效
if (!(tmp=get_free_page())) //申请一块空闲物理页保存页表
return 0; //如果失败,返回0
*page_table = tmp|7; //将页表地址保存到页目录项
page_table = (unsigned long *) tmp; //页表指针指向新申请的物理页
//此处page_table只用于
//页表项在页表中偏移地址计算
} //一个页表管理1024个页表项
//一个页表项对应4K物理地址
page_table[(address>>12) & 0x3ff] = page | 7;
//(addree>>12) & 0x3ff可以获取物理页(页表项)在页表中的偏移地址
//因为与0x3ff相与,即011,1111,1111B可以清除address中保存的页目录项的值
//page | 7表示用户级,可读写,页最低位P有效
/* no need for invalidate */
//因为只是更新页表,没有实际物理内容更新,不需要更新换高速缓存
return page; //返回物理页地址
}
//用于将线性地址address映射到实际物理页
void get_empty_page(unsigned long address)
{
unsigned long tmp;
if (!(tmp=get_free_page()) || !put_page(tmp,address)) {
//如果没有空闲物理页,die
//如果无法将申请的物理页挂载到线性地址中,die
free_page(tmp);/* 0 is ok - ignored */
//释放该物理页
oom();
//内存溢出,报错,死机
}
}
©著作权归作者所有:来自51CTO博客作者linpeng1577的原创作品,如需转载,请注明出处,否则将追究法律责任