Linux Memory Paging Management

Time: Column:Backend & Servers views:286

Memory is the primary storage of a computer. It allocates process space for storing data during process execution. This article will delve into the details of memory management, particularly the concepts of virtual memory and memory paging, starting from the physical characteristics of memory.

Memory

In simple terms, memory is like a shelf for storing data. It has a minimum storage unit, usually a byte. Memory addresses are used to sequentially number each byte's location, indicating where data is stored. These memory addresses start from 0 and increase linearly. For convenience, hexadecimal numbers represent memory addresses, such as 0x00000003 or 0x1A010CB0, where "0x" denotes hexadecimal notation.

Memory addresses have a limit, which is directly related to the width of the address bus. The CPU uses the address bus to specify the location of the data it wants to access. For example, Intel's 32-bit 80386 CPU has 32 pins for transmitting address information. These 32 pins correspond to binary bits, either 0 or 1, depending on the voltage level. This creates a 32-bit binary number, representing an address range from 0x00000000 to 0xFFFFFFFF in hexadecimal.

Memory uses Random Access Memory (RAM), meaning access time is independent of data location. Unlike memory systems like tapes, where location affects access time, RAM allows the CPU to retrieve data quickly, regardless of where it’s stored. This random access is crucial for memory’s role as the primary storage in computers.

Memory provides enough storage space to support both the operating system (kernel) and running processes. Even if a process requires more space than is available, memory can extend slightly to accommodate the process. However, memory data disappears when the system loses power, so computers still need external storage like hard drives for persistent data storage.


Virtual Memory

One of memory's main tasks is storing process-related data. Interestingly, despite this close relationship, processes cannot directly access memory. In Linux, a process cannot read or write to memory at an address like 0x1. Instead, processes use virtual memory addresses, which the operating system translates into actual physical memory addresses—a system known as virtual memory.

Each process has its own set of virtual memory addresses, which function similarly to physical memory addresses by providing a location index for data. Virtual memory addresses for different processes are independent. For example, two processes may both have the virtual address 0x10001000. The operating system translates these into different physical memory addresses (see Figure 1).

Linux Memory Paging Management

This design ensures that applications are unaware of physical memory. They operate purely on virtual memory, allowing the operating system to manage access. For instance, in a C program, printing the address of a variable will display its virtual memory address:

int v = 0;printf("%p", (void*)&v);

Virtual memory addresses prevent applications from freely accessing physical memory, enhancing security and stability. Processes cannot modify each other’s data, reducing the likelihood of errors. The operating system controls all memory access, ensuring processes are isolated in their own "kingdoms."

On the other hand, virtual memory also simplifies memory sharing. The OS can map the same physical memory region to multiple processes, allowing shared data access without copying. This is how shared libraries and kernel memory work—loaded once but accessed by multiple processes simultaneously.


Memory Paging

The separation of virtual and physical memory brings both security and efficiency to processes. However, translating between virtual and physical addresses consumes system resources. Since virtual memory is essential in modern multitasking systems, the OS needs to manage this translation efficiently.

A simple approach is to store all address mappings in a table. However, this method wastes space. For example, if every byte in 1GB of memory on a Raspberry Pi had its own mapping, the table would consume excessive space. Searching through so many entries would also slow down the system.

To solve this, Linux uses a paging system, where memory is managed in larger units called pages, typically 4KB each. You can check the page size on a Raspberry Pi with this command:

$getconf PAGE_SIZE

The result will be:

4096

This means each page contains 4096 bytes, or 4KB. Both physical memory and process spaces are divided into pages.

Paging greatly reduces the number of memory mappings. By working with pages rather than bytes, the number of entries is reduced by a factor of 4000. This makes virtual memory management feasible.

Within a page, addresses are sequential. Once a virtual page is mapped to a physical page, their data corresponds in order, meaning the lower 12 bits of the addresses are identical. This section of the address is called the offset, while the rest is the page number. The OS only needs to map the page numbers (see Figure 2).

Linux Memory Paging Management


Multi-Level Page Tables

Paging allows the OS to efficiently manage memory by mapping pages, but these mappings still need to be stored in memory. For each process, the OS maintains a page table. The simplest page table stores all mappings in a single linear list.

However, a process doesn’t use its entire address space, leaving many page table entries unused. To save space, Linux uses a multi-level page table. In a simplified example, the page number is split into two parts, and two layers of page tables map virtual addresses to physical addresses (see Figure 3).

Linux Memory Paging Management

The multi-level table works like splitting a phone number into an area code and local number. If a specific area code isn't used, no entries are stored for that region, saving memory. This method also allows the OS to scatter page tables across memory, using small, fragmented spaces.

In summary, Linux manages memory through paging, separating virtual and physical memory. This system allows the kernel to efficiently control memory allocation, improving application stability and security.


By understanding the concepts of paging and virtual memory, we gain insight into how Linux ensures process isolation and resource sharing, optimizing memory management.