# 2025q1 Homework5 (assessment)
contributed by < `HeatCrab` >
## 紀錄閱讀[〈因為自動飲料機而延畢的那一年〉](https://www.opasschang.com/docs/the-story-of-auto-beverage-machine-1)的啟發
當下在閱讀的時候,說實話,看得蠻不舒服的,因作者在整個創業的過程中,基本上都是再麻煩別人,這個創業計畫也是他腦子一熱,自以為是的產物。但是冷靜了一段時間後,我發現我蠻佩服作者的,他非常的有衝勁,做事也都很認真,不懂的事情,會去找資料,去想辦法。儘管整個故事跟過程回首來看,有些過於天馬行空與天真,但是他的在整個創造的過程中,非常的投入,跟我完全是不同的極端。
受到教育體系的影響,我是一個害怕失敗,且畏懼失敗的人。我在大學期間才意識到這件事情,並努力在改善。此外,想到之後,就勇於去嘗試的態度也令我羨慕。身為一個做事前會不停地確認計畫,並思考可能障礙的人,一旦發現實踐過程有過大的障礙,就會選擇不實踐。但這些我思考中的巨大障礙往往也是受限於我有限的認知,所有的錯誤迷思,在真正實作後,往往都不是這麼一回事。我也努力在克服這個部分,但是目前更會是偏向不去想,就是做,但這又是另一個極端,我也正在努力地找平衡中。
最後,我自認沒有受到這篇文章明顯的啟發,但我也藉助這篇文章去反思自身的問題,也從文章中看到一個人努力的過程與創業的艱辛。或許現在的我不懂,但我相信或許有一天回首,這篇文章會帶給我不一樣的感受。
### 課程 5 週之後的感想
依據課程規劃,我想要分為以下幾個部分來討論:
1. 課程測驗與問答互動
在課程中,測驗跟問答互動是兩個很重要的環節。說實話,我一開始的確不是很能理解為什麼課程問答要給這麼一大串程式碼,還要我在短短的時間內,去將問題答出來。但是隨著課程的深入,與我開始閱讀課程指定書籍。我開始理解,測驗其實就如老師說的,並不是要我們在當下完全摸透這個程式碼的運作原理,而是去用所學所得,在短時間內,去分析程式碼的部分功能與整個程式運作的模式。
而課程問答我個人認為是一個很有趣的部份,但是蠻遺憾,因為有時候在課程一不小心分心一下之後,就跟不太上老師跟同學之間思想上的碰撞了,頗為可惜。同樣在課程剛開始時,不是很明白老師問答互動中的意義何在,但是隨著寫作業的過程與自身程度慢慢地加強,開始有跟上老師後,漸漸會有能力去想老師討論這些問題的意義,與這些問題背後的理論知識等,但還是有很多不足,希望繼續加強。
2. 課後作業與觀摩
對於課程作業,我的態度其實蠻簡單的,我自己對自己的要求是,要達到自己心目中該有的程度。可以因為時間的限制導致繳交的作業成果不如作業要求,但是不能因為畏懼或是害怕失敗,而選擇擺爛或是沒有去做。這也是我希望在這堂課可以帶走的一個態度。當沒有作業分數線的要求時,我究竟能做多少東西呢?
在寫作業時,也會觀摩無論是同儕,還是是先人做出的東西。我大多時間都在感嘆:
1. 這些人好厲害,能花這麼多時間在這上面,熱情滿滿。
2. 他們懂得好多,產出的東西也好有邏輯與學問。
我個人期待,可以先慢慢滿足2.之後,當對事物有熱情,我想1.就不會是一件難事了。但慚愧的是,現在網路時代的誘惑實在是太多了,我自制力看起來還是太差了。隨著對這門課的理解越深,我明白,自身投入的越多,收穫就會越多,期許在學期的下半部分,我能花更多心思投入在課程上。
3. 課程教材
這是我對這修課後,印象最深刻的東西。在修課前,我明白這門課,作業量很大,寫不完,也體驗到了。但是我沒有想過,有這麼多的背景知識跟課程教材需要閱讀。每一週去上課,都有新知需要學習,我開始意識到,其實這些知識含量其實不是一個學期能完整吸收的,但的確是我要是要在這個行業深耕,需要了解的。趁這個機會,我也久違的靜下心來閱讀一本書,並翻閱各個課程教材,努力地吸收。我目前決定先將前三年的不足補足。
4. 對系統軟體的開發態度
我一直以為我對明白什麼是軟體工程師,明白我自身學系未來的工作會面臨什麼。但直到我第一次繳交 PR 到 lab0-c 時我才發現,我菜的離譜,也天真的可怕。在第一次跟老師 code review 時,我覺得自己運氣很好,過程中老師充滿耐心並很快地指正我的錯誤並給予修正方向。歷經3個多小時的鏖戰後,我也終於成功繳交人生第一個 PR 。但事後的我也意識到,自己有許多的不足,像是我應該要閱讀好相關文件並注意細節,再繳交等等。這個過程中我發現要成為一個好的開發者,完全是一件不簡單的事,除了需要足夠的背景知識外,也有發現問題的能力,並要有實驗與數據去證明自己的修正是對的,就如同其他理工科系一樣,知識跟實驗,依舊是一個很重要的部分。現在回頭一看,我在大學第四年才意識到這件事情,說晚的確有些晚了,但是對於準備要踏入相關行業的我來說,或許還不算晚。
## 研讀第 1 到第 6 週「[課程教材](https://wiki.csie.ncku.edu.tw/sysprog/schedule)」和 [CS:APP 3/e](https://csapp.cs.cmu.edu/) (至少到第二章)
### Demystifiying the Linux CPU Scheduler 心得與問題紀錄
[拜讀 CPU sched 教科書後隨筆札記](https://hackmd.io/v8_v-nh0QxGqzHyzCZfxOw?both)
:::danger
將內容展開到本頁面
:::
#### 問題與討論:
1.2.3
[printk() 的作用](https://docs.kernel.org/translations/zh_CN/core-api/printk-basics.html)與何謂日誌級別?
2.3.2
page.62 的程式碼中的註解:
```c
/*
* ...(to achieve that we use a multiplier of 1.25.
* If a task goes up by ~10% and another task goes down by ~10% then
* the relative distance between them is ~25%.)
* /
```
觀看去年的專題發表者整理出的[筆記](https://hackmd.io/@sysprog/rkJd7TFX0#23-Completely-Faire-Scheduler-CFS)可以理解10%是怎麼來的,但是為什麼兩者間的相對距離是約莫25%呢?
2.3.3
1. 所以 vruntime 也是一種排程器再決定下一個可以搶佔得任務的權重表示方法,對嗎?
2. fixed-point arithmetic 的計算:
```c
f = (int)(v * 1 << fixedpoint_shift)
```
> 為什麼是左移?是要隔出 fractional part 嗎?
```c
f = (f1 * f2) >> fixedpoint_shift
```
```c
f = f1 / f2 = (f1 * 1/f2) >> fixedpoint_shift
```
> 為什麼這邊又是右移? 因為要將一個 fixed-point 的 fixedpoint_shift 位移量移回來?
### [Linux 核心設計: 不只挑選任務的排程器](https://hackmd.io/@sysprog/linux-scheduler)
複習與重新理解前述閱讀過 CPU sheduled 的 Ch1 - Ch2 內容。
相關資料:[Linux 核心專題: CPU 排程器研究](https://hackmd.io/@sysprog/rkJd7TFX0#Linux-%E6%A0%B8%E5%BF%83%E5%B0%88%E9%A1%8C-CPU-%E6%8E%92%E7%A8%8B%E5%99%A8%E7%A0%94%E7%A9%B6)
「nice 數字越大,代表人越好,會退讓(優先度較低)。」
TODO:(花時間再理解)
1. [RSDL](https://hackmd.io/@sysprog/rkJd7TFX0#22-Prior-to-CFS)
3. [EAS](https://hackmd.io/@sysprog/rkJd7TFX0#%E9%96%B1%E8%AE%80%E4%B8%A6%E5%BD%99%E6%95%B4-EAS-%E7%9B%B8%E9%97%9C%E6%9D%90%E6%96%99)
:::warning
對照 [2025-05-06 問答簡記](https://hackmd.io/@sysprog/rJJtaLLllx)
:::
### 解釋 softirq 是否有 task_struct
> 參考筆記 [2025-04-15 問答簡記](https://hackmd.io/V7bD2XjnQuCZqDMt4ZizGA?view)
1. 定義清楚 task_struct
`task_struct` 是 Linux 核心用來表示一個行程或執行緒的資料型別,包含了進程的狀態、調度信息、記憶體映射等。只有真正的進程或執行緒(例如用戶進程、核心執行緒等)才會有自己的 `task_struct`。
2. 什麼是 softirq ?
> IRQ = interrupt request
是 Linux 核心用來處理延遲工作(deferred work)的機制,屬於 **bottom half** 處理的一部分,用於執行那些不需要立即在 hardirq 上下文完成的任務。
通常在以下情況觸發:
1. **hardirq 返回路徑**:在 hardirq 處理完成後,核心檢查是否有 pending 的 softirq 並執行。
2. **系統呼叫返回前**:在某些進程從核心態返回用戶態之前,核心可能會處理 pending 的 softirq。
3. **ksoftirqd 執行緒**:當 softirq 負載過高時,核心會喚醒 per-CPU 的 `ksoftirqd` 執行緒來處理。
由於 softirq 不屬於任何進程或執行緒,不依賴於 `task_struct`,而是由核心直接調用其 handler (處理函數)。
3. 核心調用 softirq 的方法:`ksoftirqd`
`ksoftirqd` 是 Linux 核心為每個 CPU 創建的一個 kernel thread,用於處理過載的 softirq 任務。當 softirq 的處理次數超過一定閾值(參考筆記中 [Software interrupts and realtime](https://lwn.net/Articles/520076/)),核心會喚醒 `ksoftirqd` 來接手 softirq 的處理。而 `ksoftirqd` 運行在 **process context** 中,是一個可被調度的執行緒,因此它**擁有自己的 `task_struct`**。
但是 `ksoftirqd` 僅是 softirq 處理的載體之一,當它執行 softirq 時,實際上是在模擬 softirq 的處理函數運行,但其執行環境已切換為 process context。這意味著 softirq 的 handler 本身並不依賴 `task_struct`,但當由 `ksoftirqd` 執行時,`ksoftirqd` 的 `task_struct` 提供了調度和上下文管理的支持。
根據筆記中提供的 bpftrace 輸出:
```
tasklet_func: comm=ksoftirqd/2, pid=30, tid=30
work_func: comm=kworker/u8:3, pid=10460, tid=10460
tasklet_func: comm=systemd-journal, pid=306, tid=306
work_func: comm=kworker/u8:3, pid=10460, tid=10460
tasklet_func: comm=in:imklog, pid=834, tid=861
work_func: comm=kworker/u8:0, pid=10254, tid=10254
```
這表明 `simrupt_tasklet_func` 由 `ksoftirqd/2` 執行,`ksoftirqd/2` 是一個核心執行緒,擁有 `pid=30` 和 `tid=30`,對應其 `task_struct`。
然而,若 tasklet 在其他進程(如 `systemd-journal`)的 context 中直接執行, 這表明 softirq 在該進程的返回路徑中直接執行,仍然不涉及 softirq 自身的 `task_struct`,而是借用了當前進程的上下文。
4. softirq 與 tasklet 的關係
根據筆記我們可以知道tasklet 是 softirq 的封裝,但是 **tasklet 本身也沒有 `task_struct`**(如筆記中明確指出 `tasklet_struct ≠ task_struct`)。筆記中也提到 tasklet 可能在以下情況執行:
- direct softirq execution**
> 為何要強調 "direct softirq execution"?
> - softirq 並非執行緒,無明確排程機制
- deferred by ksoftirqd
5. atomic context 與 interrupt context
筆記中說明:
> Interrupt context ⊂ Atomic context
**Interrupt context** 包括 hardirq 、 softirq 和 NMI (非遮蔽中斷) 的執行環境,這些都是 atomic context 的子集。而 **Atomic context** 更廣泛,包括任何不可睡眠的執行環境,例如:
- 中斷處理(hardirq、softirq)。
- 持有 spinlock 的情況。
- 禁用搶佔(preemption disabled)的情況。
其中, softirq 屬於 atomic context,因此不可睡眠,無 `task_struct`。
6. 結論
1. **softirq 無 task_struct**
softirq 不屬於進程或執行緒,因此不具備 `task_struct`。當 softirq 由 `ksoftirqd` 執行時,`ksoftirqd` 作為核心執行緒擁有 `task_struct`,但這是 `ksoftirqd` 的屬性,而非 softirq 本身。
2. **tasklet 與 softirq**
tasklet 是 softirq 的封裝,同樣無 `task_struct`,其執行可能由 `ksoftirqd` 或其他進程上下文觸發。
7. 問題與發想
筆記中有學長提到:
```c=745
static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
```
可以參考 [kernel / softirq.c](https://elixir.bootlin.com/linux/v6.14.5/source/kernel/softirq.c) 中的程式碼定義,知道 softirq 與 tasklet_head 這個資料型別的定義。
可是在同樣的程式碼中的開頭:
```c=37
/*
- No shared variables, all the data are CPU local.
- If a softirq needs serialization, let it serialize itself
by its own spinlocks.
- Even if softirq is serialized, only local cpu is marked for
execution. Hence, we get something sort of weak cpu binding.
Though it is still not clear, will it result in better locality
or will not.
Examples:
- NET RX softirq. It is multithreaded and does not require
any global serialization.
- NET TX softirq. It kicks software netdevice queues, hence
it is logically serialized per device, but this serialization
is invisible to common code.
- Tasklets: serialized wrt itself.
*/
#ifndef __ARCH_IRQ_STAT
DEFINE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
EXPORT_PER_CPU_SYMBOL(irq_stat);
#endif
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
const char * const softirq_to_name[NR_SOFTIRQS] = {
"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL",
"TASKLET", "SCHED", "HRTIMER", "RCU"
};
/*
* we cannot loop indefinitely here to avoid userspace starvation,
* but we also don't want to introduce a worst case 1/HZ latency
* to the pending events, so lets the scheduler to balance
* the softirq load for us.
*/
static void wakeup_softirqd(void)
{
/* Interrupts are disabled: no need to stop preemption */
struct task_struct *tsk = __this_cpu_read(ksoftirqd);
if (tsk)
wake_up_process(tsk);
}
```
也使用了 task_struct 定義了一顆 CPU ,註解的部分我看得有些似懂非懂,但是根據筆記與上述我整理的資料來看, softirq 理論上是沒有 task_struct 定義的,所以這一段的用意為何呢?
## 簡述想投入的專案
開學初的 [ideas](https://hackmd.io/@HeatCrab/H16K4lIj1x)
想投入的專案
> 碩班預計要做 TVM
1. RISC-V 最佳化編譯器實作
2. Linux 排程器研究
3. AI 與 kernal 結合相關?
Bonus: [MazuNIX](https://github.com/MazuNIX)
