?
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); } }