Linux 非強制中斷

來源:互聯網
上載者:User

標籤:

本文轉載自: http://blog.chinaunix.net/uid-9620812-id-3833377.html,如有需要,請移步訪問。

Technorati 標籤: Linux 非強制中斷

---------------------------------------我是分割線----------------------------------------

一、非強制中斷註冊
和硬中斷類似,非強制中斷也有類似的中斷向量表,只不過是用“軟體”實現的。
struct softirq_action softirq_vec[32]是非強制中斷向量表  
(檔案linux_2_6_24/kernel/softirq.c)

  1. struct softirq_action
  2. {
  3.     void (*action)(struct softirq_action *); //鉤子函數
  4.     void *data;                              //鉤子函數的形參
  5. };

核心用到的中斷向量(其實就是數組下標)如下所示
(檔案linux_2_6_24/include/linux/interrupt.h)

  1. enum{
  2.     HI_SOFTIRQ=0, //高優先順序的tasklet
  3.     TIMER_SOFTIRQ,      //核心定時器
  4.     NET_TX_SOFTIRQ,     //網路發送
  5.     NET_RX_SOFTIRQ,     //網路接收
  6.     BLOCK_SOFTIRQ,      //???
  7.     TASKLET_SOFTIRQ,    //普通的tasklet
  8.     SCHED_SOFTIRQ
  9. }

核心註冊一個非強制中斷用函數,本質上就是就是初始化數組某一元素

  1. void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
  2. {   //nr 即非強制中斷向量編號
  3.     softirq_vec[nr].data = data;
  4.     softirq_vec[nr].action = action;
  5. }

核心註冊非強制中斷的地方有:

  1. start_kernel()
  2. -->init_timers()
  3. -->open_softirq(TIMER_SOFTIRQ,run_timer_softirq,NULL)
  4. -->softirq_init()
  5. -->open_softirq(TASKLET_SOFTIRQ, tasklet_action,NULL)
  6. -->open_softirq(HI_SOFTIRQ,tasklet_hi_action,NULL)
  7. -->do_initcall()
  8. -->net_dev_init()
  9. -->open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
  10. -->open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
  11. -->blk_dev_init()
  12. -->open_softirq(BLOCK_SOFTIRQ, blk_done_softirq,NULL)

二、非強制中斷觸發
前面註冊完了,現在開始觸發。
核心用一個資料結構來標記曾經有“非強制中斷”發生過(或者說成非強制中斷被觸發過)
__softirq_pending 共32bit,即每個bit對應非強制中斷的一個向量,實際使用了6個bit
第n個bit置1,即softirq_vec[n]有非強制中斷發生。

  1. typedef struct {
  2.     unsigned int __softirq_pending; /* set_bit is used on this */
  3.     unsigned int __last_jiffy_stamp;
  4. } ____cacheline_aligned irq_cpustat_t;
  5. extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */
  6. #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)
  7. #define local_softirq_pending() \
  8.     __IRQ_STAT(smp_processor_id(), __softirq_pending)
  9. #define set_softirq_pending(x) (local_softirq_pending() = (x))
  10. #define or_softirq_pending(x) (local_softirq_pending() |= (x))
  11. #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)

常用的非強制中斷觸發函數

  1. void raise_softirq_irqoff(int nr){    //nr 即非強制中斷向量編號
  2.     __raise_softirq_irqoff(nr);
  3. }

但這隻是“觸發”非強制中斷,非強制中斷並不會立即被處理
三、非強制中斷處理
函數_ _do_softirq是一次性按照向量表從高到低迴圈處理所有非強制中斷(潛台詞,非強制中斷不可嵌套)
_ _do_softirq()的調用時機:
1. irq_exit() 硬體中斷處理完,返回時調用

  1. do_IRQ() -->irq_exit()
  2. -->local_softirq_pending()
  3. -->_ _do_softirq()

2. ksoftirqd()  用於輔助處理非強制中斷的核心線程,每一個CPU上都運行著一個ksoftirqd。

  1. start_kernel() --> kernel_init() -->do_pre_smp_initcalls()
  2. -->spawn_ksoftirqd() -->cpu_callback()
  3. -->kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu)
  4. -->ksoftirqd()
  5. -->local_softirq_pending()
  6. -->_ _do_softirq()

3. local_bh_enable()時,發現有待處理的非強制中斷且當時沒處在軟硬中斷上下文中

  1. local_bh_enable()
  2. -->local_softirq_pending()
  3. -->_ _do_softirq()

處理過程代碼詳解

  1. asmlinkage void __do_softirq(void)
  2. {
  3.     struct softirq_action *h;
  4.     __u32 pending;
  5. int max_restart = MAX_SOFTIRQ_RESTART;
  6. int cpu;
  7.     pending = local_softirq_pending();
  8.     account_system_vtime(current);
  9. /*非強制中斷處理中,禁止非強制中斷再次進入,非強制中斷處理是不可重新進入的*/
  10.     __local_bh_disable((unsigned long)__builtin_return_address(0));
  11.     trace_softirq_enter();
  12.     cpu = smp_processor_id();
  13. restart:
  14. /* Reset the pending bitmask before enabling irqs
  15.     下面首先清除pending,以便系統可以啟用其它軟體中斷,
  16.     然後使能外部中斷
  17.     系統在下面的處理中,將使能外部中斷以提高系統的響應,
  18.     注意,必須先清除pending,再使能外部中斷,否則死結*/
  19.     set_softirq_pending(0);
  20.     local_irq_enable();
  21.     h = softirq_vec;
  22. /*下面按照從高到低調用open_softirq註冊的控制代碼*/
  23. do {
  24. if (pending & 1) {
  25. h->action(h); //關鍵的一句,tasklet、核心timer、網路中斷都是在這裡搞的
  26.             rcu_bh_qsctr_inc(cpu);
  27. }
  28.         h++;
  29.         pending >>= 1;
  30. } while (pending);
  31.     local_irq_disable();
  32.     pending = local_softirq_pending();
  33. if (pending && --max_restart)
  34.         goto restart;
  35. if (pending)
  36.         wakeup_softirqd();
  37.     trace_softirq_exit();
  38.     account_system_vtime(current);
  39.     _local_bh_enable();
  40. }

Linux 非強制中斷

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.