/*    *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 < LOW_MEM || 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();                //内存溢出,报错,死机	}}