# 2026q1 Homework1 (warmup) contributed by < wyattsheu > {%hackmd NrmQUGbRQWemgwPfhzXj6g %} ## 探討〈[資訊科技詞彙翻譯](https://hackmd.io/@sysprog/it-vocabulary)〉 * "render" 在電腦圖學語境中為何應強調「如實呈現」?「渲染」一詞喪失什麼關鍵意涵?在 Linux 核心原始程式碼中,"render" 出現在哪些場景、語境又有哪些?翻閱詞典 (善用學校圖書館) 並考據詞源 * 說明 constant 與 immutable 的差異,並探討程式設計中的關鍵考量 * 比較 concurrent 與 parallel 的語意差異,並說明為何「並行」較貼近 concurrent 的本意 * 當我們撰寫 Linux 核心文件,應如何區分 process, thread, task, job 等術語,才能避免跨領域誤解又省去過多的中英並陳? ## 細讀〈[GNU/Linux 開發工具](https://hackmd.io/@sysprog/gnu-linux-dev/)〉 * 確保 Linux 系統已正確安裝,且每天使用 (對比: 在游泳課買泳裝並下水) * 學習 HackMD 的操作,並可正確使用 LaTeX。能夠在 HackMD 筆記中用 LaTeX 語法展現波函數和密度矩陣 * 學習 git 的操作,依據給定的教學錄影實際練習,並知曉 `git rebase` 一類命令的操作 ## 探討〈[解讀計算機編碼](https://hackmd.io/@sysprog/binary-representation)〉 * 為何計算機的加法在固定 $k$ 位元下,本質等價於 $\mathbb{Z}/2^k\mathbb{Z}$ 上的加法? * 答: 若在 $k$ 位元下,只能表示 $2^k$ 種狀態。當加法運算結果超過 $2^k - 1$ 時,硬體電路會因為位元長度限制,捨棄最高的進位位元(即第 $k+1$ 位元),可以看成除以 $2^k$ 取餘數。所以本質等價於 $\mathbb{Z}/2^k\mathbb{Z}$ 上的加法。 其中:$\mathbb{Z}/2^k\mathbb{Z}$代表所有整數在模 $2^k$ 下的餘數集合 * 為何「允許溢位」反而保證封閉性?若不允許溢位,會破壞哪些群的性質? * 答:若不允許溢位,會破壞阿貝爾群的性質:封閉性,因為「封閉性」要求運算結果必須存在於同一集合內,而允許溢位使得集合內的數列能夠成為一個首尾相連的圓環,滿足封閉性。 * 在質數模數 $p$ 下,可用 $a^{-1} \equiv a^{p-2} \pmod p$ 計算反元素,解釋該式如何來自有限群理論,並說明為何此性質僅在「非零元素形成群」時成立。從 Linux 核心實作角度分析: 1) 為何必須確保輸入元素為單位?2) 若傳入零因子會造成什麼風險? * 答: * 為何 $x \mod 2^n \equiv x \mod (2^n - 1)$ 僅對 unsigned 或非負整數安全?從 CVE/CWE 找到相關資訊安全的議題 * 為何 sign extension 僅在「跨圓環」搬移時才有意義?從數學觀點解釋,要一般化相關證明 * 為何 Linux 核心中 unsigned overflow 是 defined behavior,但 signed overflow 是 undefined behavior? * 為何 Linux 核心大量使用 unsigned long 作為時間計數器? * 若模數改為質數 $p$,是否可構成有限域?這和 AES 中 $GF(2^8)$ 有何關聯? * 二補數構成環但非域,這對除法有何限制?找出 Linux 核心原始程式碼對應的案例 * 二補數的設計是否本質上是種 algebraic encoding? * 若將系統時間設計於 $\mathbb{Z}/2^{64}$ 上,其安全極限為何? * 證明 $(\mathbb{Z}/2^k\mathbb{Z}, +)$ 為阿貝爾群,但 $(\mathbb{Z}/2^k\mathbb{Z}, \times)$ 非群 ## 探討〈[你所不知道的C語言:指標篇](https://hackmd.io/@sysprog/c-pointer)〉 * 根據 C99 對 object 的定義,請分析以下程式是否具有未定義行為,並說明理由 `int *foo(void) { int x = 10; return &x; }` 1. 若改成 `static int x = 10;` 結果是否改變? 2. 請用「storage duration」與「lifetime」兩個術語解釋差異。 3. 為何規格明確指出: > The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime. * 以下程式的輸出為何? `int a[3] = {1,2,3}; int *p = a; printf("%zu %zu\n", sizeof(a), sizeof(p));` 1. 為何 array 在 expression 中會 decay 成 pointer,但在 sizeof 中不會? 2. 為何 `&a` 與 `a` 的值相同但型態不同? 3. 用 Graphviz 繪製記憶體示意圖說明以上 * 分析: `double x[3]; int *p = (int *)&x[0]; printf("%d\n", *(p+1));` 1. 為何 pointer arithmetic 的單位取決於 type? 2. 這是否涉及 strict aliasing 問題? 3. 在 ARMv5 或 RISC-V 上可能出現什麼錯誤? * 解釋為何以下程式不會改變 main 中的 ptrA: `void func(int *p) { p = &B; }` 並分析 `void func(int **p) { *p = &B; }` 1. 用 call-by-value 解釋 2. 用 Graphviz 繪製 stack frame 示意圖 3. 為何「雙指標」這個說法在語意上不精確? * 解釋為何以下程式合法: `int main() { return (********puts)("Hello"); }` 1. 依據 C99 6.3.2.1 說明 function designator 的轉換規則。 2. 為何 `*` 的數量不影響結果? 3. 若對 function pointer 使用 `&` 會發生什麼? * 從「儲存-執行模型」角度解釋 `int a = 10; char *p = (char *)&a;` 1. CPU 實際做哪些事? 2. 為何 C 語言可以被視為 assembly 的語法抽象? * 考慮以下程式碼: ```c struct opaque; struct opaque *create(void); void destroy(struct opaque *); ``` 1. 為何可以只 forward declaration? 2. 這如何達成 binary compatibility? 3. 為何 incomplete type 只能搭配 pointer? * 舉出一個程式碼案例,使得以下得以滿足,並用 C99 對 lifetime 的定義精確解釋 * object lifetime 結束 * storage 尚未被重用 * pointer 仍保留原數值 * 但 dereference 屬於 UB * 以下程式在 -O2 下可能輸出什麼? ```c float f = 1.0f; int *p = (int *)&f; *p = 0; printf("%f\n", f); ``` 分析: 1. 是否違反 strict aliasing? 2. 若使用 `memcpy` 是否等價? 3. 為何 C 規格允許 `unsigned char *` 例外? 4. 在不同架構下是否行為不同? * 為何以下二者 ABI 不同? ```c void f(int a[10]); void f(int *a); ``` 比較: ```c void g(int (*a)[10]); ``` 回答: 1. 為何 `sizeof` 結果不同? 2. 為何 `&a` 與 `a` 型別差異重大? 3. 若跨編譯單元宣告不一致會發生什麼? ## 探討〈[linked list 和非連續記憶體](https://hackmd.io/@sysprog/c-linked-list)〉 * 從〈[資訊科技詞彙翻譯](https://hackmd.io/@sysprog/it-vocabulary)〉的角度,探討何以 linked list 翻譯為「鏈結串列」,而非「鏈表」或「連結串列」,而「串列」的詞源又在哪?翻閱詞典和二十世紀出版物來解說 * 教材中使用 `struct ListNode **indir = &head;`,描述以下: 1. `indir` 的型別語意 2. `*indir` 的語意 3. `&(*indir)->next` 的語意 並說明為何這不是「雙指標」,而是「指標的指標」 * 考慮 `prev->next = (*indir)->next; free(*indir);`,分析: 1. `*indir` 在哪一行失去 lifetime? 2. 若先 `free` 再改鏈結會發生什麼? 3. 為何 AddressSanitizer 能偵測? 4. 若在 `-O3` 下編譯器是否可能出現指令的 reorder? * 為何針對鏈結串列的節點走訪 (linked list traversal) 難以被 hardware prefetcher 預測?若使用 `__builtin_prefetch(node->next);` 是否一定改善效能?請記憶體存取圖形角度解釋,並從 git log 探討 Linux 核心的 List API 一度採用 prefetcher 又棄置的考量。 * 針對 Linux 的 merge sort 設計,回答 1. 為何 list_sort 是 stable? 2. 為何不使用 quicksort? 3. 為何 merge sort 適合 linked list? * Linux 核心的 `list_sort` 建構方式不同於 fully-eager bottom-up mergesort,回答 * 推導 worst-case comparison 次數 * 說明為何延遲合併可降低比較次數 * 建立數學上界 * 鏈結串列的新增節點的時間複雜度是 O(1),而陣列 (array) 則是 O(n),但在實際硬體上,陣列可能更快,解釋為何如此並充分量化分析 * 逐一分析[第一週教材列出](https://wiki.csie.ncku.edu.tw/linux/schedule)的**題目 1** 到**題目 7**,確認理解題目且充分作答,並指出參考題解的錯誤和待改進之處 ## 細讀〈[Linux: 作業系統術語及概念](https://hackmd.io/@sysprog/linux-concepts)〉 * 若若一個惡意應用程式成功觸發多次系統呼叫並頻繁進入核心態,是否等同於繞過 user/kernel 隔離?分析: * CPU privilege level * page table 權限位元 * 系統呼叫機制的作用和考量 * fork 作為並行流程的分岔點。假釋一個程式流程包含 $n$ 個 fork 點與 $m$ 個 join 點<推導在最理想無同步成本下,可產生的最大並行行程數上界。 * 若 fork-join 模型可抽象為 [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph),請說明: * critical path 長度如何決定 theoretical speedup * 與 [Amdahl's law](https://en.wikipedia.org/wiki/Amdahl%27s_law) 的關係 * Mach microkernel 將 thread 與 task 分離為獨立物件。比較在 NPTL 之前的 Linux 核心 與 Mach 的設計,在 scheduling abstraction 上的本質差異,而引入 NPTL 之後又如何讓 Linux 具備現代作業系統的關鍵特徵? * 若將 Linux 的 VFS 或 network stack 遷移至 userspace (類似 microkernel multi-server 模型,這在 hybrid kernel 不少見),分析: * context switch 數量變化 * cache locality * fault isolation * worst-case latency * 若 page fault handler 的平均成本為 $T_{pf}$,page fault 發生機率為 $p$,建立整體存取延遲的期望值模型 * scalability 常來自 cache coherence 與 lock 競爭。給定全域計數器使用 spinlock 保護, * 在 $N$ 核系統中,若每核每秒更新 $f$ 次,估算: * coherence traffic * lock contention 成長趨勢 * CPU 排程器是「一堆處理器」與「一堆行程」的多對多映射,在 time-sharing 下,$f : (P, t) \rightarrow C$ 是否應視為時間函數,翻閱經典論文來探討排程考量 * 教材以「卡比吸入能力」比喻 Linux 演化。從以下角度分析: 1. abstraction preservation 2. backward compatibility 3. scalability pressure 4. real-time requirement 討論: * 為何 Linux 在 monolithic 架構下仍能持續擴展? * 哪些 abstraction 是演化關鍵? ## 探討〈[從熱力學第二定律到系統軟體:機率、資訊熵與現代作業系統的大融通](https://hackmd.io/@sysprog/from-entropy-to-os)〉 > 本文致敬《[Consilience: The Unity of Knowledge](https://en.wikipedia.org/wiki/Consilience_(book))》(繁體中文版《知識大融通》) * 將文中提出三項宏觀穩定條件 (尾部可重現、吞吐時間序列分段平穩、排程誤差無長期漂移) 改寫為可被拒絕的統計假說 * 明確寫出 $H_0, H_1$ * 指出檢定方法(例如 ADF test、KPSS、two-sample KS) * 指出文中 i.i.d. 假設在 CPU 排程的追蹤,何時不成立 * 提供數學定義 * 給出 CI 與顯著水準 * 討論 Type I / Type II error * 文件引用 M/G/1 的 P-K 公式 1. 嚴格推導 $E[W_q]$ 對 $E[S^2]$ 的敏感度 2. 證明當 $\rho \to 1$ 時的發散階數 3. 構造一個 lognormal 與 Pareto 分佈: 固定 $E[S]$、改變 $E[S^2]$,隨後比較 tail latency * 針對 EEVDF 的 lag 有界性證明,即 $Lagi(t) = S_i(t) - s_i(t)$ 1. 在流體模型下證明 $\sum_i Lagi(t) = 0$ 2. 在離散 slice 條件下推導誤差界限 3. 推導當 request length 改變時界限如何縮放 4. 驗證 lag 分佈是否穩態 * 熵率優於單次熵 1. 對 `sched_wakeup` 和 `sched_switch` 事件序列,建立 n-gram 模型並計算 entropy rate 2. 設計一個負載 regime change,並比較前後熵率 * 改進數學嚴格性和書寫 1. 補充所有公式的前提條件 2. 區分「方法論類比」與「數學等價」 3. 明確說明適用範圍與失效條件