Friday, July 19, 2013

More geekyness - How is memory on a computer used?

Location: Salt Lake City, UT, USA
Since it had been a while since I had a geeky post, I figured it was time.  Following with the theme of the low level, I am going to delve into memory a bit deeper than I have in the past.  This will be a two-part post.  This post will cover the hardware and operating system view of memory.  My next post will cover the view of memory which programs see.

On your computer you have some amount of memory.  You might have 2-4 GB or a little less, or a lot more, but beyond the abstract idea that your programs go in there when they run, you likely have little idea what your computer actually does with this memory.  You may have seen something about virtual memory, seen something about swapping, or even heard people talking about locality (I'm talking spacial locality), and not understood what they meant.  I aim to clear up some of this confusion.  This post is from a programming perspective.

The memory on your computer, typically refered to as RAM (random access memory), is one large array of contiguous bytes.  If you have 2 GB of memory, you have 2*2^30 (two times two to the thirtieth power) total bytes, or 2147483648 bytes numbered from 0 to 2147483647.  This numbering forms an address system for the memory array, thought of as Physical Memory.  This is a very logical way to address memory, and lends itself to very fast hardware operations, however this method of addressing poses a problem for applications running on the computer.  To understand why, we must look at how programs are actually run by your hardware (I will go into much more detail on this subject in my next post).

When a program is run on your computer the code which makes up the program (called the code segment) is loaded into memory.  Spread liberally throughout this code are commands that jump to new memory addresses, load values from memory, save values to memory, and generally manipulate the memory in any number of ways.  If your computer is only running one program this is not a problem, but if you happen to run a second program, the computer will have to place it in a different part of memory.  Since all modern computers are able to run more than one program at a time, the programs will never know where in memory they are, and programs have no way to know ahead of time where memory values will be, something a program must be able to do because these addresses must be defined and resolved at compile time, before the program is run.  To resolve this issue Intel introduced a new architecture to their chips called Virtual Memory (not to be confused with your operating systems swap file, which is sometimes called Virtual Memory by Windows users).

Virtual memory is an addressing scheme where each running program is presented with its own address 'space'.  This is an abstract representation where each program running (or more properly put, each process) is presented with a memory space that appears to be its own computer.  This memory space is not real, in the sense that it does not directly correspond to the physical memory installed on the computer, it is a completely logical memory space as opposed to physical, an abstraction.  Since there is a disconnect between the physical memory, and what each program sees, a special piece of hardware, called a memory management unit (MMU) is added to the computer to translate these logical addresses to a physical space in your memory array.  Hardware translation is important because it is very fast.  This way each program can address its own memory as if it were the only program running, but your physical memory can be used to handle many of these programs running at once.  Virtual memory and the increasing use of multi-tasking operating systems are a large contributing factor to increasing memory requirements.

So on top of this physical memory we have a layer of abstraction giving us logical addressing.  But there is another traditional issue in computer memory which must be addressed before we can use (program for) a modern operating system, that is the issue of fragmentation and total space.  What do I mean by fragmentation?  When we are laying out programs in memory, we need to make sure those programs do not run out of space.  We also must ensure that all the memory for a program is near the other memory for that program, a concept called spacial locality.  This is important because many operations within a program will move much faster if the memory accessed is sequential (because memory is transferred in chunks), and cache schemes tend to depend to some degree on spacial locality.  To achieve this we over-allocate memory to each program leading to unused memory that is unavailable, fragmented.  Also there is the issue of running out of memory all together.  Programs regularly allocate memory.  There are many programs running on every computer which will cause it to crash if this request for memory is unsatisfied, and as we run more and more programs we use more and more memory.

To deal with these issues by making it appear that we have nearly unlimited memory (limited only by the address width) we turn to a vast but slow array of memory, your computers hard disk.  To accomplish this we introduce the abstract idea of a page, a limited range of memory of a predefined size which we can assign to a single process (program).  Pages could be of any size, but as with anything in memory are typically sized to be a power of 2, aligning properly in memory with addresses that are powers of 2.  We can then move this page (a limited range of memory) back and forth from the physical memory (via logical addresses) to the hard drive and vice-versa depending on how frequently it is needed and how full the physical memory is.  This memory paging is controlled by the operating system which builds and maintains a table of all the pages of memory allocated and manages the access and location of the data stored in that memory whether it be in physical memory, or stored on disk.  The file on the disk which holds the memory not located in physical RAM is called a page file (proper name) or swap file (descriptive).  Many people improperly or informally refer to this concept of paging as virtual memory, though this can lead to confusion as I mentioned eariler.

So if you made it this far, at the very least, the next time you get an error that refers to a page or paging you will know what is causing the issue...  Then you will restart your computer like everyone else!

The only other thing that I can think to say on the subject of virtual memory and paging is that they are working together.  Your computer, consisting of a CPU, MMU, memory and busses (which transmit data between places), handles the virtual memory translation, an address translation, and this logical view presented by the hardware is what is being manipulated by the software, or the logical system on your computer, including your operating system.  In fact, your operating system is responsible for talking to the hardware, and it is prudent to note that the OS can control how the hardware functions on this level (through user rings, and processor modes, I will not go into this here).  The operating system is what created pages.  So if logical memory is an abstraction of physical memory, pages are an abstraction of logical memory.

Computers are a layered collection of abstractions!

I will leave you with that thought, and I will follow up this post with another about how programs work with memory, and how applications are structured in memory.  If you had trouble following my post on switch statements and jump tables, this next post will help clear it up a lot!

No comments:

Post a Comment