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

📄 pagealloc.c

📁 一个完整的GUI界面OS,单盘启动 实现了多线程、FAT32文件读写
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------------------------------------------------
//          Phy Page Alloc For FireXOS  1.10 
//
//          Version  1.10
//
//          Create by  xiaofan                                   2004.9.20
//
//          Update by xiaofan                                    2004.9.20
//------------------------------------------------------------------------------------------------------------------------

#include "PageAlloc.h"
#include "Console.h"
#include "BootMem.h"
#include "Page.h"
#include "Process.h"
#include "String.h"
#include "Traps.h"
#include "CTYPE.h"

static  unsigned long HIGHT_MEM=0;                          //内存高端地址
static  unsigned long LOW_MEM=0;                            //内存低端地址

static  PageStruct* mem_map;

unsigned long  PAGING_PAGES=0;
                          
//------------------------------------------------------------------------------------------
//
//
//     物理内存分页表扩展(其中0~4MB 页表已初始化)
//
//
//
//-------------------------------------------------------------------------------------------
unsigned long PhysicalPageTableExpand(unsigned long end_mem)
{
	unsigned long  page_table_num=0;
	unsigned long  page_residue_num=0;    //不足一页表的剩余页面数
	unsigned long  index;
	unsigned long  page_table_addr;
	
  ConsolePrintf("Expand the physical page table ");

	page_table_num=(end_mem-0x400000)/(4096*1024);

	page_residue_num=((end_mem-0x400000)%(4096*1024))/4096;

	if(page_residue_num) page_table_num+=1;


	page_table_addr=(unsigned long)BootMemMalloc(page_table_num*4096);

	//重新设置Kernel Page_Dir
	//重新设置 VM 0~4MB 为空把 0 ~ 4MB 的映射断开
	for(index=0;index<1;index++)     
	{
	  //*(unsigned long *)(PG_DIR_ADDR+index*4) = 0;
	}


	//设置Kernel Page_Dir
	//设置物理空间 0 ~ 4MB 1 个页表
  for(index=0x300;index<0x301;index++)     
	{
	  *(unsigned long *)(__va(PG_DIR_ADDR)+index*4) = (PG_TABLE_ADDR+(index-0x300)*4096)|7;
	}

  //设置Kernel Page_Dir
	//设置物理空间 4MB ~ end_mem   page_table_num 个页表
  for(index=0x301;index<0x301+page_table_num;index++)     
	{
	  *(unsigned long *)(__va(PG_DIR_ADDR)+index*4) = (__pa(page_table_addr)+(index-0x301)*4096)|7;
	}

	//ConsoleMsg("  Expand Mem First 4MB page_table = %08x\n",page_table_addr);

	//设置扩展物理页表映射到物理内存 4MB ~ end_mem
	if(page_residue_num)
	for (index=0;index<0x400*(page_table_num-1)+page_residue_num;index++)	        
	{
    *((unsigned long*)(page_table_addr+index*4)) = (0x400000+index*4096)|7;
	}
	else
	for (index=0;index<0x400*page_table_num;index++)	        
	{
    *((unsigned long*)(page_table_addr+index*4)) = (0x400000+index*4096)|7;
	}

	InvalidatePageDir(PG_DIR_ADDR);

	ConsolePrintOK();

	if(page_residue_num)
	return (page_table_num-1)*1024+page_residue_num;
	else 
	return page_table_num*1024;

}


//------------------------------------------------------------------------------------------
//
//
//     内存页面扫描,并输出结果
//
//
//
//-------------------------------------------------------------------------------------------
int PageManagerScan(void)
{
    int i,free=0;

    for(i=0;i<PAGING_PAGES;i++)
    if(!TestPageUsed(&mem_map[i])) free++;

		//ConsoleMsg("  Total %d pages to alloc %d pages free\n",PAGING_PAGES,free); 
		return free;
}


//------------------------------------------------------------------------------------------
//
//
//     内存分页初始化
//
//
//
//-------------------------------------------------------------------------------------------
void PageManagerInit(unsigned long end_mem)
{
    unsigned long i;
		unsigned long page_num=0;
		unsigned long low_page_num=0;

    HIGHT_MEM=__va(end_mem);

    
		//在扩展了物理内存页面之后就不能在访问低端内存了 3GB 以下
    page_num=PhysicalPageTableExpand(end_mem);

		ConsoleMsg("  Expand %ld physical pages  total %ld KB\n",page_num,page_num*4);
		ConsoleMsg("  Physical page table set at vitrual address %08x\n",PAGE_OFFSET+PG_TABLE_ADDR);


		page_num=(end_mem)/4096;

    ConsolePrintf("Malloc the mem_map array for page alloc");
		mem_map=(PageStruct*)BootMemMalloc(page_num*sizeof(PageStruct));
		ConsolePrintOK();

		ConsoleMsg("  The mem_map array base is %08x size is %d KB \n",mem_map,page_num*sizeof(PageStruct)/1024);

		BootMemEnd(&LOW_MEM);

		ConsoleMsg("  The low mem of alloc page is %08x\n",LOW_MEM);


		low_page_num=(__pa(LOW_MEM)/4096)+1;   //向高端4KB 对齐

    PAGING_PAGES=page_num;

	
		for(i=0;i<low_page_num;i++)
		{
        SetPageReferenced(&mem_map[i]);                  //将内核页设为在内存中
				SetPageUsed(&mem_map[i]);                        //将内核页设为被占用
				SetPageLocked(&mem_map[i]);                      //将内核页设为锁定
				mem_map[i].count=0;
		}

    
		for(i=low_page_num;i<page_num;i++)
		{
        SetPageReferenced(&mem_map[i]);                 //将分配页设为在内存中
				SetPageUnUsed(&mem_map[i]);                     //将分配页设为被未占用
				SetPageUnLocked(&mem_map[i]);                   //将分配页设为被未锁定
				mem_map[i].count=0;
		}
		
		    
		PageManagerScan();
		
			

}


//------------------------------------------------------------------------------------------
//
//
//     内存页面映射表,找到一个空闲的页面,并将该页面的实际物理内存清零
//
//
//
//-------------------------------------------------------------------------------------------
unsigned long GetFreePage(void)
{
      unsigned long i;

      for(i=0;i<PAGING_PAGES;i++)
      if(!TestPageUsed(&mem_map[i]))                     //若找到了一个空闲的页
      {
         SetPageUsed(&mem_map[i]);

				 mem_map[i].count++;

         i<<=12;                                         //i*4K 得到实际的页偏移地址
				 i=__va(i);
                                                         //以下代码将页面的实际的物理地址清零    
				 /*
         __asm__("std; \n\t"
                 "movl %%ecx,%%edx\n\t"
                 "movl $1024,%%ecx\n\t"                  //ecx计数器置1024
                 "leal 4092(%%edx),%%edi\n\t"  
                 "rep: stosl\n\t"
                 "movl %%edx,%%eax"
                 :"=a"(__res)                            //输出的结果
                 :"c"(i));                               //将i送入ecx
				 */
			   memset((void*)i,0,4096);

				 return i;
      }

			KernelPanic("No enough physical memory to get a free page ");
      return 0;
}


//------------------------------------------------------------------------------------------
//
//
//     内存页面映射表,找到n个空闲的连续页面,并将该页面的实际物理内存清零
//
//
//
//-------------------------------------------------------------------------------------------
unsigned long GetFreePages(int page_num)
{
      unsigned long i;
			unsigned long start,end;
      int           num=0;

			start=end=0;

      for(i=0;i<PAGING_PAGES;i++)
      if(!TestPageUsed(&mem_map[i]))                     //若找到了一个空闲的页
      {
				 if(num==0) start=i;
				 num++;
				 if(num>=page_num) 
				 {
					 end=i;
					 break;
				 }
			}

⌨️ 快捷键说明

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