qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Linux 中斷的上半部和下半部

          Linux中斷息息相關的一個重要概念是Linux中斷分為兩個半部:上半部(tophalf)和下半部(bottom half)。上半部的功能是"登記中斷",當一個中斷發生時,它進行相應地硬件讀寫后就把中斷例程的下半部掛到該設備的下半部執行隊列中去。因此,上半部 執行的速度就會很快,可以服務更多的中斷請求。但是,僅有"登記中斷"是遠遠不夠的,因為中斷的事件可能很復雜。因此,Linux引入了一個下半部,來完 成中斷事件的絕大多數使命。下半部和上半部最大的不同是下半部是可中斷的,而上半部是不可中斷的,下半部幾乎做了中斷處理程序所有的事情,而且可以被新的 中斷打斷!下半部則相對來說并不是非常緊急的,通常還是比較耗時的,因此由系統自行安排運行時機,不在中斷服務上下文中執行。
            Linux實現下半部的機制主要有tasklet和工作隊列。
            Tasklet基于Linux softirq,其使用相當簡單,我們只需要定義tasklet及其處理函數并將二者關聯:
            void my_tasklet_func(unsigned long); //定義一個處理函數:
            DECLARE_TASKLET(my_tasklet,my_tasklet_func,data); //定義一個tasklet結構my_tasklet,與
            my_tasklet_func(data)函數相關聯
            然后,在需要調度tasklet的時候引用一個簡單的API就能使系統在適當的時候進行調度運行:
            tasklet_schedule(&my_tasklet);
            此外,Linux還提供了另外一些其它的控制tasklet調度與運行的API:
            DECLARE_TASKLET_DISABLED(name,function,data); //與DECLARE_TASKLET類似,但等待tasklet被使能
            tasklet_enable(struct tasklet_struct *); //使能tasklet
            tasklet_disble(struct tasklet_struct *); //禁用tasklet
            tasklet_init(struct tasklet_struct *,void (*func)(unsigned long),unsigned long); //類似
            DECLARE_TASKLET()
            tasklet_kill(struct tasklet_struct *); // 清除指定tasklet的可調度位,即不允許調度該tasklet
            我們先來看一個tasklet的運行實例,這個實例沒有任何實際意義,僅僅為了演示。它的功能是:在globalvar被寫入一次后,就調度一個tasklet,函數中輸出"tasklet is executing":
          #include
          //定義與綁定tasklet函數
          void test_tasklet_action(unsigned long t);
          DECLARE_TASKLET(test_tasklet, test_tasklet_action, 0);
          void test_tasklet_action(unsigned long t)
          {
          printk("tasklet is executing\n");
          }
          ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
          {
          if (copy_from_user(&global_var, buf, sizeof(int)))
          {
          return - EFAULT;
          }
          //調度tasklet執行
          tasklet_schedule(&test_tasklet);
          return sizeof(int);
          }
            下半部分的任務就是執行與中斷處理密切相關但中斷處理程序本身不執行的工作。在Linux2.6的內核中存在三種不同形式的下半部實現機制:軟中斷,tasklet和工作隊列。
            下面將比較三種機制的差別與聯系。
            軟中斷: 1、軟中斷是在編譯期間靜態分配的。
            2、最多可以有32個軟中斷。
            3、軟中斷不會搶占另外一個軟中斷,唯一可以搶占軟中斷的是中斷處理程序。
            4、可以并發運行在多個CPU上(即使同一類型的也可以)。所以軟中斷必須設計為可重入的函數(允許多個CPU同時操作),
            因此也需要使用自旋鎖來保護其數據結構。
            5、目前只有兩個子系直接使用軟中斷:網絡和SCSI。
            6、執行時間有:從硬件中斷代碼返回時、在ksoftirqd內核線程中和某些顯示檢查并執行軟中斷的代碼中。
            tasklet: 1、tasklet是使用兩類軟中斷實現的:HI_SOFTIRQ和TASKLET_SOFTIRQ。
            2、可以動態增加減少,沒有數量限制。
            3、同一類tasklet不能并發執行。
            4、不同類型可以并發執行。
            5、大部分情況使用tasklet。
            工作隊列: 1、由內核線程去執行,換句話說總在進程上下文執行。
            2、可以睡眠,阻塞。

          posted on 2014-09-28 10:44 順其自然EVO 閱讀(214) 評論(0)  編輯  收藏 所屬分類: linux

          <2014年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 深水埗区| 连平县| 忻州市| 新津县| 易门县| 巨野县| 霍州市| 万宁市| 平谷区| 上思县| 青海省| 闵行区| 萨嘎县| 江华| 吴江市| 莲花县| 繁峙县| 海兴县| 恭城| 辽宁省| 铁岭市| 棋牌| 山丹县| 确山县| 克东县| 伊宁县| 鄱阳县| 延吉市| 文成县| 邛崃市| 乌海市| 彭山县| 饶河县| 新田县| 乐东| 中阳县| 永春县| 济源市| 高安市| 蒲江县| 绥阳县|