Intro to Computer Systems

Chapter 5: Memory & Hamming/SECDED Codes

Memory Management in Software

As we have seen, for a program to run - that is, for a process to execute - its instructions have to be in memory. It is then clear that existing memory has to be shared by all the users and all the processes at the same time. Except in exceptional circumstances, there is not enough memory to keep all this in memory all the time. Operating Systems employ several techniques to solve this problem:

The Operating System allocates sections of memory to processes at their request, and quickly frees them when they are no longer needed. This means that only some fragments of a process will be in memory at a given time, the remainder most likely waiting its turn to be brought in on disk. This is called swapping, because process information is swapped out to disk to make up some space, and then swapped in again when required.

Given the previous point, there can be no guarantee that a program section will be allocated to the same portion of memory each time it is swapped in. The Operating System looks for some free space in memory where it can put the information, and places it there. Thus, the memory addresses as seen by a process are different from the actual physical addresses in the computer memory.

In addition, the Operating System manages allocations for all the users to share the same memory. The memory management system of the Operating System manages all transparently for the users, who are unaware of this. The system very efficiently translates all the process addresses to physical addresses as the process executes.

As a consequence of this swapping and use of free space, the memory space for a process is not contiguous, but the process address space is actually fragmented like a mosaic. The process thinks that is using a continuous range of addresses, but the actual addresses are scattered all over memory, and some of them are even in secondary memory.

Unlimited Memory (?)

As a consequence of virtual memory, a computer “never” runs out of memory to run applications, since the Operating System swaps out things in memory when necessary and copies them onto disk. This frees up space to load the new application, or at least part of it. Programmers write programs as if there is unlimited RAM space.

This facility, however, has a price. The speed at which a hard drive manages information is much slower than RAM speed, so if the system is using virtual memory too heavily there will be a significant performance drop. That’s why is important to have enough RAM to keep a significant portion of your processes in memory to avoid the Operating System swapping all the time in and out of disk. The system will run very slow when this happens. This phenomenon is called thrashing, where the Operating System swaps out something out of memory, only to need it immediately after, and vice versa. As we can see, having enough memory is a key to maintain the performance of a computer system.

In some systems some parameters may be tuned to run virtual memory more efficiently. In multi-user systems typically there is an administrator (called root in UNIX, for example) to do that, and in personal computers this is done by the user. You should investigate this facility for your computer system.

Virtual Memory

The size of modern programs means that usually a whole program does not fit in memory all at once. Hence, only the relevant parts of a process (a running program) are loaded into main memory, with the remainder residing on disk. When a program requests data that is not in main memory - e.g. an instruction, or data from a file - it has to get it from disk. This is organised transparently by the OS and the corresponding software and hardware, so programmers write programs as if the size of the computer memory is unlimited. Since this arrangement provides programmers with a virtual computer memory to work with, it is called virtual memory.

To see how this works, assume a word is requested by the CPU; the word:

When the required data is not in memory there is a significant performance penalty since I/O devices are several orders of magnitude slower than the processor and memory.

The most common way to implement virtual memory is by dividing up main memory into fixed-size blocks called page frames usually 1K, 2K or 4K in size, and dividing programs and data also into pages of the same size. When the required data is not in memory, the corresponding page where the data is in secondary memory is brought in, and placed in one of the frames, and accessed there. Data transfers between disk and memory are always done in terms of pages.

When the data requested is in memory, the process waits for the transfer via the data bus. When data is required from disk however, the CPU cannot block processing until the data comes in, since the CPU would be idle for too long. Instead, the running process is put to sleep - it cannot run anyhow since the data it needs is not available - waiting for the transfer of the data from disk, as follows:

Of course, this means that contiguous program pages not necessarily result in contigu­ous page frames in memory. Figure 4.4 shows two processes pages in memory, the missing pages are in secondary memory.

Memory fragmented due to paging
Memory fragmented due to paging

Virtual memory works by translating each logical (virtual) memory address into a physical memory address. This is performed at run time, taking into account where in memory is each block located. In this way it is possible to:

All this operation is managed by the Operating System, which is in charge of determining whether the data is in memory and, if not, of locating where the data is on disk, and:

  1. putting the process to sleep
  2. if there isn’t a page frame free in memory, deciding which page is to be replaced to make room for the incoming page
  3. issuing the read transfer
  4. loading the page into memory (this accepts variations)
  5. waiting until the transfer has finished

When the transfer is finished, the OS decides which process is going to run in the CPU next - it may not be the original process now sleeping - and dispatches this process to run in the CPU by copying all the process information into the CPU structures (registers, PC and IP).