---
# System prepended metadata

title: OS Final

---

# 2024 Finals

[toc]

### 1. EAT 計算

在一個帶有**關聯暫存器 (associative registers, TLB)** 的需求分頁系統中，服務一次**頁錯誤 (page fault)** 需要 **2 毫秒 (milliseconds)**。一次記憶體參考需要 **200 奈秒 (nanoseconds)**，在關聯暫存器中找到頁表條目需要 **20 奈秒**。如果 TLB **命中率 (hit ratio)** 是 **90%**，**頁錯誤率 (page fault ratio)** 是 **10%**，求**有效存取時間 (Effective Access Time, EAT)**。

**步驟 1: 參數轉換與定義**

* $T_{pf} = 2 \text{ ms} = 2,000,000 \text{ ns}$ (page fault times)
* $T_{mem} = 200 \text{ ns}$ (memory access time)
* $T_{tlb} = 20 \text{ ns}$ (TLB access time)
* $H = 0.90$ (TLB hit rate)
* $P = 0.10$ (page fault rate)
* $M = 2 \times T_{mem} = 400 \text{ ns}$ (TLB 不命中時，需要一次 TLB 存取 + 兩次記憶體存取：頁表和資料)

**步驟 2: 計算 EAT**

$$EAT = H \times (T_{tlb} + T_{mem}) + (1-H) \times [ (1-P) \times (T_{tlb} + 2 \times T_{mem}) + P \times T_{pf} ]$$

$$EAT = 0.90 \times (20 + 200) + 0.10 \times [ 0.90 \times (20 + 200 + 200) + 0.10 \times 2,000,000 ]$$

$$EAT = 0.90 \times (220) + 0.10 \times [ 0.90 \times (420) + 0.10 \times 2,000,020 ]$$

$$EAT = 198 + 0.10 \times [ 378 + 200,002 ]$$

$$EAT = 198 + 0.10 \times [ 200,380 ]$$

$$EAT = 198 + 20,038$$

$$EAT = 20,236 \text{ ns} \approx 20.24 \text{ }\mu\text{s}$$

**有效存取時間 (EAT) 約為 $20,236 \text{ ns}$ (或 $20.24 \text{ }\mu\text{s}$ )。**

---

### 2. 記憶體位址轉換（分段與分頁）

**題目 (Q2)：** 考慮一個 $16 \text{ 位元}$ 虛擬位址、實體記憶體 $4 \text{ KB}$、頁面大小 $256 \text{ Bytes}$、最大段大小 $1 \text{ KB}$ 的電腦系統。給定段表、頁表和 $16 \text{ bits}$ 十六進制邏輯位址 **"0C42"**，完成位址轉換圖：(a) 段表索引 (b) 線性位址 (二進制) (c.) 頁表索引 (d) 實體位址 (二進制)。

#### **基礎參數計算 (Base Parameter Calculation)**

* **虛擬位址 (邏輯位址)：** $16 \text{ bits}$
* **頁面大小：** $256 \text{ Bytes} = 2^8 \text{ Bytes}$ $\implies$ **page offset $d = 8 \text{ bits}$**
* **線性位址空間 (Segment Limit)：** $1 \text{ KB} = 1024 \text{ Bytes} = 2^{10} \text{ Bytes}$ $\implies$ **offset $d' = 10 \text{ bits}$**
* **邏輯位址 "0C42" (Hex)：** $0000 \ 1100 \ 0100 \ 0010 \text{ (Binary)}$

#### **解答 (Solution)**

![image](https://hackmd.io/_uploads/H1DPU3jG-g.png)



---

### 3. 不同分頁機制下行程頁表所需的記憶體空間

考慮一個 **32 位元作業系統 (32-bit OS)**，運行在具有 **64MB 實體記憶體 (physical memory)** 的機器上。OS 將 32 位元邏輯位址空間劃分成頁，每頁大小為 **4KB**。假設頁表中每個條目大小為 **4 bytes**，請計算在下列四種位址轉換方法下，**一個行程的頁表**所需的記憶體空間。

#### **基礎參數計算 (Base Parameter Calculation)**

1.  **邏輯位址空間大小：** $2^{32} \text{ bytes}$
2.  **Page Size, $P$:** $4 \text{ KB} = 2^{12} \text{ bytes}$
3.  **Offset Bits:** $\log_2P = 12 \text{ bits}$
4.  **Virtual Page Number, VPN:** $32 - 12 = 20 \text{ bits}$
5.  **Total Virtual Pages:** $2^{20} \text{ 頁}$

#### **解答 (Solution)**

**(a) 一級頁表 (One-level page table)**

* **所需的記憶體空間：** 頁表條目數 $\times$ 每個條目大小
    $$2^{20} \times 4 \text{ bytes} = 4 \text{ MB}$$

**(b) 二級頁表 (Two-level page table)**

* **條件：** 第一級頁表有 **256 個條目** (即 $2^8$)；只需要**第一級頁表**和**第一塊第二級頁表**存於記憶體中。
* **位址分解：** 20 位 VPN 分解為：
    * 第一級頁號 ($P_1$): $\log_2(256) = 8 \text{ bits}$
    * 第二級頁號 ($P_2$): $20 - 8 = 12 \text{ bits}$
* **所需頁表條目數：**
    * 第一級頁表：$2^8 = 256 \text{ 條}$
    * 第二級頁表（只需第一塊）：$2^{12} = 4096 \text{ 條}$
* **所需的記憶體空間：** (第一級條目數 + 第二級條目數) $\times$ 每個條目大小
    $$(256 + 4096) \times 4 \text{ bytes} = 4352 \times 4 \text{ bytes} = 17,408 \text{ bytes} \approx 17.0 \text{ KB}$$
    **所需空間：$17,408 \text{ bytes}$ (或 $17.0 \text{ KB}$)**

**(c.) Hashed paged table**

* **條件：** 雜湊函數的範圍在 **0 到 27** 之間，即雜湊表（Hash Table）有 $28$ 個**雜湊鏈 (hash chains)**。
* **定義：** 雜湊頁表只儲存**實際使用的**虛擬頁號及其對應的頁框號。它的大小與**虛擬位址空間大小**無關，而與**實際使用的頁面數**和**雜湊表大小**有關。
* **計算：** 題目沒有給出行程實際使用的頁數，但一個簡單的估計是基於雜湊表的鏈頭數量。通常雜湊頁表空間至少包含雜湊表本身。
    * **雜湊表 (鏈頭) 空間：** 雜湊鏈數量 $\times$ 每個條目大小
        $$28 \times 4 \text{ bytes} = 112 \text{ bytes}$$
    * *註：* 這是**雜湊表**的大小，還未計算實際的**鏈條**空間（即鏈接的頁表條目）。由於條件不足（缺少實際使用的頁面數），**最精簡且確定的回答是鏈頭的大小**。
    **所需空間 (鏈頭)：$112 \text{ bytes}$**

**(d) 反向頁表 (Inverted page table)**

* **定義：** 反向頁表只有**一個**，表中的條目數量與**實體記憶體中的頁框數量 (Frame Count)** 相等，而不是與虛擬頁面數相等。
* **實體記憶體大小 (Physical Memory, $M$):** $64 \text{ MB} = 2^6 \times 2^{20} = 2^{26} \text{ bytes}$
* **實體頁框數 (Frame Count):** $M / P$
    $$2^{26} \text{ bytes} / 2^{12} \text{ bytes} = 2^{14} \text{ 頁框}$$
* **所需的記憶體空間：** 實體頁框數 $\times$ 每個條目大小
    $$2^{14} \times 4 \text{ bytes} = 2^{14} \times 2^2 \text{ bytes} = 2^{16} \text{ bytes} = 64 \text{ KB}$$
    **所需空間：$64 \text{ KB}$**

---

### 4. Page Replacement Algorithms

考慮下表中五個頁面的狀態。在下列各演算法下，哪一頁將會被置換？

| Page | Loading time | The last reference time | R bit | M bit | Accumulated reference bit |
| :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | 087 | 682 | 1 | 0 | 516 |
| 2 | 941 | 993 | 1 | 1 | 020 |
| 3 | 684 | 981 | 0 | 0 | 278 |
| 4 | 194 | 625 | 1 | 1 | 397 |
| 5 | 091 | 277 | 0 | 1 | 093 |

**What is the replaced page under each of following algorithm?**
(a) FIFO (b) LRU (c.) second chance (d) enhanced second chance (e) LFU

#### **解答 (Solution)**

置換原則是選擇各演算法中最小或最不符合條件的頁面。

**(a) FIFO (First-In, First-Out)**
* **原則：** 選擇**載入時間 (Loading time)** 最早的頁面。
* **判斷：** **頁面 1 (087)**, 頁面 2 (941), 頁面 3 (684), 頁面 5 (091), 頁面 4 (194)。
* **置換頁面：** **Page 1** (載入時間 087)

**(b) LRU (Least Recently Used)**
* **原則：** 選擇**上次參考時間 (The last reference time)** 最早的頁面。
* **判斷：** 頁面 1 (682), 頁面 2 (993), 頁面 3 (981), 頁面 4 (625), **頁面 5 (277)**。
* **置換頁面：** **Page 5** (上次參考時間 277)

**(c.) Second Chance (第二次機會演算法)**
* **原則：** 依 FIFO 順序，檢查 **R bit (參考位元)**。若 $R=0$，置換；若 $R=1$，給予第二次機會（設定 $R=0$ 並移到佇列尾部）。假設檢查順序為頁面 1 $\to$ 2 $\to$ 3 $\to$ 4 $\to$ 5 (根據 Loading time 的 FIFO 順序: 1, 5, 4, 3, 2)。
    * **FIFO 順序：** 頁面 1 $\to$ 頁面 5 $\to$ 頁面 4 $\to$ 頁面 3 $\to$ 頁面 2
    * **檢查：**
        1.  **Page 1 (R=1)：** 得到第二次機會，R $\to 0$，移到尾部。
        2.  **Page 5 (R=0)：** **置換**。
* **置換頁面：** **Page 5**

**(d) Enhanced Second Chance (增強型第二次機會/NRU)**
* **原則：** 根據 **(R, M)** 類別優先置換：**Class 1 (0, 0)** $\to$ **Class 2 (0, 1)** $\to$ **Class 3 (1, 0)** $\to$ **Class 4 (1, 1)**。在同類別中，依 FIFO 順序選擇。
    * **Class (0, 0):** Page 3 (最不常用且未修改) $\to$ **首選置換**
* **置換頁面：** **Page 3**

**(e) LFU (Least Frequently Used)**
* **原則：** 選擇**參考次數 (Accumulated reference bit)** 最小的頁面。
* **判斷：** 頁面 1 (516), 頁面 2 (020), 頁面 3 (278), 頁面 4 (397), 頁面 5 (093)。
* **置換頁面：** **Page 2** (參考次數 020)

---

### 5. Deadlock 的四種處理策略

* **死鎖預防 (Deadlock Prevention)：** 透過**限制**，確保死鎖的四個**必要條件**（互斥、持有並等待、不可搶佔、循環等待）中**至少一個永遠不會成立**。
* **死鎖避免 (Deadlock Avoidance)：** 系統在每次資源申請時**動態檢查**，使用演算法（如**銀行家演算法**）確保系統**永遠不會進入不安全狀態**。
* **死鎖偵測 (Deadlock Detection)：** 允許死鎖發生，但系統會**定期執行演算法**檢查資源分配圖中是否存在**循環**。
* **死鎖恢復 (Deadlock Recovery)：** 一旦偵測到死鎖，採取措施**打破循環**。
    * *方法：* **中止行程**（一次一個或一次全部），或**資源搶佔**（從受害者行程中拿走資源）。

---

### 6. 分頁與夥伴系統的定義與比較

* **Paging for User Space：**
    * 將程式的**邏輯位址**和**實體記憶體**都劃分成**固定大小**的塊（page/frame）。
* **Buddy System for Kernel：**
    * 一種動態記憶體分配技術，將記憶體劃分為大小為 **$2^n$** 的塊。

| 特徵 (Feature) | 分頁 (Paging) | 夥伴系統 (Buddy System) |
| :--- | :--- | :--- |
| **主要用途** | user space 程式的 virtual memory 實作 | **kernel space** 記憶體分配 |
| **分配單位** | **固定大小**的頁面 | **2 的冪次**大小的塊 |
| **主要功能** | **位址轉換** (邏輯 $\to$ 實體) | **動態記憶體分配與合併** |
| **碎片問題** | **內部碎片** | 內部碎片，外部碎片較少（合併快速） |

### 7. Definition and solutions of Thrashing

當系統的**多工度過高**，行程總頁面需求超過實體記憶體時，行程會**不斷地**發生**頁錯誤（Page Faults）**。系統將大部分時間花費在磁碟 I/O（調入/調出頁面）上，導致 **CPU utilization rate 極低**。

* **方法一：Working-Set Model**
    * **機制：** 定義一個**工作集 (Working Set)**，即在一段時間 $\Delta$ 內行程存取過的頁面集合。只允許在**所有行程工作集總和**小於實體記憶體容量時，才允許執行該行程。
* **方法二：Page-Fault Frequency, PFF**
    * **原理：** 監控每個行程的**頁錯誤率**。
    * **機制：** 設定 PFF 上限和下限。
        * 若 PFF **高於上限**：認為頁框不足，應**增加**分配給該行程的頁框數。
        * 若 PFF **低於下限**：認為頁框過多，應**減少**分配給該行程的頁框數。

---

### 8. Banker's Algorithm

考慮一個系統的快照如下：

| Process | Allocation (A B C D) | Max (A B C D) | Available (A B C D) |
| :--- | :--- | :--- | :--- |
| P0 | 0 6 0 4 | 1 9 8 9 | A: 1, B: 4, C: 1, D: 3 |
| P1 | 1 0 0 1 | 2 4 2 1 | |
| P2 | 0 1 1 2 | 1 1 2 3 | |
| P3 | 0 0 2 5 | 0 5 5 9 | |
| P4 | 2 1 4 1 | 4 2 6 7 | |

(a) What is the content of the matrix **Need**? (2 points)
(b) Is the system in a **safe state**? Please list the corresponding access sequence. (5 points)
(c.) If a request from process P1 arrives for **(0, 2, 0, 0)**, can the request be granted immediately, why? If it can, please list the corresponding access sequence. (5 points)

#### **解答 (Solution)**

#### (a) 計算需求矩陣 (Need Matrix)

$\text{Need} = \text{Max} - \text{Allocation}$

| Process | Need (A B C D) |
| :--- | :--- |
| P0 | 1 3 8 5 |
| P1 | 1 4 2 0 |
| P2 | 1 0 1 1 |
| P3 | 0 5 3 4 |
| P4 | 2 1 2 6 |

#### (b) 判斷系統是否處於安全狀態 (Safe State)

**Available** $= (1, 4, 1, 3)$

| Step | Process | Need | Available $\ge$ Need? | New Available | 序列 (Sequence) |
| :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | P0 | (1, 3, 8, 5) | False | | |
| | P1 | (1, 4, 2, 0) | False | | |
| | **P2** | **(1, 0, 1, 1)** | **True** | $(1, 4, 1, 3) + (0, 1, 1, 2) = (1, 5, 2, 5)$ | P2 |
| | P3 | (0, 5, 3, 4) | False | | |
| | P4 | (2, 1, 2, 6) | False | | |
| 2 | **P3** | **(0, 5, 3, 4)** | **False** (5 > 5) $\implies$ Need is **(0, 5, 3, 4)**. Wait, Need(P3, B) = 5. Available(B) is now 5. **True** | $(1, 5, 2, 5) + (0, 0, 2, 5) = (1, 5, 4, 10)$ | P2, P3 |
| 3 | **P0** | **(1, 3, 8, 5)** | False (8 > 4) $\implies$ Wait. Let's try P1. | | |
| | **P1** | **(1, 4, 2, 0)** | **True** | $(1, 5, 4, 10) + (1, 0, 0, 1) = (2, 5, 4, 11)$ | P2, P3, P1 |
| 4 | **P4** | **(2, 1, 2, 6)** | **True** | $(2, 5, 4, 11) + (2, 1, 4, 1) = (4, 6, 8, 12)$ | P2, P3, P1, P4 |
| 5 | **P0** | **(1, 3, 8, 5)** | **True** | $(4, 6, 8, 12) + (0, 6, 0, 4) = (4, 12, 8, 16)$ | P2, P3, P1, P4, P0 |

**結論：** **是**，系統處於安全狀態。
**安全序列：** $\langle P2, P3, P1, P4, P0 \rangle$ (或其他有效排列)

#### (c.) 處理 P1 的資源請求 Request(0, 2, 0, 0)

1.  **檢查 1：Request $\le$ Need?**
    * $\text{Request}(0, 2, 0, 0) \le \text{Need}(\text{P}1)(1, 4, 2, 0)$
    * $(0 \le 1, 2 \le 4, 0 \le 2, 0 \le 0) \implies$ **True**

2.  **檢查 2：Request $\le$ Available?**
    * $\text{Request}(0, 2, 0, 0) \le \text{Available}(1, 4, 1, 3)$
    * $(0 \le 1, 2 \le 4, 0 \le 1, 0 \le 3) \implies$ **True**

3.  **暫時分配：**
    * $\text{Available}' = \text{Available} - \text{Request} = (1, 4, 1, 3) - (0, 2, 0, 0) = (1, 2, 1, 3)$
    * $\text{Allocation}'(\text{P}1) = \text{Allocation}(\text{P}1) + \text{Request} = (1, 0, 0, 1) + (0, 2, 0, 0) = (1, 2, 0, 1)$
    * $\text{Need}'(\text{P}1) = \text{Need}(\text{P}1) - \text{Request} = (1, 4, 2, 0) - (0, 2, 0, 0) = (1, 2, 2, 0)$

4.  **執行安全演算法 (Safety Check) - 新狀態：**
    * $\text{Available}' = (1, 2, 1, 3)$

| Step | Process | Need' | Available' $\ge$ Need'? | New Available | 序列 (Sequence) |
| :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | P0 | (1, 3, 8, 5) | False | | |
| | P1 | (1, 2, 2, 0) | False | | |
| | **P2** | **(1, 0, 1, 1)** | **True** | $(1, 2, 1, 3) + (0, 1, 1, 2) = (1, 3, 2, 5)$ | P2 |
| 2 | P0 | (1, 3, 8, 5) | False | | |
| | P1 | (1, 2, 2, 0) | True | $(1, 3, 2, 5) + (1, 2, 0, 1) = (2, 5, 2, 6)$ | P2, P1 | **P3** | (0, 5, 3, 4) | False (3<5) $\implies$ Wait. Let's try P4. | | |
| | **P4** | (2, 1, 2, 6) | True | $(2, 5, 2, 6) + (2, 1, 4, 1) = (4, 6, 6, 7)$ | P2, P1, P4 |
| 4 | **P0** | (1, 3, 8, 5) | False | | |
| | **P3** | (0, 5, 3, 4) | True | $(4, 6, 6, 7) + (0, 0, 2, 5) = (4, 6, 8, 12)$ | P2, P1, P4, P3 |
| 5 | **P0** | (1, 3, 8, 5) | True | $(4, 6, 8, 12) + (0, 6, 0, 4) = (4, 12, 8, 16)$ | P2, P1, P4, P3, P0 |

**結論：** **可以**立即批准請求。因為新狀態仍是安全的。
**對應的安全序列：** $\langle P2, P1, P4, P3, P0 \rangle$

---

### 9. 當 page size 增加時，下列特性如何變化，並說明原因。

* (a) Fragmentation (碎片)
    * 增加，頁面越大，最後一頁未使用的空間越多，內部碎片增加。
* (b) Page table size (頁表大小) 
    * 減少，在相同總記憶體下，頁面數減少，因此頁表中的條目數量減少。
* (c.) Resolution (解析度/分辨度) 
    * 減少，記憶體被劃分為更大的塊，位址轉換和記憶體管理變得更粗略。
* (d) I/O time (輸入/輸出次數) 
    * 減少，每次 I/O 傳輸的資料量增加，減少了總 I/O 次數。
* (e) Number of page faults (頁錯誤次數) 
    * 減少，根據空間局部性，一次載入更多鄰近資料，命中率提高，減少缺頁。
* (f) Locality (區域性/局部性)
    * 不相關的資料也被載入，增加「無用資料」的比例，locality 下降
* (G) TLB size and effectiveness: 
    * 

---

### Banker's Algorithm

確保在分配資源給行程時，系統仍能找到一個**安全序列 (Safe Sequence)**，即所有行程都能在有限時間內完成執行的次序。

#### 四個關鍵數據結構

* **Available (可用資源向量):** 一個長度為 $m$ 的向量，表示每種資源類型當前有多少個可用的實例。
    * *例：* $\text{Available}[j] = k$ 表示資源 $R_j$ 還有 $k$ 個實例可供分配。
* **Max (最大需求矩陣):** 一個 $n \times m$ 的矩陣，表示每個行程 $P_i$ 對每種資源 $R_j$ 的**最大需求**數量。
* **Allocation (分配矩陣):** 一個 $n \times m$ 的矩陣，表示每種資源類型當前已分配給每個行程 $P_i$ 的實例數量。
* **Need (需求矩陣):** 一個 $n \times m$ 的矩陣，表示每個行程 $P_i$ 還需要的資源實例數量。
    * 計算公式：$\text{Need}[i, j] = \text{Max}[i, j] - \text{Allocation}[i, j]$。
    * 目前需要的 = 最大需求量 - 已經分配的

#### 安全狀態 (Safe State) 檢查演算法

系統在分配資源前，必須執行安全檢查演算法來判斷新的狀態是否安全。

1.  **初始化:** 設置兩個向量：
    * **Work (工作向量):** 初始化為 $\text{Work} = \text{Available}$。
    * **Finish (完成向量):** 初始化為 $n$ 個 $\text{False}$，表示所有行程尚未完成。
2.  **查找:** 尋找一個滿足以下兩個條件的行程 $P_i$：
    * (a) $\text{Finish}[i] == \text{False}$ (該行程尚未完成)。
    * (b) $\text{Need}_i \le \text{Work}$ (目前需求 <= 系統的工作量)。
3.  **執行:** 如果找到這樣的行程 $P_i$：
    * 假設 $P_i$ 獲得所需資源並執行完成，釋放其已分配的資源。
    * 更新 $\text{Work} = \text{Work} + \text{Allocation}_i$。
    * 設置 $\text{Finish}[i] = \text{True}$。
    * 返回步驟 2 繼續查找下一個行程。
4.  **結束:** 如果找不到滿足步驟 2 條件的行程，檢查所有行程是否都已完成。
    * 如果所有 $\text{Finish}[i]$ 都是 $\text{True}$，則系統處於**安全狀態**。
    * 如果至少有一個 $\text{Finish}[i]$ 是 $\text{False}$，則系統處於**不安全狀態 (Unsafe State)**，可能導致死鎖。
    

#### Resource-Request Algorithm

當行程 $P_i$ 提出資源請求 $\text{Request}_i$ 時，系統會執行以下步驟來決定是否批准分配：

1.  **檢查需求:** 請求的資源量是否超過其最大需求？
    * 如果 $\text{Request}_i \le \text{Need}_i$，則進入下一步。
    * 否則，請求出錯，因為行程要求的資源量超過了其最大聲明。(根本不用那麼多)
2.  **檢查可用性:** 請求的資源量是否超過當前可用資源？
    * 如果 $\text{Request}_i \le \text{Available}$，則進入下一步。
    * 否則，行程必須等待，直到資源可用。(不夠用，要等)
3.  **試探性分配:** 系統**假設**資源已被分配給 $P_i$，並暫時修改狀態：
    * $\text{Available} = \text{Available} - \text{Request}_i$。
    * $\text{Allocation}_i = \text{Allocation}_i + \text{Request}_i$。
    * $\text{Need}_i = \text{Need}_i - \text{Request}_i$。
4.  **安全檢查:** 執行**安全狀態檢查演算法** (步驟 2)。
    * 如果新狀態是**安全**的，則**批准**分配，交易完成。
    * 如果新狀態是**不安全**的，則**拒絕**分配，並**恢復**到原始狀態，行程 $P_i$ 必須等待。

---

### Pseudocode 整理 (必考)

#### 1\. Mutex Locks (互斥鎖) - Spinlock 實現

實現 **Mutual Exclusion (互斥)**，保護 **Critical Section** 。這是最簡單的同步工具 。

| 操作 (Operation) | Pseudocode (偽代碼) | 核心概念 (Key Concept) |
| :--- | :--- | :--- |
| **`acquire()`** (獲取鎖) | $$\begin{array}{l} \text{acquire() \{} \\ \quad \text{while (!available)} \\ \quad \quad \text{; /* busy wait */ }\\ \quad \text{available = false;} \\ \text{\}} \end{array}$$ | **Busy Waiting**：如果鎖不可用 (`!available`)，**Process** 會一直空轉等待 。因此這種鎖被稱為 **Spinlock** 。 |
| **`release()`** (釋放鎖) | $$\begin{array}{l} \text{release() \{} \\ \quad \text{available = true;} \\ \text{\}} \end{array}$$ | 將鎖狀態設為可用，讓其他等待的 **Process** 能夠通過 `acquire()` 。 |
| **原子性要求** | **`acquire()`** 和 **`release()`** 必須是 **Atomic (原子性)** 的 。 |

-----

### 2\. Semaphores (號誌)

**Semaphore** 是一個整數變數，只能被兩個 **Atomic (原子性)** 操作修改：`wait()` 和 `signal()` 。

#### A. Busy Waiting 實現 (原始定義)

這是最簡單的 **Semaphore** 定義，但會導致 **CPU Cycles** 浪費 。

| 操作 (Operation) | Pseudocode (偽代碼)  | 核心概念 (Key Concept) |
| :--- | :--- | :--- |
| **`wait(S)`** | $$\begin{array}{l} \text{wait (S) \{} \\ \quad \text{while S } \leq 0 \\ \quad \quad \text{; // busy wait} \\ \quad \text{S--;} \\ \text{\}} \end{array}$$ | 阻塞 (Block) 直到 $S > 0$，然後將 $S$ 減一 。 |
| **`signal(S)`** | $$\begin{array}{l} \text{signal (S) \{} \\ \quad \text{S++;} \\ \text{\}} \end{array}$$ | 將 $S$ 加一 。 |

#### B. Blocking (阻塞) 實現 (避免 Busy Waiting)

為了解決 **Busy Waiting** 浪費資源的問題，現代 **Semaphore** 實作讓 Process 進入 **Waiting Queue** (等待佇列) 並 **Block (阻塞)** 自己 。

**資料結構：**

```c
typedef struct{
    int value;
    struct process *list; // Pointer to waiting process list
} semaphore;
```

| 操作 (Operation) | Pseudocode (偽代碼)  | 核心概念 (Key Concept) |
| :--- | :--- | :--- |
| **`wait(S)`** | $$\begin{array}{l} \text{wait(semaphore *S) \{} \\ \quad \text{S->value--;} \\ \quad \text{if (S->value < 0) \{} \\ \quad \quad \text{add this process to S->list;} \\ \quad \quad \text{sleep();} \\ \quad \text{\}} \\ \text{\}} \end{array}$$ | 如果 $S \rightarrow value < 0$，表示資源被佔用或計數不足，**Process** 加入 **Waiting List** 後調用 **`sleep()`** 暫停 。 |
| **`signal(S)`** | $$\begin{array}{l} \text{signal(semaphore *S) \{} \\ \quad \text{S->value++;} \\ \quad \text{if (S->value <= 0) \{} \\ \quad \quad \text{remove a process P from S->list;} \\ \quad \quad \text{wakeup(P);} \\ \quad \text{\}} \\ \text{\}} \end{array}$$ | 如果 $S \rightarrow value \leq 0$，表示有 **Process** 正在等待，移除其中一個 **Process P**，並調用 **`wakeup(P)`** 恢復其執行 。 |

-----

### 3\. Monitors (管程)

**Monitor** 本身是一個程式語言的構造，它在語言層面保證了對 **Shared Data** 的 **Mutual Exclusion** (互斥) 。

#### A. 核心概念：Condition Variables (條件變數)

**Monitor** 內部的同步等待是通過 **Condition Variables** 實現的，它沒有值，但有兩個方法：

| 操作 (Operation) | 作用 (Function) | 核心概念 (Key Concept) |
| :--- | :--- | :--- |
| **`x.wait()`** | 暫停調用操作的 **Process**，放入該 **Condition Variable** 的 **Waiting List** 。 | **Process** 釋放 Monitor 的 **Mutual Exclusion** 鎖，並等待特定 **Event** 發生 。 |
| **`x.signal()`** | 恢復一個 (如果有的話) 正在調用 **`x.wait()`** 的 **Process** 。 | **Signal** 如果沒有 **Waiting Process** 將會被**丟失** 。 |

#### B. Monitor 的 Semaphore 實現結構

儘管 **Monitor** 本身是高級語言結構，但其內部 **Mutual Exclusion** 和 **Condition Variables** 的語義通常是用 **Semaphores** 實現的 。

| Semaphore/Counter | 初始值 (Initial Value) | 用途 (Purpose) |
| :--- | :--- | :--- |
| **`mutex`** | 1 | 確保 Monitor 內的**互斥** (只有一個 Process 在執行) 。 |
| **`next`** | 0 | 用於 **Signaling Process** 暫時等待，以便將 **Monitor** 釋放給被喚醒的 **Process** (防止互斥違規) 。 |
| **`next_count`** | 0 | 記錄有多少 **Process** 因 **Signal** 而暫時等待在 `next` **Semaphore** 上 。 |

> 由於 **Monitor** 的實作細節較為複雜且依賴於 **Semaphore** 的 `wait/signal` 邏輯，教授可能更傾向於直接測試 **Bounded-Buffer** 或 **Dining-Philosophers** 這些經典問題中 **Semaphore** 的應用程式級 **Pseudocode**。

### 必考的經典同步問題 Pseudocode

#### 1\. Bounded-Buffer Problem (有限緩衝區問題)

**Semaphore 設置：** `mutex=1` (互斥鎖), `empty=N` (空位數), `full=0` (數據數)。 

| 角色 (Role) | Pseudocode (偽代碼)  | 關鍵步驟|
| :--- | :--- | :--- |
| **Producer (生產者)** | $$\begin{array}{l} \text{do \{} \\ \quad \text{// produce an item in nextp} \\ \quad \mathbf{\text{wait (empty)};} \\ \quad \mathbf{\text{wait (mutex)};} \\ \quad \text{// add the item to the buffer} \\ \quad \mathbf{\text{signal (mutex)};} \\ \quad \mathbf{\text{signal (full)};} \\ \quad \text{\} while (TRUE);} \end{array}$$ | **1. `wait(empty)`**: 確保有空位可放 (數量控制) 。<br> **2. `wait(mutex)`**: 確保互斥存取 Buffer 。 |
| **Consumer (消費者)** | $$\begin{array}{l} \text{do \{} \\ \quad \mathbf{\text{wait (full)};} \\ \quad \mathbf{\text{wait (mutex)};} \\ \quad \text{// remove an item from buffer to nextc} \\ \quad \mathbf{\text{signal (mutex)};} \\ \quad \mathbf{\text{signal (empty)};} \\ \quad \text{// consume the item in nextc} \\ \quad \text{\} while (TRUE);} \end{array}$$ | **1. `wait(full)`**: 確保有數據可取 (數量控制) 。<br> **2. `wait(mutex)`**: 確保互斥存取 Buffer 。 |

> 考點：**順序**。如果 Producer 的 `wait(mutex)` 和 `wait(empty)` 順序顛倒，可能會導致 **Deadlock (死鎖)** 。

#### 2\. Dining-Philosophers Problem (哲學家進餐問題)

**Semaphore 設置：** 陣列 `chopstick[5]` (每根筷子) 初始化為 1 。

| 角色 (Role) | Pseudocode (偽代碼)  | 關鍵步驟 (Critical Steps) |
| :--- | :--- | :--- |
| **Philosopher $i$** | $$\begin{array}{l} \text{While (TRUE) \{} \\ \quad \mathbf{\text{wait (chopstick[i]);}} \\ \quad \mathbf{\text{wait (chopstick[ (i+1)%5]);}} \\ \quad \text{// eat} \\ \quad \mathbf{\text{signal (chopstick[i]);}} \\ \quad \mathbf{\text{signal (chopstick[ (i+1)%5]);}} \\ \quad \text{// think} \\ \text{\}} \end{array}$$ | **Deadlock 條件**：如果所有五位 **Philosophers** 同時執行到第二個 `wait()`，將導致 **Circular Wait (循環等待)**，從而陷入 **Deadlock** 。 |

![image](https://hackmd.io/_uploads/HkqtwaKf-l.png)

### 考古

![image](https://hackmd.io/_uploads/HylDd-6MWg.png)

以下為精簡版、無 emoji、只有文字與計算結果：

---

**已知條件：**

* 磁碟軌道 0–199
* 目前磁頭在 100
* 剛服務完 110，因此方向向左
* 佇列：86, 117, 91, 150, 102

---

#### (a) FCFS

順序：100 → 86 → 117 → 91 → 150 → 102

距離：
14 + 31 + 26 + 59 + 48 = **178**

**FCFS = 178**

---

#### (b) SSTF

排序過程：
100 → 102 → 91 → 86 → 117 → 150

距離：
2 + 11 + 5 + 31 + 33 = **82**

**SSTF = 82**

---

#### (c.) SCAN（方向向左）

左側：91, 86
右側：102, 117, 150

路徑：100 → 91 → 86 → 0 → 102 → 117 → 150

距離：
9 + 5 + 86 + 102 + 15 + 33 = **250**

**SCAN = 250**

---

#### (d) C-SCAN（方向向左）

路徑：100 → 91 → 86 → 0 → 199 → 150 → 117 → 102

距離：
9 + 5 + 86 + 199 + 49 + 33 + 15 = **396**

**C-SCAN = 396**

---

#### (e) LOOK（不掃到邊界）

路徑：100 → 91 → 86 → 102 → 117 → 150

距離：
9 + 5 + 16 + 15 + 33 = **78**

**LOOK = 78**

---

#### 最終答案

* FCFS = 178
* SSTF = 82
* SCAN = 250
* C-SCAN = 396
* LOOK = 78
