日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

理解Linux中断 (3)【转】

發布時間:2025/3/17 linux 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解Linux中断 (3)【转】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.csdn.net/tommy_wxie/article/details/7425712

版權聲明:本文為博主原創文章,未經博主允許不得轉載。 4、下半部 在中斷處理過程中,不能睡眠。另外,它運行的時候,會把當前中斷線在所有處理器上都屏蔽(在ack中完成屏蔽);更糟糕的情況是,如果一個處理程序是SA_INTERRUPT類型,它執行的時候會禁上所有本地中斷(通過cli指令完成),所以,中斷處理應該盡可能快的完成。所以Linux把中斷處理分為上半部和下半部。 上半部由中斷處理程序完成,它通常完成一些和硬件相關的操作,比如對中斷的到達的確認。有時它還會從硬件拷貝數據,這些工作對時間非常敏感,只能靠中斷處理程序自己完成。而把其它工作放到下半部實現。 下半部的執行不需要一個確切的時間,它會在稍后系統不太繁忙時執行。下半部執行的關鍵在于運行的時候允許響應所有的中斷。最早,Linux用”bottom half”實現下半部,這種機制簡稱BH,但是即使屬于不同的處理器,也不允許任何兩個bottom half同時執行,這種機制簡單,但是卻有性能瓶頸。不久,又引入任務隊列(task queue)機制來實現下半部,但該機制仍不夠靈活,沒法代替整個BH接口。 從2.3開始,內核引入軟中斷(softirqs)和tasklet,并完全取代了BH。2.5中,BH最終舍去,在2.6中,內核用有三種機制實現下半部:軟中斷,tasklet和工作隊列。Tasklet是基于軟中斷實現的。軟中斷可以在多個CPU上同時執行,即使它們是同一類型的,所以,軟中斷處理程序必須是可重入的,或者顯示的用自旋鎖保護相應的數據結構。而相同的tasklet不能同時在多個CPU上執行,所以tasklet不必是可重入的;但是,不同類型的tasklet可以在多個CPU上同時執行。一般來說,tasklet比較常用,它可以處理絕大部分的問題;而軟中斷用得比較少,但是對于時間要求較高的地方,比如網絡子系統,常用軟中斷處理下半部工作。4.1、軟中斷 內核2.6中定義了6種軟中斷:下標越低,優先級越高。4.1.1、數據結構 (1)軟中斷向量 [html] view plain copy print? //linux/interrupt.h struct softirq_action { void (*action)(struct softirq_action *); //待執行的函數 void *data; //傳給函數的參數 }; //kernel/softirq.c //軟中斷向量數組 static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp; 內核定義了一個包含32個軟中斷向量的數組,所以最多可有32個軟中斷,實際上,內核目前只使用了6個軟中斷。 (2) preempt_count字段 位于任務描述符的preempt_count是用來跟蹤內核搶占和內核控制路徑嵌套關鍵數據。其各個位的含義如下: 位 描述 0——7 preemption counter,內核搶占計數器(最大值255) 8——15 softirq counter,軟中斷計數器(最大值255) 16——27 hardirq counter,硬件中斷計數器(最大值4096) 28 PREEMPT_ACTIVE標志第一個計數用來表示內核搶占被關閉的次數,0表示可以搶占。第二個計數器表示推遲函數(下半部)被關閉的次數,0表示推遲函數打開。第三個計數器表示本地CPU中斷嵌套的層數,irq_enter()增加該值,irq_exit減該值。 宏in_interrupt()檢查current_thread_info->preempt_count的hardirq和softirq來斷定是否處于中斷上下文。如果這兩個計數器之一為正,則返回非零。 (3) 軟中斷控制/狀態結構 softirq_vec是個全局量,系統中每個CPU所看到的是同一個數組。但是,每個CPU各有其自己的“軟中斷控制/狀態”結構,這些數據結構形成一個以CPU編號為下標的數組irq_stat[](定義在include/asm-i386/hardirq.h中) [html] view plain copy print? typedef struct { unsigned int __softirq_pending; unsigned long idle_timestamp; unsigned int __nmi_count; /* arch dependent */ unsigned int apic_timer_irqs; /* arch dependent */ } ____cacheline_aligned irq_cpustat_t; //位于kernel/softirq.c irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned; 4.1.2、軟中斷初始化 可以通過open_softirq注冊軟中斷處理程序: [html] view plain copy print? <pre name="code" class="html">//位于kernel/softirq.c //nr:軟中斷的索引號 // softirq_action:處理函數 //data:傳遞給處理函數的參數值 void open_softirq(int nr, void (*action)(struct softirq_action*), void *data) { softirq_vec[nr].data = data; softirq_vec[nr].action = action; } //軟中斷初始化 void __init softirq_init(void) { open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL); open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL); }</pre> <pre></pre> 軟中斷執行時,允許響應中斷,但它自己不能睡眠,4.1.3、觸發軟中斷raise_softirq會將軟中斷設置為掛起狀態,并在下一次運行do_softirq中投入運行。 <div class="cnblogs_code"><span style="color:#008000">//</span><span style="color:#008000">位于kernel/softirq.c</span><span style="color:#008000"></span></div> <pre name="code" class="cpp"><pre name="code" class="cpp">void fastcall raise_softirq(unsigned int nr) { unsigned long flags; //保存IF值,并關中斷 local_irq_save(flags); //調用wakeup_softirqd() raise_softirq_irqoff(nr); //恢復IF值 local_irq_restore(flags); } inline fastcall void raise_softirq_irqoff(unsigned int nr) { //把軟中斷設置為掛起狀態 __raise_softirq_irqoff(nr); //喚醒內核線程 if (!in_interrupt()) wakeup_softirqd(); </pre><br> <pre></pre> <pre name="code" class="cpp">該函數觸發軟中斷前,先要關閉中斷,之后再恢復;如果之前中斷已經關閉,可以直接調用raise_softirq_irqoff()觸發軟中斷。 在中斷服務例程中觸發軟中斷是最常見的形式。而中斷服務例程通常作為設備驅動的一部分。例如,對于網絡設備,當接口收到數據時,會產生一個中斷,在中斷服務例程中,最終會調用netif_rx函數處理接到的數據,而netif_rx作相應處理,最終以觸發一個軟中斷結束處理。之后,內核在執行中斷處理任務后,會調用do_softirq()。于是軟中斷就通過軟中斷處理函數去處理留給它的任務。 4.1.4、軟中斷執行 (1) do_softirq()函數 //處理軟中斷,位于arch/i386/kernel/irq.c asmlinkage void do_softirq(void) { //處于中斷上下文,表明軟中斷是在中斷上下文中觸發的,或者軟中斷被關閉 /*這個宏限制了軟中斷服務例程既不能在一個硬中斷服務例程內部執行, *也不能在一個軟中斷服務例程內部執行(即嵌套)。但這個函數并沒有對中斷服務例程的執行 *進行“串行化”限制。這也就是說,不同的CPU可以同時進入對軟中斷服務例程的執行,每個CPU *分別執行各自所請求的軟中斷服務。從這個意義上說,軟中斷服務例程的執行是“并發的”、多序的。 *但是,這些軟中斷服務例程的設計和實現必須十分小心,不能讓它們相互干擾(例如通過共享的全局變量)。 */ if (in_interrupt()) return; //保存IF值,并關中斷 local_irq_save(flags); //調用__do_softirq asm volatile( " xchgl %%ebx,%%esp \n" " call __do_softirq \n" " movl %%ebx,%%esp \n" : "=b"(isp) : "0"(isp) : "memory", "cc", "edx", "ecx", "eax" ); //恢復IF值 local_irq_restore(flags); (2)__do_softirq()函數 //執行軟中斷,位于kernel/softirq.c asmlinkage void __do_softirq(void) { struct softirq_action *h; __u32 pending; /*最多迭代執行10次.在執行軟中斷的過程中,由于允許中斷,所以新的軟中斷可能產生.為了使推遲函數能夠在 *較短的時間延遲內執行,__do_softirq會執行所有掛起的軟中斷,這可能會執行太長的時間而大大延遲返回用戶 *空間的時間.所以,__do_softirq最多允許10次迭代.剩下的軟中斷在軟中斷內核線程ksoftirqd中處理. */ int max_restart = MAX_SOFTIRQ_RESTART; int cpu; //用局部變量保存軟件中斷位圖 pending = local_softirq_pending(); /*增加softirq計數器的值.由于執行軟中斷時允許中斷,當do_IRQ調用irq_exit時,另一個__do_softirq實例可能 *開始執行.這是不允許的,推遲函數必須在CPU上串行執行. */ local_bh_disable(); cpu = smp_processor_id(); restart: /* Reset the pending bitmask before enabling irqs */ //重置軟中斷位圖,使得新的軟中斷可以發生 local_softirq_pending() = 0; //開啟本地中斷,執行軟中斷時,允許中斷的發生 local_irq_enable(); h = softirq_vec; do { if (pending & 1) { //執行軟中斷處理函數 h->action(h); rcu_bh_qsctr_inc(cpu); } h++; pending >>= 1; } while (pending); //關閉中斷 local_irq_disable(); //再一次檢查軟中斷位圖,因為在執行軟中斷處理函數時,新的軟中斷可能產生. pending = local_softirq_pending(); if (pending && --max_restart) goto restart; /*如果還有多的軟中斷沒有處理,通過wakeup_softirqd喚醒內核線程處理本地CPU余下的軟中斷. */ if (pending) wakeup_softirqd(); //減softirq counter的值 __local_bh_enable(); } (3)軟中斷執行點 內核會周期性的檢查是否有掛起的軟中斷,它們位于內核代碼的以下幾個點: (1)內核調用local_bh_enable()函數打開本地CPU的軟中斷: //位于kernel/softirq.c void local_bh_enable(void) { preempt_count() -= SOFTIRQ_OFFSET - 1; if (unlikely(!in_interrupt() && local_softirq_pending())) do_softirq(); //軟中斷處理 //…… } </pre><br> <br> <pre></pre> <pre></pre> <pre></pre> </pre>

?

【作者】張昺華 【出處】http://www.cnblogs.com/sky-heaven/ 【博客園】 http://www.cnblogs.com/sky-heaven/ 【新浪博客】 http://blog.sina.com.cn/u/2049150530 【知乎】 http://www.zhihu.com/people/zhang-bing-hua 【我的作品---旋轉倒立擺】 http://v.youku.com/v_show/id_XODM5NDAzNjQw.html?spm=a2hzp.8253869.0.0&from=y1.7-2 【我的作品---自平衡自動循跡車】 http://v.youku.com/v_show/id_XODM5MzYyNTIw.html?spm=a2hzp.8253869.0.0&from=y1.7-2 【新浪微博】 張昺華--sky 【twitter】 @sky2030_ 【facebook】 張昺華 zhangbinghua 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利.

總結

以上是生活随笔為你收集整理的理解Linux中断 (3)【转】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。