⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pagealloc.c

📁 一个完整的GUI界面OS,单盘启动 实现了多线程、FAT32文件读写
💻 C
📖 第 1 页 / 共 2 页
字号:
			else if(num>0)
			{
				num=0;
				start=0;
			}

			for(i=start;i<=end;i++)
			SetPageUsed(&mem_map[i]);

      start<<=12;                                         // i*4K 得到实际的页偏移地址
			start=__va(start);
                                                         //以下代码将页面的实际的物理地址清零    
			memset((void*)start,0,page_num*4096);
		  return start;
}

//------------------------------------------------------------------------------------------
//
//
//     释放某一页面  addr 要释放的页面的物理地址
//
//
//
//-------------------------------------------------------------------------------------------
int FreePage(unsigned long addr)
{
     if(addr<LOW_MEM) 
     {
        return -1;
     } 

     if(addr>HIGHT_MEM)
     {
        return -1;
     }
     
     addr=__pa(addr);
     addr>>=12;                                    //把addr转换成页面号

     if(TestPageUsed(&mem_map[addr]) && !TestPageLocked(&mem_map[addr])) 
		 {
			 //ConsoleWarning("  Free addr %08x mem_mep.conut =%d\n",__va(addr<<12),mem_map[addr].count);
			 mem_map[addr].count--;

			 if(mem_map[addr].count<=0)
			 {
				  mem_map[addr].count=0;
				  SetPageUnUsed(&mem_map[addr]);
					return 0;
			 }
			 else return mem_map[addr].count;
		 }

		 return -2;
}


//------------------------------------------------------------------------------------------
//
//
//     添加某一页面  的使用计数
//
//
//
//-------------------------------------------------------------------------------------------
void AddPageCount(unsigned long addr)
{
	  if(addr<LOW_MEM) 
    {
        return;
    } 
    if(addr>HIGHT_MEM)
    {
        return;
    }

		addr=__pa(addr);
    addr>>=12;                                    //把addr转换成页面号
    if(TestPageUsed(&mem_map[addr]) && !TestPageLocked(&mem_map[addr])) 
		{
			mem_map[addr].count++;
		}

}

//------------------------------------------------------------------------------------------
//
//
//     在指定的物理地址处放置一页面,即将某一页的地址索引放入页表的指定位置处
//
//     page 要放置的页面真实物理地址,address 要放置页面指针的页表地址(线性地址)
//
//-------------------------------------------------------------------------------------------
unsigned long PutPage(unsigned long pg_dir,unsigned long page,unsigned long address)
{
        unsigned long tmp,*page_table;
				unsigned long page_phy_addr;
        
		
        if(page<LOW_MEM || page>HIGHT_MEM)        //若是要放入页表的页地址不在可分配空间中则出错
        {
           ConsoleWarning("put page error out of the page memory space 2MB~8MB addr %08x page %08x\n",
						               address,page);
           return 0;
        }

				page_phy_addr=__pa(page);

       
        if(!TestPageUsed(&mem_map[page_phy_addr>>12]))
        {
           ConsoleWarning("put page error mem map disgrees with the page num addr %08x page %08x\n",
						               address,page);
           return 0;
        }


        page_table=(unsigned long *)(pg_dir+((address>>20)&0xffc)); //找到address对应的实际在页目录中的地址

				//ConsolePrintf("  page_table %08x *page_table %08x\n",page_table,*page_table);

        if((*page_table)&1)
				{
            page_table=(unsigned long *)(0xfffff000 & *page_table);    //address对应的页表指针,注意为物理地址
						page_table=(unsigned long *)__va((unsigned long)page_table);
						AddPageCount((unsigned long)page_table);

				}
        else                                                 //若对应的页表指针不存在,则申请一个页面来存放页表
        {
           if(!(tmp=GetFreePage()))                          //<----注意这里在VM释放时要释放其页表所占页面
					 {ConsoleWarning("put page error --- you do not have enough memory!\n");return 0;}

           *page_table=__pa(tmp)|7;                           //注意要把页表的物理地址放入页目录
            page_table=(unsigned long *)tmp;                  //找到一个空闲页面来放页表
						//page_table=(unsigned long *)__va((unsigned long)page_table);
        }

				//ConsolePrintf("  page_table %08x page_table[%d]=%08x\n",page_table,(address>>12)&0x3ff,page_phy_addr|7);
        
        page_table[(address>>12)&0x3ff]=page_phy_addr | 7;

        return page;                
}

extern int nr_read;
//------------------------------------------------------------------------------------------
//
//
//     缺页故障处理函数
//
//     
//
//-------------------------------------------------------------------------------------------
unsigned long NoPage(unsigned long address)
{
	   unsigned long page;
		 unsigned long put_page=0;
		 int i;

     if(!(page=GetFreePage()))
		 return 0;

		 for(i=0;i<MAX_PROCESS;i++)
			 if(proc[i].procFlag==P_RUN)
		 {
		    if(!(put_page=PutPage(__va(proc[i].procTss.cr3),page,address))) return 0;
		    else if(i>0) AddPageCount((unsigned long)put_page);
		 }


		 if(ProcCurrent->pid!=0)
		 {
         InvalidatePageDir(ProcCurrent->procTss.cr3);
		 }
		 else InvalidatePageDir(PG_DIR_ADDR);

		 //ConsolePrintf(" Get a Free Page %08x\n",page);
		 //if(!(put_page=PutPage(__va(PG_DIR_ADDR),page,address))) return 0;
     //InvalidatePageDir(PG_DIR_ADDR);
		 //ConsolePrintf("Proc %d PGD %08x Put a new page %08x at address %08x\n",
		 //              ProcCurrent->pid,ProcCurrent->procTss.cr3,put_page,address);
		 return put_page;

}

//------------------------------------------------------------------------------------------
//
//
//     已对齐页面拷贝
//
//     内存管理中最重要的一部分!!!
//
//-------------------------------------------------------------------------------------------
int  AlignPageTableCopy(unsigned long from_pg_dir,unsigned long to_pg_dir,
									      unsigned long from,unsigned long to,unsigned long size)
{
   unsigned long j=0;

	 unsigned long* from_page_table=NULL;
	 unsigned long* to_page_table=NULL;

	 unsigned long new_page_table;

	 unsigned long page_num=size/4096;                //要拷的页面总数

	 unsigned long phy_addr;                          


	 if((size % 4096)) page_num++;

	 while(1)
	 {
     from_page_table=(unsigned long *)(from_pg_dir+((from>>20)&0xffc));   //找到from对应的实际在页目录中的地址
	   to_page_table=(unsigned long *)(to_pg_dir+((to>>20)&0xffc));         //找到to对应的实际在页目录中的地址


		 from_page_table=(unsigned long *)(0xfffff000 & *from_page_table);    //from对应的页表指针,注意为物理地址
		 from_page_table=(unsigned long *)__va((unsigned long)from_page_table);



		  if(!((*to_page_table)&1)) 
		  {
           if(!(new_page_table=GetFreePage()))                                 //新建目标页面表
	         {ConsoleWarning("copy page error --- you do not have enough memory!\n");return -2;}

		        *to_page_table=((unsigned long) __pa((unsigned long)new_page_table)) | 7;
		   }

		    to_page_table = (unsigned long *)(0xfffff000 & *to_page_table);         //获得要目的页面表的地址指针
		    to_page_table = (unsigned long*)__va((unsigned long)to_page_table);


	

		 for(j=0;j<1024;j++)
	   {
		    phy_addr=from_page_table[(from>>12)&0x3ff] & 0xfffff000;
				to_page_table[(to>>12)&0x3ff]=phy_addr | 7;

				//ConsoleMsg("Proc %d Copy Page %08x FromDir %08x ToDir %08x From %08x To %08x\n",
				//	          ProcCurrent->pid,from_pg_dir,to_pg_dir,phy_addr,from,to);
		    page_num--;
				if(page_num==0) return 1;
				from+=4096;
				to+=4096;

				if(((from>>12)&0x3ff)==0) break;                                   //超出了1023 则到下一页表去
				if(((to>>12)&0x3ff)==0) break;
	   }
	 }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -