1. Virtual Memory

When you double-click a program containing a sequence of instructions, a process is created. The Windows operating system provides each new process created with its own private memory address space (called the process memory). The process memory is a part of virtual memory; virtual memory is not real memory, but an illusion created by the operating system's memory manager. It is because of this illusion that each process thinks that it has its own private memory space. During runtime, the Windows memory manager, with the help of hardware, translates the virtual address into the physical address (in RAM) where the actual data resides; to manage the memory, it pages some of the memory to the disk. When the process's thread accesses the virtual address that is paged to the disk, the memory manager loads it from the disk back to the memory. The following diagram illustrates two processes, A and B, whose process memories are mapped to the physical memory while some parts are paged to the disk:

Since we normally deal with virtual addresses (the ones that you see in your debugger), we will keep physical memory out of the discussion for the rest of the chapter. Now, let's focus on virtual memory. Virtual memory is segregated into process memory (process space or user space) and kernel memory (kernel space or system space). The size of the virtual memory address space depends on the hardware platform. For example, on a 32-bit architecture, by default, the total virtual address space (for both process and kernel memory) is a maximum of 4 GB. The lower half (lower 2 GB), ranging from 0x00000000 through 0x7FFFFFFF, is reserved for user processes (process memory or user space), and the upper half of the address (upper 2 GB), ranging from 0x80000000 through 0xFFFFFFFF, is reserved for kernel memory (kernel space).

On a 32-bit system, out of the 4 GB virtual address space, each process thinks that it has 2 GB of process memory, ranging from 0x00000000 - 0x7FFFFFFF. Since each process thinks that it has its own private virtual address space (which ultimately gets mapped to physical memory), the total virtual address gets much larger than the available physical memory (RAM). The Windows memory manager addresses this by paging some of the memory to the disk; this frees the physical memory, which can be used for other processes, or for the operating system itself. Even though each Windows process has its own private memory space, the kernel memory is, for the most part, common, and is shared by all the processes. The following diagram shows the memory layout of 32-bit architecture. You may notice a 64 KB gap between the user and kernel space; this region is not accessible and ensures that the kernel does not accidentally cross the boundary and corrupt the user-space. You can determine the upper boundary (last usable address) of the process address space by examining the symbol MmHighestUserAddress, and the lower boundary (first usable address) of the kernel space by querying the symbol MmSystemRangeStart with a kernel debugger such as Windbg:

Even though the virtual address range is the same for each process (x00000000 - 0x7FFFFFFF), both the hardware and Windows make sure that the physical addresses mapped to this range are different for each process. For instance, when two processes access the same virtual address, each process will end up accessing a different address in the physical memory. By providing private address space for each process, the operating system ensures that processes do not overwrite each other's data.

The virtual memory space need not always be divided into 2 GB halves; that is just the default setup. For example, you can enable a 3 GB boot switch by using the following command, which increases the process memory to 3 GB, ranging from 0x00000000 - 0xBFFFFFFF; the kernel memory gets the remaining 1 GB, from 0xC0000000 - 0xFFFFFFFF:

bcdedit /set increaseuserva 3072

The x64 architecture provides much larger address space for both the process and kernel memory, as shown in the following diagram. On x64 architecture, the user space ranges from 0x0000000000000000 - 0x000007ffffffffff, and the kernel space from 0xffff080000000000 and above. You may notice a huge address gap between the user-space and the kernel space; this address range is not usable. Even though, in the following screenshot, the kernel space is shown as starting from 0xffff080000000000, the first usable address in the kernel space starts at ffff800000000000. The reason for this is that all addresses used in x64 code must be canonical. An address is said to be canonical if it has the bits 47-63 either all set or all clear. Attempting to use a non-canonical address results in a page fault exception:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.230.82