[Linux kernel] memory management - virtual memory, segmentation, paging mechanism

Reprint please indicate the source: https://www.cnblogs.com/Ethan-Code/p/16613018.html

Virtual Memory

Why is there virtual memory?

  1. Let each process have an independent memory space , and each process has its own private page table, providing an environment that can execute multiple processes.
  2. Using the principle of program running locality, the memory space of the process is allowed to exceed the physical memory size .
  3. The permission attribute of the page is maintained in the page table, making memory access more secure .

If there is no virtual memory, there will be a problem that the process space is not isolated. For example, process A will rewrite the content of process B and cause process B to crash. And there will be problems of memory efficiency and insufficient memory. The physical memory is limited. If the process is sleeping, the unused memory still occupies the physical memory, and the new process may fail to start due to insufficient memory.

The mapping of physical memory to virtual memory is implemented by the hardware MMU (Memory Management Unit). If there is no MMU, for example, there is no virtual memory on the single-chip microcomputer, and multiple programs run on it, the memory space of each program is not independent. If the same address is accessed, it will directly affect the operation of other programs and cause the program to crash.

Hence the conclusion:

  • Only multi-threading can be run on the single-chip microcomputer, and the thread is the basic unit of scheduling
  • To realize a multi-process environment, MMU needs to be added to provide a virtual memory environment. A process is the basic unit of resource allocation.

memory segmentation

When there is no segmentation, the swapping in and out of memory is based on the entire process memory space, which is very time-consuming and the utilization rate of memory is not high.

Under memory segmentation, a program is composed of several logical segments, such as code segment, data segment, stack segment, and heap segment.

Different segments have different attributes, so these segments are separated in the form of Segmentation.

The virtual address under the segmentation mechanism consists of two parts, the segment selection factor and the offset within the segment.

  • The segment selector is stored in the segment register. The most important thing in the segment selector is the segment number, which is used as the index of the segment table. The segment table stores the segment's base address, segment boundaries, and privilege levels.
  • The intra-segment offset in the virtual address should be between 0 and the segment limit. If the intra-segment offset is legal, add the segment base address to the segment offset to obtain the physical memory address.

Address mapping process under memory segmentation:

  • A virtual address consists of a segment selector and a segment offset
  • Find the corresponding segment descriptor from the segment table through the segment number in the segment selector
  • The segment base address is provided in the segment descriptor, plus the segment offset on the virtual address to obtain the physical address

Disadvantages:

  • generate external memory fragmentation
  • Inefficient memory swapping

paging

Paging is to cut the entire virtual and physical memory space into segments of fixed size. Such a continuous and fixed-size memory space is called a page. Under Linux, the size of each page is 4KB.

Mapping between virtual addresses and physical addresses through page tables

The page table is stored in memory, and the memory management unit (MMU) does the work of converting virtual memory addresses into physical addresses.

When the virtual address accessed by the process cannot be found in the page table, the system will generate a page fault exception, enter the system kernel space to allocate physical memory, update the process page table, and finally return to the user space to resume the operation of the process.

Paging is adopted, since the memory space is pre-divided, and the pages are closely arranged, so there will be no external fragmentation.

Disadvantages:

  • generate internal memory fragmentation

Swap in and out:

The paging method makes it no longer necessary to load the program into physical memory all at once when loading the program. Only when the program needs to use the instructions and data in the corresponding virtual memory page, it is loaded into the physical memory.

Under the paging mechanism, the virtual address is divided into two parts, the page number and the offset within the page. The page number is used as the index of the page table, and the page table contains the base address of the physical memory where each page of the physical page is located. The combination of the base address and the offset in the page forms the physical memory address.

Three steps for a memory address translation:

  • Divide the virtual memory address into page numbers and offsets;
  • According to the page number, query the corresponding physical page number from the page table;
  • Take the physical page number directly and add the previous offset to get the physical memory address.

multi-level page table

Multi-level page table saves memory: the page table needs to cover the entire virtual address space, and the non-hierarchical page table needs more than 1 million page table entries to map, while the second-level paging only needs 1024 page table entries.

To give a specific example: VA stands for virtual address, and PA stands for physical address.

VA is divided into 3 segments

mmu_table[VA1][VA2] + VA3 = PA

Equivalent practice

VA =0xC1203040;
VA1 = 0xC12;
VA2 = 0x03;
VA3 = 0x40;
mmu_table = 0x40004000 (PA);
mmu_table[0xC12] = ((u32*)0x40004000)[0xC12] 
                 = 0x41224000 (PA);
mmu_table[0xC12][0x03] = ((u32*)0x41224000)[0x03]
                       = 0x42240000 (PA);
mmu_table[0xC12][0x03] + 0x40 = 0x42240040(PA);

For 64-bit systems, two-level paging is definitely not enough, so it becomes a four-level directory, which are:

  • Global page directory entry PGD (Page Global Directory);
  • The upper page directory item PUD (Page Upper Directory);
  • The middle page directory item PMD (Page Middle Directory);
  • Page table entry PTE (Page Table Entry);

page table cache

There is a Cache in the CPU that stores page table entries most frequently accessed by programs, which is TLB (Translation Lookaside Buffer), which is usually called page table cache, forwarding bypass cache, and fast table.

Inside the CPU chip, the memory management unit (Memory Management Unit) chip is packaged, which is used to complete address translation and TLB access and interaction.

With the TLB, the CPU will first check the TLB when addressing, and if it is not found, it will continue to check the regular page table.

segment page memory management

Segment first and then page, the address structure consists of three parts: segment number, page number in the segment and displacement in the page.

The data structure used for segment page address translation is a segment table for each program, and a page table is established for each segment. The address in the segment table is the starting address of the page table, and the address in the page table is a certain page physical page number

To obtain the physical address in segment page address translation, three memory accesses are required:

  • Access the segment table for the first time to get the start address of the page table;
  • Access the page table for the second time to get the physical page number;
  • The third time combines the physical page number with the displacement within the page to obtain the physical address.

Use Liangxu's picture:

memory management

In the Linux operating system, the virtual address space is divided into two parts: kernel space and user space.

The kernel address in each virtual memory is actually associated with the same physical memory

Division of virtual space

User space memory, from low to high, is 6 different memory segments:

  • Program file segment (.text), including binary executable code;
  • The initialized data segment (.data), including static constants;
  • Uninitialized data segment (.bss), including uninitialized static variables;
  • Heap segments, including dynamically allocated memory, grow upwards from low addresses;
  • The file mapping segment, including dynamic library, shared memory, etc., grows upward from the low address (related to the hardware and kernel version (opens new window));
  • The stack segment, including local variables and the context of function calls, etc. The stack size is fixed, typically 8 MB. Of course, the system also provides parameters so that we can customize the size;

Memory for heap and file-mapped segments is allocated dynamically. For example, using malloc() or mmap() of the C standard library, you can dynamically allocate memory in the heap and file mapping segments respectively.

Good article recommendation: graphic operating system

Guess you like

Origin blog.csdn.net/weixin_45636061/article/details/127184676