fb_0413

可以搭配參考 2025-04-15 問答簡記

目前的主要參考資料 〈Linux Kernel Development〉v2.6 (許多 API 已過時) 和 Interrupts and Interrupt Handling

近日我與帥潮繼寬同學一同討論 Linux2025 核心實作第三份作業(kxo),在理解程式碼的過程中遇到不少疑問,查閱資料後仍有許多不解之處。在老師的建議下,發文向各位大神與同學們請益,相關問題整理如下,並附上連結供參考,謝謝大家!

  1. top 與 bottom 的差異是否僅在於「是否屏蔽其他中斷」?
    還是 top 和 bot half 是一種「功能導向」的概念性區分(僅是一種抽象的概念)

原本以為是透過「是否會屏蔽中斷」來區分 top half 和 bottom half,例如 top half 會屏蔽 (Hard IRQ)、bottom half 則不會。不過在閱讀 tasklet_action() 的時候注意到它其實也會使用 local_irq_save() 去關中斷 (繼寬發現的),而根據 〈LKMPG〉 與 〈Linux Kernel Development〉 兩本書,tasklet 又明確被歸類為 bottom half 的一種。
這樣一來,是否就推翻了「以是否屏蔽中斷」作為 top/bottom 劃分依據的說法? 另外我在這兩本書中也沒有找到關於 top/bottom half 劃分的明確定義

  1. 若 top half 與 bottom half 並非僅為抽象概念,在 top half 與 bottom half 各自內部,是否還能依照具體功能再細分出自己的「top / bottom」結構呢?
  2. 討論如何區分兩者(top / bottom half)是否有意義?
  3. tasklet 和 workqueue 的具體差異為何? 它們在 interrupt context 中的角色與行為如何區分?
  4. 如何判斷目前執行環境是否處於 interrupt context? 是透過下方的 MARCO 嘛?
    include/linux/preempt.h
 /*
 * The following macros are deprecated and should not be used in new code:
 * in_irq()       - Obsolete version of in_hardirq()
 * in_softirq()   - We have BH disabled, or are processing softirqs
 * in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled
 */
#define in_irq()		(hardirq_count())
#define in_softirq()		(softirq_count())
#define in_interrupt()		(irq_count())
  1. Interrupt context 與 process context 有哪些具體差異?為何在設計上需要明確區分這兩者? 書中提到 interrupt handler 執行時的場景就稱為 Interrupt context ,程式處於該場景無法進入 sleeping state, 但為何要這樣?
    此外書中強調 Interrupt context 又稱 Atomic context, 在 workqueue 與 tasklet 的比較中也能看到 tasklet 相較與 workqueue 具有 atomic 的特性:

    This means that workqueue functions must not be atomic as tasklet functions.

    "Atomic" 在中斷處理中的意義為何?

已經解決

  1. 在閱讀 Interrupts and Interrupt Handling. Part 9. 時,不理解為什麼會說把 tasklets 存放在 tasklet_vectasklet_hi_vec 的 "Array" 中,這兩者的資料結構不應該是鏈結串列?

    Tasklets and high-priority tasklets are stored in the tasklet_vec and tasklet_hi_vec arrays, respectively

    經過帥潮繼寬的查證,tasklet_vectasklet_hi_vec 都是鏈結串列(It's the head of the linked list in fact),目前也以著手提交 patch 修正!

    Fix incorrect description of tasklet #861,已被 merge ,恨帥潮。

  2. 乘上,透過 tasklet_vec.tail 推斷 tasklet_vec 是鏈結串列,但卻找不到此結構體的定義
    該段落末段提到:

    These two per-cpu variables defined in the same source code file as the softirq_init function and represent two tasklet_head structures.

    因此該變數的結構應該是 struct tasklet_head 沒錯

    ​​​​struct tasklet_head {
    ​​​​        struct tasklet_struct *head;
    ​​​​        struct tasklet_struct **tail;
    ​​​​};
    

    但問題來了,要如何儲存 tasklets ? -> 就是個平凡的 linked list, 但我不知道為何要儲存「指向最後一個元素」的指標? 只有 head 會怎樣?

    ​​​​struct tasklet_struct
    ​​​​{
    ​​​​    struct tasklet_struct *next;
    ​​​​    unsigned long state;
    ​​​​    atomic_t count;
    ​​​​    void (*func)(unsigned long);
    ​​​​    unsigned long data;
    ​​​​};
    

    所以 tasklet_struct 的 *func 會用來除存 handler 的指標


0414: 謝謝仁廷學長的回覆,我禮拜一晚上前會看完並回覆,謝謝!