Memory management – linear space, system space

?
2. Linear memory management

The 32-bit memory space is 4G. Except for some reserved for hardware and some special purposes, the remaining first 2G is allocated to applications and used separately by different programs (user mode), and the last 2G is allocated to the system. Shared by all programs (core state). Therefore, two management lists need to be established.

The storage location of the system memory management sequence table is determined when the kernel file is compiled, and there is no need to apply for additional space. Here you can see the benefits of compiling kernel files into PE files.

Custom linear space list:

Start address End address Size Description
0 0x000FFFFF 1M Reserved
0x00100000 0x7FFFFFFFF 2G-1M User space
0x80000000 0x803FFFFF 4M Free space
0x80400000 0x80412FFF 1.2M Kernel Image
0x80413000 0x80417FFF 16K System stack
0x80418000 0x80419FFF 8K Physical memory map
0x8041A000 0xB0000000 783M Free space
0xC0000000 0xC03FFFFF 4M Page directory, page table

The code is completed by three functions: mem_sys_virtual_init, mem_virtual_alloc, and mem_virtual_alloc. Divide the memory into several blocks, label each block with attributes, and find the appropriate block when you need to apply for it, or split the block into small blocks. The attributes of the preceding and following blocks are searched when released, and they are merged when free.

//Initialization of system memory management sequence table
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 image, the file has several segments, and the inner segments are initialized. Merge a paragraph here
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;
//kernel stack
pmbi[1].BaseAddress=MbiSys[0].BaseAddress + size;
pmbi[1].AllocationBase=MbiSys[1].BaseAddress;
pmbi[1].RegionSize=0x4000; //This value should be synchronized with the value in line 239 of osloader.asm, 16K kernel stack
pmbi[1].AllocationProtect=0;
pmbi[1].State=MEM_IMAGE;

//Physical memory map
pmbi[2].BaseAddress=MbiSys[1].BaseAddress + MbiSys[1].RegionSize;
pmbi[2].AllocationBase=MbiSys[2].BaseAddress;
pmbi[2].RegionSize=0x2000; // + 8K physical memory map
pmbi[2].AllocationProtect=0;
pmbi[2].State=MEM_PRIVATE;
\t//free space
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 space is used for memory paging
//Reserved, used to store memory management data
pmbi[4].BaseAddress=(PVOID)0xC0000000;
pmbi[4].AllocationBase=MbiSys[4].BaseAddress;
pmbi[4].RegionSize=0x400000;
pmbi[4].AllocationProtect=0;
pmbi[4].State=MEM_RESERVE;
//used to end
pmbi[5].BaseAddress=(DWORD)MbiSys;
pmbi[5].AllocationBase=1;
pmbi[5].RegionSize=0;
pmbi[5].AllocationProtect=0;
pmbi[5].State=MEM_RESERVE;
}

//Apply for linear space and allocate it in segments of 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);
 //Traverse
do
{
//The current block is free and the current block >= required
if((pmbi->State==MEM_FREE) & amp;(pmbi->RegionSize>=numbytes))
{
//1. Current block first address = required, save the current pointer and will not change it.
//2. If the current block first address < or > is required, the current pointer will be saved and will not be changed.
if(pmbi->BaseAddress==lpAddress)
{//
rMbi=pmbi;
if(rMbi->RegionSize==numbytes)
{//Current block size = required
//Modify properties directly,
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);
//After the above loop is completed, pmbi is the last block and rMbi is the divisible block.

switch(count)
{
case 1: //The first address of the current block = required, and the current block size > required
change2:
//The block after rMbi is moved back one block, rMbi is divided into two blocks, and the previous block is returned.
while(pmbi != rMbi)
{
pmbi[1]=*pmbi;
pmbi--;
}
pmbi + + ;//Here pmbi=back block, rMbi is front block
//rMbi size and attributes change, the size of the subsequent block needs to be changed, the first address
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 Current block first address >required
//Split into two pieces, return to the previous piece, move backward + create a new piece
printf("rmbi>lp \
 ");
goto change2;
}
else
{//2.2 Current block first address <required

if((DWORD)(rMbi->BaseAddress) + rMbi->RegionSize==(DWORD)(lpAddress) + numbytes)
{ //2.2.1. If the back block can meet the needs, divide it into two blocks, return the back block, move back + create a new block
while(pmbi != rMbi)
{
pmbi[1]=*pmbi;
pmbi--;
}
pmbi++;
//The front block only needs to change the size, and the back block needs to change the size, first address, and attributes.
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) & amp;((DWORD)rMbi->BaseAddress + rMbi->RegionSize>(DWORD)lpAddress + numbytes))
{//2.2.2 The middle block can be divided into three pieces, return the middle block, move backward + create a new second block
while(pmbi!=rMbi)
{
pmbi[2]=pmbi[1];
pmbi--;
}
pmbi++;
//Second block, size=state

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

//Third block
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;


//First block, change the size to
rMbi->RegionSize=(DWORD)lpAddress-(DWORD)rMbi->AllocationBase;

pmbi--;
//return pmbi->AllocationBase;
pmem=pmbi->BaseAddress;
goto funcover;
}
else
{//2.2.3, although the required address is currently, the size cannot be satisfied, so it is divided into two blocks, returns to the previous block, moves backward + creates a new block
goto change2;
}
}
//case 2:
}//switch(count)
funcover:
print_farmat_msg("mem_virtual_alloc :%x,%x,%x\
",pMbiBase,numbytes,pmem);
returnpmem;
}
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)
{
//Check the before and after blocks, whether they need to be merged, and move the useless blocks
prevmbi=(currentMbi-1);
nextmbi=(currentMbi + 1);
if(prevmbi->State==MEM_FREE)
{//Move one position forward from the current block, and see if the next block can be merged later.
prevmbi->RegionSize + =currentMbi->RegionSize;
movecount=1;
}
if(nextmbi->State==MEM_FREE)
{
if (movecount==1)
{//The front block + the back block can be merged
prevmbi->RegionSize + =nextmbi->RegionSize;
movecount=2;
}
else
{//Only the last block can be merged
currentMbi->RegionSize + =nextmbi->RegionSize;
currentMbi=nextmbi;
movecount=1;
}
}
// case 0: //Cannot merge forward or backward
// case 1,2:// may be forward or backward
nextmbi=(currentMbi + movecount);
do
{
*currentMbi=*nextmbi;
currentMbi + + ;
nextmbi++;
}while((PDWORD)nextmbi->AllocationBase!=1);
}
}