---
# System prepended metadata

title: 'Ch8:Memory Management'
tags: [Operating System, Ch8, Review]

---

---
title: Ch8:Memory Management
---
# 作業系統Ch8: Memory Management
###### tags: `Operating System` `Review` `Ch8`

## Background
- CPU 可以直接存取的只有 Main memory and registers。
- 在 disk 上等待被帶入 memory 和被執行的 processes 集合。
- 多個 programs 帶入到 memory 以改善資源使用率和 response time to users。
- A process 可能在執行過程中的 disk 和 memory 之間移動。

## Multistep Processing of a User Program

在不同時間，可能會進行不同 address binding。

![](https://i.imgur.com/q8lJufh.png)

## Address Binding
### Address Binding - Compile time
- Compiler translates symbolic code into **absolute code**
> absolute code 使用絕對位址
- If starting location changes $\rightarrow$ recompile
- e.g., MS-DOS .COM format binary

記憶體位址從 Compile 完，就會全部都知道，然後再 load 到 memory。

![](https://i.imgur.com/cXk4Ogh.png)


### Address Binding - Load time
- Compiler translates symbolic code into **relocatable code**
> relocatable code: 機器語言可以從任何記憶體位址運行。
- If starting location changes $\rightarrow$ reload

如果不是在 compile time 就知道 process 的 data 或者 instruction 位於記憶體的位址，那麼會產生 relocatable code ，且 binding 會到 load time 時才做。

![](https://i.imgur.com/qjXqoRd.png)

### Address Binding - Execution time

- Compiler translates symbolic code into logical-address (i.e. virtual-address) code
- 這方法需要硬體 MMU。
- 通用目的的 OS 使用這方法。

Program 在 compile 完後會產生 logical address，而 CPU 讀取 memory content 將 logical address load 到 Memory 前必須要透過 MMU 才能轉換成 Physical address

![](https://i.imgur.com/sMlFM9l.png)

### Memory-Management Unit (MMU)

- 硬體裝置用來 virtual address 映射到 physical address.
- physical address 是由 user process 產生的每一個 address 被送入到記憶體時加上在 relocation register 中的值。

![](https://i.imgur.com/kWZpt3I.png)

### Logical vs. Physical Address

- Logical address – generated by CPU
    - a.k.a. virtual address
- Physical address - seen by the memory module
- compile-time & load-time address binding
    - logical addr $=$ physcial addr
- Execution-time address binding
    - logical addr $\neq$ physical addr
- user program 處理 logical addr， 它永遠不會看見 the real physcial addr。

## static/dynamic loading and linking
### Dynamic loading

**Static loading**: 將所有 data 和 function 全部放入到 memory ，為了去執行。

**Dynamic loading**: A routine is loaded into memory when it is called。
- 更好記憶體空間使用率
    - unused routine is never loaded
    - Particularly useful when large amounts of code are  infrequently used (e.g., error handling code)
- No special support from OS is required implemented through program (library, API calls)

Dynamic Loading Example in C
> dlopen: 開啟 library 且為使用準備它。
> dlsym: 在開啟的 library 中查找 the value of a symbol。
> dlclose: 關閉 DL library。

```c=
#include<dlfcn.h>
int main()
{
    double (*cosine)(double);
    void *handle = dlopen("/lib/libm.so.6", RTLD_LAZY);
    cosine = dlsym(handle, "cos");
    printf("%f\n", (*cosine)(2.0));
    dlclose(handle);
}
```

概念示意圖如下，如果 function B 和 C 是 Dynamic loading，則一開始只有 function A 會載入到記憶體。

![](https://i.imgur.com/WxYy7SA.png)

### Static linking

**Static linking**: ~~loader~~(此處恐龍書有 typing mistake，應為linker) 會將 libraries 混入 program 在 memory image。
> A memory image is simply a copy of the process's virtual memory, saved in a file.
- Waste memory: duplicated code
- Faster during execution time
> 因為不用去尋找。

<font color=red> Static linking + Dynamic loading</font>: 仍然會有 duplicated code。
> Dynamic loading 是針對一 process 在呼叫時才載入，可是如果今天有多個 process 需要進行 printf() 的 function call 時，這每個 process 同樣都會進行Dynamic loading，因此記憶體還是會產生重複 code。

![](https://i.imgur.com/5YzzBhk.png)

![](https://i.imgur.com/nem9PLG.png)

### Dynamic Linking
**Dynamic Linking**: 等到執行時再進行 linking (也就是延遲 linking)。
- Only one code copy in memory and shared by everyone
- A stub is included in the program in memory image for each lib reference
- 當呼叫函數時，會先跳入 stub 中，而 stub call 會檢查被參考 lib 是否在記憶體中，如果不在的話，則載入 lib，接著執行lib 中的 function。
- DLL (Dynamic link library) on Windows；在 UNIX/Linux 中的動態連結函式庫則被稱為 Share Objects，其附檔名通常是 .so。

![](https://i.imgur.com/BOVXU1R.png)


## Swapping

### Swapping

- a process 可以被 swapped out of memory to a **backing store**，之後 swapped into memory for continuous execution。
    - Also used by midterm scheduling.
- Backing store - 一塊 disk，跟檔案系統是分隔開來的，提供直接 access to these images。
- Why Swap a process:
    - Free up memory
    - Roll out, roll in: swap lower-priority process with a  higher one
- Swap back memory location
    - if binding is done at compile/load time
        - swap back memory address must be the same
        > 這樣就會產生麻煩，因為有可能 memory address 被其他的占用。
    - If binding is done at execution time
        - swap back memory address can be different
A process to be swapped 一定要是 idle，也不能進行 I/O
> 如果正在等待 I/O時，此時卻 swapped，會產生一些問題。
> 解決方式就是:
> (1) 不要 swap 正在 pending I/O 的 process
> (2) 透過 OS buffers 來完成 I/O operations
 >> OS 為 process create 一個 OS buffer(為 I/O 寫入的資料) ，位在 OS 的記憶體空間，接著將 I/O 資料搬到 OS memory，在搬的時候，process 沒有 touch 到它本身的 memory，所以 process 可以被 swap 掉，等到 I/O 做完了，再把 process swapped into memory，接著 OS buffer 的內容 copy back 那個 process 的 記憶體空間。

- 大部分 swap time 的時間都是進行 transfer time，總 transfer time 跟 memory swapped 的量成正比。 

![](https://i.imgur.com/dCxI0Jj.png)

## Contiguous Memory Allocation
### Memory Allocation
- Fixed-partition allocation:
    - Each process loads into one partition of fixed-size。
    - multiprogramming 的程度受限於 partitions 的數量。
- Variable-size allocation:
    - Hole: 連續 free memory 的區塊
    - 多個不同大小的 holes 會散落在記憶體中。
    - OS 會維護資訊 - 正在使用的和有空閒的 hole
    - A free hole 可以和另外一個 hole 合併形成較大的 hole。

![](https://i.imgur.com/AjuLKyC.png)

### Dynamic Storage Allocation Problem

如何從一串 free holes 來滿足有一個大小為 n 的分配請求?
- First-fit: 看到第一個滿足它的就分配給它。
- Best-fit: 分配最小的 hole，但是可以滿足它。
    - 需要搜尋一遍
- Worst-fit: 分配最大的 hole。
    - 需要搜尋一遍

前兩者比後者在速度和空間使用率上更好。

### Fragmentation
- External fragmentation
    - 總 free mem space 足夠大以滿足 a request，但是不連續。
    - 發生在 variable-size allocation
![](https://i.imgur.com/3KOdOIf.png)

- Internal fragmentation
    - partition 的內部有記憶體未被使用
    - 發生在 Fixed-partition allocation

![](https://i.imgur.com/3IhQNUU.png)

Solution:
- Compaction
    - 在 run time，重組記憶體內容來將所有 free memory 放置到一塊大的 block。
    - Only if binding is done at execution time

![](https://i.imgur.com/0kDHGXA.png)

## Non-Contiguous Memory Allocation - Page
### Paging Concept
Method:

- Physical memory 分割成固定大小的 blocks 稱作 frames。
- logical address space 切成同樣大小的 blocks 稱作 pages。
- 為了跑 n pages 的 program，就需要找到 n free frames 且載入 program
- 追蹤 free frames
- 設立 a page table 去轉換 logical to physical address
> 每一個 process 會有自己的 page table， 由 OS 維護。

Page table:
- Each entry maps to the base address of a page in physical memory
- A structure maintained by OS **for each process**
    - Page table 只包含由 process 擁有的 pages
    - A process 不能存取在它之外的空間得 memory

![](https://i.imgur.com/MKZhT31.png)


Benefit:
- 允許 process 的 physical address space 是 **noncontinuous**
- 避免 external fragmentation
- 有限 internal fragmentation
- 提供共享 memory / pages

### Address Translation Scheme
- Logical address 分成兩個部分
    - Page number\(p\):
        - 當作 page table 的 index ，包含在實體記憶體中每一 page 的 base address。
        - N bits 代表 a process 可以分配到最多 $2^{N}$ pages
        > $2^{N}\times\ page\ size\ memory\ size$ 代表一個 process 能夠擁有的記憶體空間。
    - Page offset\(d\):
        - 結合 base address 去定義送到 memory unit 的實體記憶體。
        > 在實體記憶體的 page 大小
        - N bits 代表 the <font color=red>page size</font> 是 $2^{N}$

$Physical\ addr\ =\ page\ base\ addr\ +\ page\ offset$

Address Translation Architecture

![](https://i.imgur.com/fQZf1n8.png)

### Free Frames

free-frame list 是 linked list，每次有新的 process 分成 pages，去逐一對應從 linked list 頭開始。

![](https://i.imgur.com/iYwommr.png)

### Page / Frame Size
- page (frame) size 由硬體定義:
    - 通常是 a power of 2
    - 4KB/8 KB 常用
- page size 太大會有 internal fragmentation，page table 變小，更多浪費空間。
- page size 太小會造成 page 數量變多，page table 變大，造成搜尋時間上的增加。

### Paging Summary
- Paging 分隔使用者的視角和真實 physical memory。
- OS maintains a copy of the <font color=red>page table for each process</font>.
- OS maintains a <font color=red>frame table</font> for managing physical memory.

### Implementation of Page Table

- Page table 保留在 memory 中。
- Page-table base register (PTBR)
    - The physical memory address of the page table
    - PTBR 值儲存在 PCB
    - 在 Context-switch 期間，改變 PTBR 的值
- 每次記憶體參考會導致 2 memory reads。
- The 2-access problem can be solved by
    - <font color=red>Translation Look-aside Buffers (TLB)</font> which is implemented by <font color=red>Associative memory</font> (HW)

### Associative Memory
- 所有 memory entries 可以同時存取。$O(1)$
- entries 的數量有限。($64\ \sim\ 1024$)

![](https://i.imgur.com/gr8OfPR.png)

### Translation Look-aside Buffer
- A cache for page table shared by all processes
> 如果 cache hit，可以少一次 access；如果 cache miss，則依然需要 2 access ，然後再 cache 住。
- TLB must be <font color=red>flushed</font> after a context switch
    - Otherwise, TLB entry must has a PID field (address-space identifiers (ASIDs))

![](https://i.imgur.com/xVAe3AZ.png)

### Effective Memory-Access Time

有 TLB 的話可以有效降低 EMAT。
- 20 ns for TLB search
- 100 ns for memory access
    - 70% TLB hit-ratio: 
        - EMAT = 0.70 x (20 + 100) + (1-0.70) * (20+100+100) = 150 ns
    - 98% TLB hit-ratio:
        - EMAT = 0.98 x 120 + 0.02 x 220 = 122 ns
> 如果兩次 memory access 是 200 ns

### Memory Protection
- 每 page 與在 page table 中的一組 protection bit 有關。
- Common use: valid-invalid bit
    - Valid: the page/frame 是在 process 中的 logical address space，因此是合法的 page
    - Invalid: the page/frame **不**在 process 中的 logical address space
- Potential issues:
    - 未使用的 page entry 造成記憶體浪費 $\rightarrow$ 使用 page table length register(PTLR)
    > 指出 the size of the page table (以 byte 為單位)。它的值會針對每個 logical address 檢查去驗證是否 address 在對於 process 而言有效的 range。 測試失敗的話會對於OS 產生 error trap。
    - Process memory may NOT be on the boundary of a page $\rightarrow$ memory limit register is still needed

![](https://i.imgur.com/9uoL1Oi.png)

### Shared Pages
- Page 允許 processes 共享 common code 且一定要是 reentrant。
- Reentrant code (pure code)
    - 它在執行期間不會改變
    - e.g., text editors, compilers, web servers, etc
- 只會在 physical memory 保持一份 shared code。
- 兩個以上 virtual addr 會映射到同一個 physical address。
- Process 會保有它的私有 data and code 一份。 
- Shared code 會出現在 所有 processes 的 logical addr space 相同位置。 

![](https://i.imgur.com/uaZLQm4.png)

### Page Table Memory Structure
- Page table 可能太大且難以載入
    > 假設有 4GB ($2^{32}$) logical address 且有 4KB ($2^{12}$) 大小的 page，將會有 1 million ($2^{20}$) page table entries。
    > 又假設每一 entry 需要有 4 bytes (32 bits) 去做紀錄，則需要 Total size = 4MB。在實體記憶體中不一定能夠找到連續的 4MB 大小空間。
    > 因此需要拆成很多較小的 page table， 在單一 page size 更好的範圍內。(i.e. 4KB) 或者減少 total size of page table (很多分配而沒用到的)
- Solutions:
    - Hierarchical Paging
    - Hash Page Tables
    - Inverted Page Table

### Hierarchical Paging
- Break up the logical address space into multiple page tables.
- Two-level paging (32-bit address with 4KB ($2^{12}$) page size)
    - 12-bit offset (d) $\rightarrow$ 4KB ($2^{12}$) page size
    - 10-bit outer page number $\rightarrow$ 1KB ($2^{10}$) page table entries
    - 10-bit inner page number $\rightarrow$ 1KB ($2^{10}$) page table entries
    - <font color= red> 3 memory accesses </font>

![](https://i.imgur.com/wojukG8.png)

第二層的 p2 的值對應到 physical address，然後透過 page offset 得到在 physical address 的佔用空間。

![](https://i.imgur.com/UmbYVJB.png)

假如一個 entry 需要佔 4 B，那麼原先我們需要找到 $2^{22}$ B，也就是 4MB 才能儲存 page table，運用兩層的 page table，我們只需要找 4KB就可以儲存一個小的 page table，我們實際上是把 page table 的大小變小，但是原先 page table 數量只有一個，現在是變成有 $2^{10} + 1$ page tables，而且如果去看 total entries 數量，也是比原先大的，因為我們需要用額外 entries (實則level 1 的 entries) 去追蹤原先每 $2^{10}$ 劃分成小 page table。總而言之，如果單看總記憶體使用量和 entries 數，完全是比原先還要多，但是使用兩層的好處就是它更容易儲存於記憶體中。


概念示意圖如下:

![](https://i.imgur.com/EnH8Gg9.png)

如果考慮到 64-bit Address

分兩層 page tables 如下:
- 42 (p1) + 10 (p2) + 12 (offset)
> outer table requires $2^{42}$ x 4B = <font color=red>16TB contiguous memory!!!</font>
分五層 page tables 如下:
- 12 (p1)+10 (p2)+10 (p3)+10 (p4)+10 (p5)+12 (offset)
> outer table requires $2^{12}$ x 4B = 16KB contiguous memory
> <font color=red> 6 memory accesses </font>

> 實務上，分四層已經是很多了，不過因為可能會有頭尾都有用到，但是中間卻是 free 的狀況，但是還是要分配成 page，所以很浪費記憶體空間 。

### Hashed Page Table (> 32 bits)
- Virtual page number is hashed into a hash table
- The size of the hash table varies
    - Larger hash table $\rightarrow$ smaller chains in each entry
- Each entry in the hashed table contains
    - $(Virtual\ Page\ Number,\ Frame\ Number,\ Next\ Pointer)$
    - Pointers waste memory
    - Traverse linked list waste time & cause additional memory references

![](https://i.imgur.com/nTw4wGC.png)

![](https://i.imgur.com/Bkhbkmh.png)

Hashed Page Table Address Translation

概念示意圖如下:

![](https://i.imgur.com/dvLt5aU.png)

--- 

考慮到當 page 很多時，可能會產生在某一個 hash function 後的值會是一長串，因此需要花費很多時間去 traverse，因此我們需要改變成 hash array 的方式，將它一次scan 多個並 load 到 MMU 去做處理(comparison)。

Improved Hashed Page Table Implementation

概念示意圖如下:

![](https://i.imgur.com/UZFw250.png)

### Inverted Page Table
- 對於每個 process 不維護 page table
- 對於整個實體記憶體維護一個 frame table
- Each entry in the frame table has
    - $(PID,\ Page\ Number)$
- Eliminate the memory needed for page tables but increase memory access time
    - 每次存取都需要搜尋整個 frame table
    - Solution: use **hashing** for the frame table
- Hard to support shared page/memory
> 要做到一個 frame 對到多個 pages 很難

Inverted Page Table Addr Translation

概念示意圖如下:

![](https://i.imgur.com/oG6blBj.png)

## Non-Contiguous Memory Allocation — Segmentation
### Segmentation
- 使用者觀點的 memory
> 也就是隨需要調整大小的 memory。
- A program 是 a collection of segments. A segment is a logical unit such as:
    - main program
    - function, object
    - local/global variables
    - stack, symbol table
    - arrays, etc...

![](https://i.imgur.com/epEDL19.png)

### Segmentation Table

- Logical address: $(seg\#,\ offset)$
    - offset has the same length as physical addr
- Segmentation table - maps two-dimensional physical addr; each table entry has:
    - Base (4 bytes): physical addr 起始位址
    - Limit (4 bytes): segment 的長度
- Segment-table base register (STBR):
    - the physcial addr of the segmentation table
- Segment-table length register (STLR):
    -  the $\#$ of segments

### Segmentation Hardware
- limit register: 檢查 offset length
- MMU 分配 memory 透過指定一個適當的 base addr 對於每一個 segment
    - Physical addr 不能 overlap between segments

![](https://i.imgur.com/B2vjxBB.png)

### Address Translation Comparison

![](https://i.imgur.com/Mss53ty.png)

### Example of Segmentation

![](https://i.imgur.com/3csasdv.png)

### Sharing of Segments

![](https://i.imgur.com/KqoYHRL.png)

### Protection & Sharing

- Protection bits 與 segments 相關
    - Read-only segment (code)
    - Read-write segments (data, heap, stack)
- Code 共享只發生在 segment level
    - shared memory communication
    - shared library
- 在兩個 segment tables 中，共享 segment 擁有 same base

## Non-Contiguous Memory Allocation - Segmentation with Paging
### Basic Concept
- 運用 segmentation 在 logical addr space
- 運用 paging 在 physical addr space

![](https://i.imgur.com/Ji0mYsZ.png)


### Address Translation

Segmentation 和 paging unit 都在 MMU 裡面

![](https://i.imgur.com/0sc779Q.png)

### Example: The Intel Pentium

- Logical address space 分成兩 partitions:
    - 1st: 8K($2^{13}$) segments (private), local descriptor table (LDT)
    - 2nd: 8K($2^{13}$) segments (shared), global descriptor table (GDT)
> 可透過 OS 跟 其他 segment 共享
- logical address:
    - max $\#$ of segments per process = $2^{14}$ = 16K
    - size of a segment $\leq$ $\ 2^{32}$ = 4GB
![](https://i.imgur.com/2MWJaP7.png)
> protection info 代表 Read-only, Read-write, execute

### Intel Pentium Segmentation
- Segment descriptor
     - Segment base address and length
     - Access right and privileged level

![](https://i.imgur.com/9M1gzMP.png)

> 實際上 selector 找到在 table 上面的 index，會有 base and length (limit)， 然後 offset 如果沒有超過的話，就跟 base 相加(兩者同樣都是 32 bits)，得到 32-bit linear address

### Intel Pentium Paging (Two-Level)
- Page size can be either 4KB or 4MB
    -  Each page directory entry has a flag for indication
    > 設立一個 bit 去決定要 4KB or 4MB

![](https://i.imgur.com/yGMHbuu.png)

> 透過兩層 page， outer and inner 大小都是 10 bits，offset 則是 12 bits。將 linear address 分成三段，如果今天 flag 設為 0，則採用 4KB 方案，跟兩層 page 作法一樣；flag 設為 1 時，則將 inner 和 offset 的部份合併在一起 (22 bits) 當作 offset，對應到 4MB page。

### Example Question

> Q: Let the physical mem size is 512B, the page size is 32B and the logical address of a program can have 8 segments. Given a 12 bits hexadecimal logical address “448”, translate the addr. With blow page and segment tables.
> A: $(448)_{16} = (01001001000)_{2}$
> 根據題意，最高位 bit 頭三個是 seg $\#$，其餘都是 seg offset
> 也就是 $(010)_{2}$ 代表第二個 segment，去找到第二個 segment 對應到> 的 base address，再加上 offset 即可獲得 linear address = $(010111110)_{2}$。
> 接著根據題意，最高位 bit 頭四個為 page $\#$，其餘都是 page offset，
> 也就是 $(0101)_{2}$ 代表第五個 page，對應到 frame $\#$，找到相對應的位置(即 frame number 乘上 page size)， 再加上 offset $(11110)_{2}$，即是 physical address。

![](https://i.imgur.com/Ee2CsbQ.png)

## Ref

[1] [上課影片 link](https://www.youtube.com/playlist?list=PLS0SUwlYe8czigQPzgJTH2rJtwm0LXvDX)
[2] [投影片 link](https://ocw.nthu.edu.tw/ocw/index.php?page=course_news_content&cid=141&id=999)
