Virtual Memory Technology and Its Implementation code in the operating system, virtual memory of the Operating System
Virtual Memory is a widely used technology in modern operating systems.
The basic idea of virtual memory is that each process uses an independent logical address space. The memory is divided into multiple equal-Size Blocks, called pages ). Each page is a consecutive address. For a process, there seems to be a lot of logical memory space, some of which correspond to a piece of physical memory (called a page frame, usually with the same page size as the page frame ), there are also some maps that are not loaded into the memory on the hard disk. By introducing the logical address of a process, the process address space is separated from the actual storage space to increase the flexibility of storage management.
The basic concepts of address space and storage space are defined as follows:
Address Space: The target program compiled by the source program exists in the address range defined by it. This range is called address space. An address space is a set of logical addresses.
Storage space: a set of physical units that store a series of information in the primary storage. The number of these units is called a set of physical addresses.
There are three management methods derived from this:
Page-based storage management, segment-based storage management, and segment-based storage management. This section describes page-based storage.
When the webpage system is created, the operating system assigns a page box for all pages in the process. When a process is revoked, all the page boxes allocated to it are withdrawn. During the running of the program, if the process is allowed to dynamically apply for space, the operating system also needs to allocate a physical page for the space requested by the process. To complete these functions, the operating system must record the actual page box usage in the system memory. During process switching, the operating system also correctly switches the ing between two different process address spaces to the physical memory space. To understand how the operating system meets these requirements, we should first understand the page table technology. Let's take a look at the figure, which is reproduced from 51CTO:
An entry in a page table is called a page table entry. A page table entry records the ing between a virtual address and a physical address.
Since the page table is stored in the Memory, the program accesses the Memory at least twice each time it reads the Memory, it represents a hardware logical unit integrated into the CPU. It is mainly used to provide the CPU with the function of switching from a virtual address to a physical address, hardware provides a memory protection mechanism for the software). The memory access efficiency is greatly reduced. If the memory usage performance is poor, this reduction in efficiency will be more obvious. Therefore, how to minimize system consumption while giving full play to the advantages of MMU becomes an urgent problem.
As a result, TLB is generated. What is TLB? We call it a conversion bypass buffer, which is actually a set of relocation registers temporarily storing the conversion data in MMU. Since TLB is essentially a set of registers, it is easy to understand that it is much faster to access TLB than to access the page tables in the memory. Therefore, if all the content of the page table is stored in TLB, the access efficiency can be solved.
However, due to manufacturing costs and other restrictions, it is almost impossible to store all page tables in TLB. In this way, we can only store some of the most commonly used page tables in a limited capacity TLB to improve the MMU efficiency to a certain extent.
The theoretical basis for this method to produce results is the local principle of memory access. It means that the program has a higher probability of accessing the code that is close to the current position during execution. Therefore, theoretically, we can say that TLB stores most page table items that need to be used in the current time period, so it can greatly improve the running efficiency of MMU.
What we use here is the second-level page table technology. What is a second-level page table? That is, MMU uses the second-level Table query method. That is, the virtual address is used to index a part of the first table, then, search for the second table based on the content to determine the physical address. The first table is called a level-1 page table, and the second table is called a level-2 page table. The primary purpose of using the second-level lookup method is to reduce the memory space occupied by the page table, but the disadvantage is that it further reduces the addressing efficiency of the memory.
Well, the previous introduction is complete, the following is good, with the OS161 developed by Harvard University for teaching to implement VM, OS161 Based on MIP-I hardware.
Code on github: https://github.com/tian-jiang/OS161-VirtualMemory
First, let's take a look at the code. arch/mips/include/vm. h. The physical memory allocation is defined here
/* * MIPS-I hardwired memory layout: * 0xc0000000 - 0xffffffff kseg2 (kernel, tlb-mapped) * 0xa0000000 - 0xbfffffff kseg1 (kernel, unmapped, uncached) * 0x80000000 - 0x9fffffff kseg0 (kernel, unmapped, cached) * 0x00000000 - 0x7fffffff kuseg (user, tlb-mapped) * * (mips32 is a little different) */#define MIPS_KUSEG 0x00000000#define MIPS_KSEG0 0x80000000#define MIPS_KSEG1 0xa0000000#define MIPS_KSEG2 0xc0000000
The following figure shows the memory allocation.
This figure shows the physical memory allocation in OS161.
Let's start from scratch: man. c
1 /* Early initialization. */2 ram_bootstrap();3 .......4 5 /* Late phase of initialization. */6 vm_bootstrap();7 ........
When the operating system is started, raw_bootstrap () and vm_bootstrap () are called to start the vm management module. Where are these two functions defined and used? Let's look at the following code.
Include/vm. h and arch/mips/include/vm. h
/* Initialization function */void vm_bootstrap(void);
/* * Interface to the low-level module that looks after the amount of * physical memory we have. * * ram_getsize returns the lowest valid physical address, and one past * the highest valid physical address. (Both are page-aligned.) This * is the memory that is available for use during operation, and * excludes the memory the kernel is loaded into and memory that is * grabbed in the very early stages of bootup. * * ram_stealmem can be used before ram_getsize is called to allocate * memory that cannot be freed later. This is intended for use early * in bootup before VM initialization is complete. */void ram_bootstrap(void);paddr_t ram_stealmem(unsigned long npages);void ram_getsize(paddr_t *lo, paddr_t *hi);
The two functions are defined here, so what are the two functions doing?
vaddr_t firstfree; /* first free virtual address; set by start.S */static paddr_t firstpaddr; /* address of first free physical page */static paddr_t lastpaddr; /* one past end of last free physical page *//* * Called very early in system boot to figure out how much physical * RAM is available. */voidram_bootstrap(void){ size_t ramsize; /* Get size of RAM. */ ramsize = mainbus_ramsize(); /* * This is the same as the last physical address, as long as * we have less than 508 megabytes of memory. If we had more, * various annoying properties of the MIPS architecture would * force the RAM to be discontiguous. This is not a case we * are going to worry about. */ if (ramsize > 508*1024*1024) { ramsize = 508*1024*1024; } lastpaddr = ramsize; /* * Get first free virtual address from where start.S saved it. * Convert to physical address. */ firstpaddr = firstfree - MIPS_KSEG0; kprintf("%uk physical memory available\n", (lastpaddr-firstpaddr)/1024);}
/* * Initialise the frame table */voidvm_bootstrap(void){ frametable_bootstrap();}
/* * Make variables static to prevent it from other file's accessing */static struct frame_table_entry *frame_table;static paddr_t frametop, freeframe;/* * initialise frame table */voidframetable_bootstrap(void){ struct frame_table_entry *p; paddr_t firsta, lasta, paddr; unsigned long framenum, entry_num, frame_table_size, i; // get the useable range of physical memory ram_getsize(&firsta, &lasta); KASSERT((firsta & PAGE_FRAME) == firsta); KASSERT((lasta & PAGE_FRAME) == lasta); framenum = (lasta - firsta) / PAGE_SIZE; // calculate the size of the whole framemap frame_table_size = framenum * sizeof(struct frame_table_entry); frame_table_size = ROUNDUP(frame_table_size, PAGE_SIZE); entry_num = frame_table_size / PAGE_SIZE; KASSERT((frame_table_size & PAGE_FRAME) == frame_table_size); frametop = firsta; freeframe = firsta + frame_table_size; if (freeframe >= lasta) { // This is impossible for most of the time panic("vm: framemap consume physical memory?\n"); } // keep the frame state in the top of the useable range of physical memory // the free frame page address started from the end of the frame map frame_table = (struct frame_table_entry *) PADDR_TO_KVADDR(firsta); // Initialise the frame list, each entry corrsponding to a frame, // and each entry stores the address of the next free frame. // If the next frame address of this entry equals zero, means this current frame is allocated p = frame_table; for (i = 0; i < framenum-1; i++) { if (i < entry_num) { p->next_freeframe = 0; p += 1; continue; } paddr = frametop + (i+1) * PAGE_SIZE; p->next_freeframe = paddr; p += 1; }}
struct frame_table_entry { // address of next free frame size_t next_freeframe;};
Raw_bootstrap is used to check the amount of physical memory available during system initialization. While vm_bootstrap simply calls frametable_bootstrap (), while frametable_bootstrap () refers to paging the available physical memory, with a page size of 4 K, then, save the linked list of blank record pages in the memory and store them from the top of the free memory. Before storing them, you need to calculate the space required to store the frame table. Therefore, the size of the frame table is calculated before the code, and the linked list of the frame table is initialized later. Because it is empty during initialization, you can direct it to the address of the next page.
The vm initialization of the operating system is complete. How is the vm used? See the following.