contributed by < LinMarc1210
>
先編譯並產生 simrupt.ko
檔案並使用以下命令掛載 simrupt 模組,並輸出 /dev/simrupt
的內容,可以看到每秒會輸出一個字元。
bpftrace 用來追蹤的命令:sudo bpftrace [OPTIONS]
先搞懂幾個 bpftrace 的行為:
tracepoint
: kernel static tracingkprobe
: kernel dynamic tracing,附加於要追蹤的函式的進入點kretprobe
: 附加於要追蹤的函式的返回點comm
: 目前執行緒的 command name,根據 comm
值可區分 deffered work 的執行來源:
kworker/uX:Y
:執行於 workqueue context,具備可睡眠能力的獨立核心執行緒 (kernel thread for workqueue)ksoftirqd/N
:代表由 softirq daemon 延後執行 taskletswapper/N
: idle,N
為 tid
systemd-journal
, cat
等):代表 softirq 被直接執行於該行程的核心脈絡中使用以下命令追蹤:
其概念可想成 tracepoint 設在 /dev/simrupt
的位置,並且當我們另外開啟新的視窗並輸入 sudo touch /dev/simrupt
的時候,可以在原本的視窗看到如以下輸出:
以上是重複執行三次 touch
的輸出,三次的 pid
不同但 comm
相同是因為三次都用 touch,所以 command name 都是 touch,但每次執行時會被當作不同的行程,因此有不同的 pid
。
使用以下命令觀察在我們輸入命令sudo cat /dev/simrupt
,simrupt
模組在執行 tasklet 與 workqueue 函式時的實際執行脈絡:
會得到類似以下的輸出(simrupt 每輸出一個字元就有一組):
可觀察到 workqueue 都是執行於獨立核心執行序,由核心統一管理並且可排程。tasklet 則可能直接執行於使用者行程,也有可能由 ksoftirqd
延遲處理。
在 softirq context 中,pid 通常為 0,因其執行於 interrupt context,不屬於一般行程。
追蹤 simrupt_tasklet_func
(tasklet) 或 simrupt_work_func
(workqueue) 都可以在要監控的函式進入點與返回點分別加入 kprobe
和 kretprobe
,如以下命令:
用 kprobe
加 kretprobe
的組合可以得到 CPU 編號、執行開始與結束時間 (單位: ns)、行程 PID、行程名稱 (comm
,例如 kworker/1:1
) 等資訊。一樣執行 sudo cat /dev/simrupt
以在模組執行時監控函式:
在 simrupt 模組中函式呼叫的關係是 timer_handler
呼叫 simrupt_tasklet_func
,simrupt_tasklet_func
再呼叫 simrupt_work_func
,我們用 kprobe 來觀察他們的關係,就算將 kprobe
追蹤函式的順序調換,也不影響輸出的順序。
接下來參考 2025-04-15 問答簡記 ,得知 simrupt
展現 deffered work 的三層處理:
函式名稱 | comm 名稱範例 | TID | Context 類型 | 說明 |
---|---|---|---|---|
timer_handler |
swapper/0 | 0 | TIMER_SOFTIRQ |
idle context 中的計時器處理 |
simrupt_tasklet_func |
ksoftirqd/0 | 16 | TASKLET_SOFTIRQ |
softirq handler thread |
systemd-journal 等 | 非固定 | direct softirq | softirq 同步執行於現行行程中 | |
simrupt_work_func |
kworker/u8:2, u8:0… | 多變化 | workqueue (kthread) | workqueue 處理延後工作 |
timer_handler
) → TIMER_SOFTIRQsimrupt_tasklet_func
) → TASKLET_SOFTIRQ / direct softirqsimrupt_work_func
) → Process Context有時 tasklet
會在非 ksoftirqd
的行程中執行,這代表 softirq 以「直接」方式於該行程內立即執行。
與前面追蹤 simrupt_work_func
相同,只是這次將時間戳儲存至雜湊表 @start
中,函式返回就會用 (pid, comm)
區分不同工作執行緒的延遲行為。
執行完 sudo cat /dev/simrupt
並在另一個執行 bpftrace 的視窗按下 CTRL+C
就可看到直方圖:
TODO: 藉由 eBPF 觀察 workqueue 排入佇列後,如何由 CPU 排程?當系統存在 real-time (或 deadline) class 的任務時,是否影響 workqueue 的 work 排程呢?