This is a course note of an online course I took relating to the Operating System on educative.io.
Chapter 4: Address Space
The address space of a process contains all of the memory state of the running program.
- The code of the program.
- The program, while it is running, uses a stack to keep track of where it is in the function call chain as well as to allocate local variables and pass parameters and return values to and from routines.
- The heap is used for dynamically-allocated, user-managed memory
Goals of virtualising memory
- Transparency : The OS should implement virtual memory in a way that is invisible to the running program.
- Efficiency: The OS should strive to make the virtualisation as efficient as possible, both in terms of time and space.
- Protection : The OS should make sure to protect processes from one another as well as the OS itself from processes.
Types of Memory
- Stack memory: The first is called stack memory, and allocations and deallocations of it are managed implicitly by the compiler for you, the programmer; for this reason, it is sometimes called automatic memory.
- Heap memory: It is the heap memory, where all allocations and deallocations are explicitly handled by you.
Malloc(): The malloc() function shall allocate unused space for an object whose size in bytes is specified by size and whose value is unspecified. Upon successful completion with size not equal to 0, malloc() shall return a pointer to the allocated space.
Free(): The free() function shall cause the space pointed to by ptr to be deallocated; that is, made available for further allocation. If ptr is a null pointer, no action shall occur.
calloc() allocates memory and also zeroes it before returning.
The realloc() makes a new larger region of memory, copies the old region into it, and returns the pointer to the new region.
Underlying OS Support
The malloc library manages space within your virtual address space, but itself is built on top of some system calls.
One such system call is called
brk, which is used to change the location of the program’s break: the location of the end of the heap. It takes one argument (the address of the new break), and thus either increases or decreases the size of the heap based on whether the new break is larger or smaller than the current break. An additional call
sbrk is passed an increment but otherwise serves a similar purpose.
You can also obtain memory from the operating system via the
mmap() call. By passing in the correct arguments,
mmap() can create an anonymous memory region within your program — a region which is not associated with any particular file but rather with swap space.
Memory virtualisation with address translation
Hardware-based address translation
With address translation, the hardware transforms each memory access (e.g., an instruction fetch, load, or store), changing the virtual address provided by the instruction to a physical address where the desired information is actually located.
Dynamic (Hardware-based) Relocation
When a program starts running, the OS decides where in physical memory it should be loaded and sets the base register to that value. Now, when any memory reference is generated by the process, it is translated by the processor in the following manner with two hardware registers : one is called the base register, and the other the bounds (or a limit register).
physical address = virtual address + base
A bounds (or limit) register ensures that such addresses are within the confines of the address space.
Process control block (PCB)
When a context switch occurs, there is only one base and bounds register pair on each CPU. Thus, the OS must save and restore the base-and-bounds pair when it switches between processes. Specifically, when the OS decides to stop running a process, it must save the values of the base and bounds registers to memory, in process structure or process control block (PCB).
That’s so much of it!