How does x86 paging work?

后端 未结 2 1485
后悔当初
后悔当初 2020-11-22 09:47

This question is meant to fill the vacuum of good free information on the subject.

I believe that a good answer will fit into one big SO answer or at least in a few

2条回答
  •  天涯浪人
    2020-11-22 10:17

    Here's a very short, high-level answer:

    An x86 processor operates in one of several possible modes (roughly: real, protected, 64-bit). Each mode can use one of several possible memory addressing models (but not every mode can use every model), namely: real-mode addressing, segmented addressing, and flat-linear addressing.

    In the modern world, only flat-linear addressing in protected or 64-bit mode are relevant, and the two modes are essentially the same, with the main difference being the size of the machine word and thus the addressable amount of memory.

    Now, the memory addressing mode gives meaning to the memory operands of the machine instructions (such as mov DWORD PTR [eax], 25, which stores a 32-bit (aka dword) integer of value 25 into the memory whose address is stored in the eax 32-bit register). In flat-linear addressing, this number in eax is allowed to run over a single, contiguous range, from zero up to the maximal value (in our case that's 232 − 1).

    However, flat-linear addressing can be either paged or not paged. Without paging, the address directly refers to physical memory. With paging, the processor's memory management unit (or MMU) transparently feeds the desired address (now called a virtual address) into a lookup mechanism, the so-called page tables, and obtains a new value, which is interpreted as a physical address. The original operation now operates on this new, translated address in physical memory, even though the user only ever sees the virtual address.

    The key benefit of paging is that the page tables are managed by the operating system. Thus the operating system can modify and replace the page tables arbitrarily, such as when "switching tasks". It can keep a whole collection of page tables, one for each "process", and whenever it decides that a particular process is going to run on a given CPU, it loads the process's page tables into that CPU's MMU (each CPU has its own set of page tables). The result is that each process sees its own virtual address space which looks the same regardless of which physical pages were free when the OS had to allocate memory for it. It never knows about the memory of any other process, since it cannot access physical memory directly.

    Page tables are nested tree-like data structures stored in normal memory, written by the OS but read directly by hardware, so the format is fixed. They're "loaded" into the MMU by setting a special CPU control register to point to the top-level table. The CPU uses a cache called a TLB to remember lookups, so repeated accesses to the same few pages are much faster than scattered accesses, for TLB-miss reasons as well as the usual data cache reasons. It's common to see the term "TLB entry" used to refer to page table entries even when they aren't cached in the TLB.

    And in case you worry that a process might just disable paging or try and modify the page tables: This is not allowed, since x86 implements privilege levels (called "rings"), and user code executes at a privilege level that's too low to allow it to modify the CPU's page tables.

提交回复
热议问题