Memory Management in an Operating System
RAM is a fairly valuable resource, which must be managed according to certain principles. There are different management concepts, which lead to different techniques, with their pros and cons.
The management of main memory (RAM, primary, or as we call it) is one of the most important aspects of the operating systems. Like all computer resources, RAM must also be managed according to the usual principles of fairness and performance.
In particular, memory management must:
· Being economic (low overhead).
· Maximize its use.
A little better, you don't have to waste CPU time putting and taking stuff out of the primary memory, and you have to use all the available space efficiently.
Memory Management Requirements
To ensure efficiency and ease of management, data protection, and a minimum of code portability, we need these requirements.
Protection and Sharing
Generally, we don't want a process to access memory areas of other processes. Imagine having a password manager running: in RAM, you certainly have your credentials in the clear. we are sure you wouldn't like any process to access that piece of memory and read your credentials.
At the same time, however, we also ensure that some memory zones are shared between processes.
Imagine you have a large 500 kB library, which is used by 20 processes: instead of having the library copied in each of the 20 processes (for which 500 * 20 kB = 10 MB), we leave it shared and saved at least 10 MB.
This is a nice concept. let's see what it means.
We know that:
- The size of the RAM is not the same for each device.
- The operating system decides where to allocate in memory.
- A process can be taken out of memory, and put back later (swapping).
A process must be able to execute its instructions without thinking about where they actually are in RAM. This is the essence of relocation, making the process independent of its memory position. The information is stored in two specialized registers, called the base register and the bounds register, respectively.
In practice, the relocation is implemented by introducing relative addresses, also called logical ones. The process uses these relative addresses, which are then translated by the operating system into real physical addresses. To finish this concept, let's talk about the two types of relocation.
It is basic and not good. In this phase, all the logical addresses are translated into physical and calculating them starting from the initial one.
· Pros: none.
· Cons: the process is not swappable -> the memory cannot be reorganized.
It is good and modern technique. We can translate the addresses at runtime.
· Pros: we can relocate the process around the RAM -> we can reorganize the memory
· Cons: none.
We must distinguish between physical and logical.
· Physically, in memory, we implement overlaying, or we can allocate different modules/processes in the same memory zone, but at different times. Furthermore, the management is done transparently to the user/programmer.
· Logically, we see memory in a linear fashion, with permissions for each module/process.
The primary memory is a linear space in which the operating system allocates and de-allocates the memory. These two operations seem very trivial in words, but in reality, they are a big problem.
Over the years, several ideas have been introduced to make these operations possible. Modern operating systems use techniques called segmentation and paging (also used together), which allow the main memory to be used efficiently and without waste.
The basic idea of this cave technique was to divide the RAM into blocks of a certain length, called partitions.
The main features were:
· A program in each partition
· No partitioning programs.
We have three types of partitioning:
· Variable (fixed with variable size).
The idea was to have fixed-length partitions.
This technique required not just hardware support: in fact, it is used to put more than one processes in the main memory.
It is also quite intuitive to understand the limitations:
· Limited number of processes loaded simultaneously into memory.
· Maximum size of processes given by the size of the partitions.
Furthermore, here we introduce a problem called internal fragmentation.
Some intelligent people realized that there was a fairly intuitive way to reduce internal fragmentation. If we have internal fragmentation, it means we have smaller partition programs.
Then, if we had partitions with different lengths, we could allocate the programs in the most similar partitions.
· No need for memory already partitioned.
· ** Partitions created ad-hoc ** at runtime.
·No internal fragmentation.
·Goodbye process limits.
· Now the maximum size of the process coincides with the size of the RAM.
In fact, there are different algorithms to decide where to allocate new process. They are given below:
· Process allocated in the smallest space that can contain it (the best, by definition).
· High overhead, because finding this space takes time.
· In the long term it brings us more external fragmentation.
· Process allocated in the first free space from the beginning of the memory.
· Low overhead.
· In the long term it tends to crowd the initial part of the RAM.
· Like the first-fit, but starting from the last allocated position (idea derived from the principle of locality).
· Low overhead.
· In the long term, it tends to crowd the final part of the RAM.
This technique is a bit more complex than the previous ones, and the basic idea is to divide the memory into blocks called buddies and allocate the process to use if it respects a specific condition.
If you like comparisons, we can say that this technique uses some principles of fixed partitioning, but in a modern way.
Yes, maybe this description is better suited for reviewing a music album, but it's not wrong. Let's see why.
With pagination, both memory and processes are divided into ** small blocks of fixed size ** (typically 512 kB).
We introduce terminology on the fly:
· Pieces of memory: pages.
· Process pieces: frame.
This other system is instead heir to dynamic partitioning.
In fact, each process is divided into segments of variable length.
For each process, we have a segment table, which maps the pair to the corresponding physical address.
Segmentation allows us to see memory as an address space. There is a problem though: the segments may not be contiguous. in this case, the address space is not contiguous but fragmented. This makes things a little uncomfortable and not very elegant.
Segmentation on Pagination (or Paged Segmentation)
This method combines segmentation and paging. In practice, we use segmentation to address pages. In this way, we succeed in abstracting the discontinuity of the segments, making the program believe that it has a contiguous address space. Segments and pages remain discontinuous in memory, but we use a system to - in fact - abstract the address space.