内存管理——线性空间,系统空间


二、线性内存管理

       32位的内存空间是4G,除开些保留的、给硬件的、还有一些特殊用途的将,剩余的前2G分给应用程序,由不同的程序单独使用(用户态),后2G分给系统由所有程序共享(核心态)。因此需要建立两个管理列表。       

     系统内存管理顺序表由内核文件编译时决定存放位置,不用额外申请空间。在这里可以体现将内核文件编译成PE文件的好处。

自定义的线性空间列表:

开始地址   结束地址    大小         说明  
 0x000FFFFF  1M  保留    
0x00100000    0x7FFFFFFF    2G-1M用户空间    
0x80000000    0x803FFFFF    4M  自由空间    
0x80400000    0x80412FFF   1.2M   内核映像    
0x80413000    0x80417FFF16K     系统栈    
0x80418000  0x80419FFF     8K    物理内存map    
0x8041A000 0xB0000000783M     自由空间    
0xC00000000xC03FFFFF 4M  页目录、页表    

代码由mem_sys_virtual_init,mem_virtual_alloc,mem_virtual_alloc三个函数完成。将内存分成若干块,每块标注属性,需要申请时找到合适的块,或者从大块中分割小块出来。释放时查找前后块的属性,都为空闲时合并。

//系统内存管理顺序表初化
void mem_sys_virtual_init(PMEMORY_BASIC_INFORMATION pmbi)
{


	DWORD size=((PIMAGE_DOS_HEADER)0x80400000)->e_lfanew+0x80400000;
	size=((PIMAGE_NT_HEADERS)size)->OptionalHeader.SizeOfImage;
	//oskrnl映像,文件有几个段,初始化内处段。此处合并一段
	pmbi[0].BaseAddress=(PVOID)0x80400000;
	pmbi[0].AllocationBase=MbiSys[0].BaseAddress;
	pmbi[0].RegionSize=size;
	pmbi[0].AllocationProtect=PAGE_EXECUTE_WRITECOPY;
	pmbi[0].State=MEM_COMMIT;
	pmbi[0].Type=MEM_IMAGE;
	//内核栈
	pmbi[1].BaseAddress=MbiSys[0].BaseAddress+size;
	pmbi[1].AllocationBase=MbiSys[1].BaseAddress;
	pmbi[1].RegionSize=0x4000; //此值应与 osloader.asm 239行的值同步,16K内核栈
	pmbi[1].AllocationProtect=0;
	pmbi[1].State=MEM_IMAGE;

	//物理内存map
	pmbi[2].BaseAddress=MbiSys[1].BaseAddress+MbiSys[1].RegionSize;
	pmbi[2].AllocationBase=MbiSys[2].BaseAddress;
	pmbi[2].RegionSize=0x2000; //+8K物理内存map
	pmbi[2].AllocationProtect=0;
	pmbi[2].State=MEM_PRIVATE;
	//自由空间
	pmbi[3].BaseAddress=MbiSys[2].BaseAddress+MbiSys[2].RegionSize;
	pmbi[3].AllocationBase=MbiSys[3].BaseAddress;
	pmbi[3].RegionSize=0xB0000000-(DWORD)(MbiSys[3].BaseAddress);
	pmbi[3].AllocationProtect=0;
	pmbi[3].State=MEM_FREE;
	//0xC0000000-0xC0400000 4m 空间用于内存分页
	//保留,用于存放内存管理数据
	pmbi[4].BaseAddress=(PVOID)0xC0000000;
	pmbi[4].AllocationBase=MbiSys[4].BaseAddress;
	pmbi[4].RegionSize=0x400000;
	pmbi[4].AllocationProtect=0;
	pmbi[4].State=MEM_RESERVE;
	//用于结束
	pmbi[5].BaseAddress=(DWORD)MbiSys;
	pmbi[5].AllocationBase=1;
	pmbi[5].RegionSize=0;
	pmbi[5].AllocationProtect=0;
	pmbi[5].State=MEM_RESERVE;
}

//申请线性空间,以4K为单位分段分配
void *mem_virtual_alloc(PMEMORY_BASIC_INFORMATION pMbiBase,LPVOID lpAddress,
		DWORD numbytes,DWORD state,DWORD flProtec)
{

	PMEMORY_BASIC_INFORMATION pmbi=pMbiBase;
	PMEMORY_BASIC_INFORMATION rMbi=0;
	DWORD count=0;
	void* pmem=NULL;
	_ALIGN(numbytes,4);
 //遍历
	do
	{
		//当前块是空闲的,并且当前块>=需要的
		if((pmbi->State==MEM_FREE)&(pmbi->RegionSize>=numbytes))
		{
			//1、当前块首地址=需要,保存当前指针,不再变更
			//2、当前块首地址 < 或>需要,保存当前指针,不再变更
			if(pmbi->BaseAddress==lpAddress)
			{//
				rMbi=pmbi;
				if(rMbi->RegionSize==numbytes)
				{//当前块大小=需要
					//直接修改属性,
					rMbi->State=state;
					//return rMbi->BaseAddress;
					pmem=rMbi->BaseAddress;
					goto funcover;
				}
				count=1;
			}
			else if(rMbi==NULL)
			{
				rMbi=pmbi;
				count=2;
			}
		}
		pmbi++;
	}while ((DWORD)pmbi->AllocationBase!=1);
//上面循环完后,pmbi为最后一个块,rMbi为可分割的块

	switch(count)
	{
	case 1: //当前块首地址=需要,并且当前块大小>需要
		change2:
		//rMbi之后的块后移一块,rMbi分成两块,返回前块,
		while(pmbi != rMbi)
		{
			pmbi[1]=*pmbi;
			pmbi--;
		}
		pmbi++;//此处pmbi=后块,rMbi为前块
		//rMbi大小、属性改变,后块需改变大小 ,首地址
		pmbi->BaseAddress=(void*)((DWORD)rMbi->BaseAddress+numbytes);
		pmbi->AllocationBase=pmbi->BaseAddress;
		pmbi->AllocationProtect=rMbi->AllocationProtect;
		pmbi->RegionSize=rMbi->RegionSize-numbytes;
		pmbi->State=rMbi->State;
		rMbi->RegionSize=numbytes;
		rMbi->State=state;
		rMbi->AllocationProtect=flProtec;
		//return rMbi->BaseAddress;
		pmem=rMbi->BaseAddress;
		goto funcover;
		break;
	case 2:
		if(rMbi->BaseAddress>lpAddress)
		{//2.1当前块首地址 >需要
			//分成两块,返回前块,后移+新建一块
			printf("rmbi>lp \n ");
			goto change2;
		}
		else
		{//2.2当前块首地址 <需要

			if((DWORD)(rMbi->BaseAddress)+rMbi->RegionSize==(DWORD)(lpAddress)+numbytes)
			{	//2.2.1、如果后块能满足需要,则分成两块,返回后块,后移+新建一块
				while(pmbi != rMbi)
				{
					pmbi[1]=*pmbi;
					pmbi--;
				}
				pmbi++;
				//前块只需要改变大小 ,后块需将大小、首地址,属性改变
				rMbi->RegionSize-=numbytes;

				pmbi->RegionSize=numbytes;
				pmbi->BaseAddress=lpAddress;
				pmbi->AllocationBase=lpAddress;
				pmbi->State=state;
				pmbi->AllocationProtect=flProtec;
				//return pmbi->BaseAddress;
				pmem=pmbi->BaseAddress;
				goto funcover;
			}
			else if((rMbi->BaseAddress<lpAddress)&((DWORD)rMbi->BaseAddress+rMbi->RegionSize>(DWORD)lpAddress+numbytes))
			{//2.2.2 中间块能满足分成三块,返回中间块,后移+新建二块
				while(pmbi!=rMbi)
				{
						pmbi[2]=pmbi[1];
						pmbi--;
				}
				pmbi++;
				//第二块,大小=state

				pmbi->AllocationBase=lpAddress;
				pmbi->BaseAddress=lpAddress;
				pmbi->State=state;
				pmbi->RegionSize=numbytes;
				pmbi->AllocationProtect=flProtec;

				//第三块
				pmbi++;
				pmbi->AllocationBase=(void*)((DWORD)lpAddress+numbytes);
				pmbi->BaseAddress=pmbi->AllocationBase;
				pmbi->State=MEM_FREE;
				pmbi->RegionSize=(DWORD)rMbi->RegionSize-((DWORD)lpAddress-	(DWORD)rMbi->BaseAddress)-numbytes;
				pmbi->AllocationProtect=0;


				//第一块,将大小变为
				rMbi->RegionSize=(DWORD)lpAddress-(DWORD)rMbi->AllocationBase;

				pmbi--;
				//return pmbi->AllocationBase;
				pmem=pmbi->BaseAddress;
				goto funcover;
			}
			else
			{//2.2.3 ,虽然需要的地址在当前,但大小无法满足,分成两块,返回前块,后移+新建一块
				goto change2;
			}
		}
		//case 2:
	}//switch(count)
	funcover:
	 print_farmat_msg("mem_virtual_alloc :%x,%x,%x\n",pMbiBase,numbytes,pmem);
	 return pmem;
}
void mem_vitrual_free(PMEMORY_BASIC_INFORMATION pmbi,LPVOID lpAddress)
{
	PMEMORY_BASIC_INFORMATION currentMbi,pMbi=pmbi,prevmbi,nextmbi;
	int movecount=0;
	do
	{
		if (pMbi->BaseAddress==lpAddress)
		{
			currentMbi=pMbi;
			currentMbi->State=MEM_FREE;
			break;
		}
	}while((DWORD)pMbi->AllocationBase!=1);
	if(currentMbi !=0)
	{
		//检查前后块,是否需要合并,并移动除无用的块
		prevmbi=(currentMbi-1);
		nextmbi=(currentMbi+1);
		if(prevmbi->State==MEM_FREE)
		{//从当前块开始前移1个位置,后面再看能不能合并后块,
			prevmbi->RegionSize+=currentMbi->RegionSize;
			movecount=1;
		}
		if(nextmbi->State==MEM_FREE)
		{
			if (movecount==1)
			{//前块+后块都可以合并
				prevmbi->RegionSize+=nextmbi->RegionSize;
				movecount=2;
			}
			else
			{//只有后块可合并
				currentMbi->RegionSize+=nextmbi->RegionSize;
				currentMbi=nextmbi;
				movecount=1;
			}
		}
	//		case 0: //不能向前也不能向后合并
	//		case 1,2://可能向前也可能向后
		nextmbi=(currentMbi+movecount);
		do
		{
			*currentMbi=*nextmbi;
			currentMbi++;
			nextmbi++;
		}while((PDWORD)nextmbi->AllocationBase!=1);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麻雀123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值