How Virtual Memory works

Throughout this article we’ll take a look at which problems Virtual Memory (VM onward) solves and how it actually maps into RAM

What VM actually does is add a level of indirection between Virtual Program Addresses and Physical Addresses (RAM). Virtual program addresses would map directly into RAM if it wasn’t for this process. Now, that’s a lot of jargon, I know, so let’s look at the problems VM solves and you will start to see the big picture of how it works.

The first thing VM solves is it allow us to map memory to disk, the hard drive. Programs need RAM space to run, but that is very limited, so this allows us to use some disk space to augment the ammount of memory in which our program runs. The second thing it does is it increases security. Programs can’t access each other’s information. And third, it helps us avoid memory fragmentation. Let’s tackle each one!

Map Memory to Disk

This first one is not that complicated. Imagine your program needs 4GB of memory to run, but you only have 2GB free for use. VM gives this program some virtual memory, it tells it ‘sure, I got your 4GB, you can run no prob’, when in reality it is using the 2GB available and maps, stores, the other 2GB on disk. Whenever your program needs something from RAM that is already in there, the VM delivers it; when the data your program needs is actually on disk, the VM opens up some space in RAM (from something your program is not currently using) and gets the data requested to the RAM so that your program can access it. Now, why wouldn’t we just use disk space for all of this? The thing is reading from disk is one thousand times slower than reading from RAM. So that’s why we need to be constantly maping back to RAM. This speed issue will be addressed (no pun intended) at the end of this article.

Increase Security

Let’s change scenario. Now you have two programs running on your PC and both are trying to write data to the same physical memory address, like this:

Each program is just concerned with accessing address 1024, they don’t know, nor should they, what other programs are doing on that address. What the VM does is map, for each program, the ammount of memory needed and then manage it. Each map has a specific ammount of physical memory aloted to it. So, if two programs have to interact with the same address number, they would be doing so in the mapped addresses, not the physical ones. In this example, each program would have the same memory address asigned, but the map of each would have a different physical address aloted, that way both programs would technically be doing what they are programmed to do, but with the VM and not the RAM, and both could run at the same time without messing with other program’s data.

Avoid Memory Fragmentation

Say you have 4GB of RAM, and a program that needs 2GB of contiguous memory starts running. The problem is that it runs not from the start of the memory but right in the middle. To simplify it, imagine four contiguous slots (1, 2, 3 and 4) of memory and your program takes the two slots in the middle (takes 2 and 3), leaving the other slots separated from each other (1 and 4). So far nothing bad has happened, but say you need to run another progamm that also needs 2GB of contiguous memory, there is none, since what is left has been fragmented.

Since VM is based on indirection, it can provide for your program 2GB of contiguous memory (Program 3 in the slide) and reference two fragmented slots in the physical memory, allowing your program to run without any issues.

So, these are all pretty important issues, but how does any of this works? To understand the just-big-pictured solutions delineated so far, it’s important to understand how the mapping actually works. We will start by understanding Page Tables, which are tables that store the Virtual Address of each entry and its corresponding Physical Address. So if a program tries to access something with its Virtual Address, the map knows its corresponding Physical Address. Think of it as a dictionary, you need to know how to say tomato in Spanish, you look it up and you get tomate. Now, these are called tables for a reason. It would take way to much space to save each one of these records, one by one, so we save a block of them in and reference that block. Back to the dictionary example, if you need to say ‘Hi, how’s your day’, it would be a pain to find each word, so you get a phrases dictionary. Yo don’t get the translation of each word, but of the whole phrase. This process is called, no kiding, translation: we are translating a virtual memory address for a physical one.

Now, this translation process is very slow, that’s where the translation lookaside buffer (TLB) comes in. The TLB is a cache that stores the latest traslations done. So your program needs an address and the first time it tries to access it, the VM has to translate it from memory, but it stores this translation in the TLB, so the next time your program needs it, there’s no need to look for it, it just knows where it is. Back to the dictionary example, think of the TLB as a good old bookmarker. You can’t be looking for ‘Good morning, my name is ______’ in your dictionary every time you need to introduce yourself, so you bookmark it and next time you need to say ‘Buenos dias, mi nombre es ______’ it’s right there.

Using Page Tables and the TLB, the Virtual Memory makes the whole process a lot faster and memory efficient. This is, of course, applied to the three problems delineated before.

Sources:

Sometimes writer, avid for programming.