1. 程式人生 > >第五章 中斷和中斷服務程式

第五章 中斷和中斷服務程式

第五章  中斷和中斷服務程式

一,處理器與外圍裝置進行通訊有兩種方式:

    1,輪詢(效率低下)
    2,中斷
二,中斷原理
    當我們在敲擊鍵盤的時候,鍵盤控制器會發送一箇中斷給處理器,告訴OS有中斷產生,處理器停下當前的工作,轉而由內  核呼叫中斷服務程式。(中斷控制器傳送中斷給處理器的時候,處理器根據中斷號查詢中斷向量表,找到中斷服務程式的入口地址,才能去執行中斷服務程式)。
三,中斷處理程式
    1,在響應中斷的時候,核心會執行一個函式--中斷服務程式(interrupt handler)或者叫做中斷服務例程(interrupt service routine,ISR)。中斷處理程式是裝置驅動程式的一部分。
    2,中斷處理程式與核心其他函式的區別在於:中斷處理程式是由核心呼叫來響應中斷的,運行於中斷上下文(interrupt context)。
    3,中斷處理程式應該儘量快的執行,儘可能快地恢復中斷程式碼的執行。
四,上半部與下半部的對比
    又想讓中斷服務程式儘量快地執行,同時又想讓程式完成儘可能多的工作,這兩個目標顯然是有矛盾的,基於這樣的矛盾,我們把中斷服務程式劃分為兩個部分:上半部(top half)和下半部(bottom half)。
     1,上半部:接收到一箇中斷就馬上開始執行,具有嚴格的時限要求,比如 對硬體裝置的響應和對硬體進行復位,這些工作都是在所有中斷被禁止 的情況下完成的。中斷服務程式是上半部。
     2,下半部:沒有特別嚴格的時限要求,允許稍後完成的工作被劃分到下半部來做。一般來說中斷服務程式返回的時候會立刻執行下半部。
五,註冊中斷服務程式
    驅動程式通過以下的函式來註冊一箇中斷服務程式:
     int request_irq(unsigned int irq,//中斷號
          irqreturn_t (*handler)(int,void *,struct pt_regs*),//中斷服務程式
          unsigned long irqflags,
          const char *devname,//產生中斷的裝置名
          void *dev_id)
   1,irqflags引數可以是0,也可是幾個掩碼(SA_INTERRUPT,SA_SAMPLE_RANDOM,SA_SHIRQ)的或操作。
     SA_INTERRUPT:表明該中斷處理程式是快速中斷處理程式(fast interrupt handler)。加此標誌說明中斷服務程式在禁止 所有中斷的情況之下執行。如果沒有這個標誌的話,除了正在執行的中斷
服務程式對應的那條中斷線遮蔽之外,其他的中斷都是處於啟用狀態。
     SA_SAMPLE_RANDOM:(待考查)。
     SA_SHIRQ:表示可以在多箇中斷處理程式間共享中斷線。在同一個中斷線上的每個中斷處理程式必須設定該標誌。
   2,dev_id主要用於共享中斷線。當一箇中斷處理程式需要釋放的時候,dev_id將提供唯一的資訊,用於標識具體刪除哪個中斷處理程式,如果沒有該標誌,核心無法知道同一個中斷線上到底要刪除哪個中斷服務程式。如果無需共享中斷線,那麼該指標設定為NULL即可。
   request_irq如果呼叫成功則返回0,失敗的話返回非0,最常見的是返回_EBUSY,表示此時中斷線正在被使用,或者沒有設定SA_SHIRQ標誌。
***********************注意點**********************
        request_irq函式可能導致睡眠,所以該函式不能用在中斷上下文和不能阻塞的程序中。原因是:在註冊中斷處理程式的過程中,核心需要在/proc/irq檔案建立一個與中斷對應的項,proc_makedir ()就是用來建立新的procfs項的。proc_makedir()通過proc_create()來對procfs進行設定,而proc_create()會呼叫kmalloc()來請求分配記憶體。而kmalloc()是可以睡眠的。
************************注意點*********************
   釋放中斷處理程式:
     void free_irq(unsigned int irq,void *dev_id);
    如果指定的中斷
線未設定共享標誌,那麼在刪除中斷處理程式的同時禁用這條中斷線,如果中斷線是共享的,那麼根據dev_id來刪除指定的中斷處理程式。而只有等到該中斷線上的所有中斷處理程式都刪除完了才會禁用該中斷線。
六,編寫中斷處理程式
   1,static irqreturn_t (*handler)(int irq,void *dev_id,struct pt_regs* regs)irq指中斷號,dev_id和request_irq中的dev_id必須一致。
七,中斷上下文
    當執行一箇中斷處理程式或者下半部時,核心執行在中斷上下文。因為中斷沒有程序的背景,所以中斷上下文中不能睡眠(核心排程的單位是程序,要進行的是程序上下文切換)。另外,中斷處理程式並沒有自己的棧,它共享被中斷程序的核心棧。如果沒有正在執行的程序,它就使用idle程序棧。

第六章 中斷下半部(bottom half)

一,什麼是下半部?
    下半部就是與中斷處理密切相關,但是中斷處理程式本身不執行的工作。
二,為什麼要用下半部?
     中斷處理程式執行的時間應該儘量的短,因為在中斷服務例程執行期間,當前的中斷
線會被遮蔽(如果設
     置了SA_INTTERUPT則會遮蔽所有的中斷),這樣其他的中斷就極有可能無法得到處理器的響應。為此,
     為了儘量縮短中斷服務程式的執行,我們要把一些對時間要求不嚴格的工作推遲去作。這就是為什麼需要
     使用下半部的原因。
三,下半部實現方法
     有軟中斷、tasklet、工作佇列,其中tasklet是基於軟中斷實現的。軟中斷是一組靜態定義的下半部
     介面,一共有32個,可以在所有處理器上同時執行(甚至相同型別的軟中斷可以同時執行)。而tasklet則
     沒有這麼寬鬆的條件--相同型別的tasklet是不能同時執行的。對於大部分下半部處理來說,tasklet
     就足夠了,像網路這樣要求非常高的才需要軟中斷。另外,軟中斷是在編譯期靜態註冊的,而tasklet可
     以通過程式碼動態註冊。

四,軟中斷的實現
    軟中斷由softirq_action結構表示,定義在<linux/interrupt.h>中
      struct softirq_action{
          void (*action)(struct softirq_action*);//for process the bottom half
          void *data;//parameter for the function above
      在<kernel/softirq.c>中包含了擁有32個該結構成員的陣列,每個被註冊的softirq佔據陣列的一項,
      所以,最多應該可以有32個softirq,這是一個定值,無法動態改變。
     1,軟中斷處理程式action的函式原型
         void softirq_handler(struct softirq_action*);
            軟中斷不會被另外一個軟中斷搶佔,唯一可以搶佔軟中斷的只有中斷服務程式。但是,其他型別的軟
            中斷,甚至是同類型的軟中斷可以在其他處理器上面執行。
     2,執行軟中斷
         一個軟中斷註冊之後只有被標記了才會執行,這被稱作觸發軟中斷(raising the softirq)。一般的,
         中斷處理程式(上半部)在返回前會標記軟中斷,使其在稍後執行。
          在 以下地方,softirq會被檢查和執行:
                  1)處理完一個硬體中斷(中斷服務程式上半部)
                  2)在ksoftirqd核心執行緒中
                  3)在那些顯示檢查和執行待處理的軟中斷的程式碼中,如網路子系統
            不管是在什麼地方,以什麼樣的方式來喚起softirq,softirq都要在do_softirq()中執行。該函式
            實現比較簡單,就是用迴圈遍歷待處理的softirq,每個都呼叫一下。
     3,使用軟中斷
          軟中斷留給系統中對時間有嚴格要求以及最重要的下半部使用,目前,只有網路子系統和SCSI直接使用軟中斷,像
          核心定時器和tasklet都是建立在軟中斷上的。
          1)分配索引
             在編譯期間,通過<linux/interrupt.h>中的列舉型別來靜態宣告一個軟中斷。核心用從0開始的索引來表示一種
             相對優先順序。index小的比大的優先順序要高。建立一個新的軟中斷必須在此列舉型別中加入新的項。而且加入的
             的時候必須根據你希望賦予它的優先順序來決定加入到什麼位置。一般加入到網路相關的項之後,最後一項之前。
          2)註冊軟中斷處理程式
             在執行時通過open_softirq()註冊軟中斷處理程式。該函式有3個引數:軟中斷索引號,中斷處理函式指標,還
             有就是data資料域指標。
          3)觸發軟中斷
             在列舉型別列表中新增新項以及通過open_softirq()之後軟中斷服務程式就可以執行了,raising_softirq()函式
             可以將軟中斷設定為一個掛起狀態,讓它在下次do_softirq()的時候投入執行。
五,Tasklets
    tasklets是建立在軟中斷上的,換句話說,tasklets本身就是一種軟中斷。tasklets由兩類軟中斷表示:HI_SOFTIRQ和
    TASKLET_SOFTIRQ,兩者的唯一區別就是前者比後者的優先順序高。
    1,tasklet結構體,定義在<linux/interrupt.h>中
       struct tasklet_struct{
          struct tasklet_struct *next;
          unsigned long state;
          atomic_t count;
          void (*func)(unsigned long);
          unsigned long data;
        }
       func函式指標是tasklet中斷處理函式,data是函式引數,state是tasklet的狀態,有0,TASKLET_STATE_SCHED和
       TASKLET_STATE_RUN。TASKLET_STATE_SCHED表示tasklet已經被排程,準備投入執行,而TASKLET_STATE_RUN則
       表示tasklet正在執行。count是引用計數器,當count不為0時,tasklet被禁止,為0時,tasklet才被啟用。
   2,排程tasklets
      已排程的tasklet存放在兩個單處理器資料結構:tasklet_vec和tasklet_hi_vec。這兩個結構都是由tasklet_struct
      組成的,每一個節點代表不同的tasklet。
      tasklets由tasklet_schedule()和tasklet_hi_schedule()函式進行呼叫。以下是tasklet_schedule()的執行細節:
      1)如果tasklet的狀態是TASKLET_STATE_SCHED,則說明tasklet已經被排程,函式立即返回。
      2)儲存中斷狀態,然後禁止中斷,這樣可以保證處理器資料不會混亂。
      3)把需要排程的tasklet加到tasklet_vec或tasklet_hi_vec連結串列中。
      4)喚起TASKLET_SOFTIRQ或HI_SOFTIRQ,這樣下一次在do_softirq()中就會執行該tasklet。
      5)恢復中斷到原狀態並返回。

相關推薦

構建之法 團隊流程

ini 之前 組織 第五章 團隊 mod 交互 然而 逆轉 典型的團隊開發模式和流程,完全是新的內容;涉及到更多的術語和有意思的策略性東西 1.團隊模式【我比較認可的】 主治醫師模式 由首席程序員(相當於首席醫生)負責整個工程,周圍人員各司其職,配合支持中心人物的工作;

團隊流程隨筆

步驟 但是 位置 產品 地理位置 開始 如果 軟件 流程 軟件團隊的模式: 主治醫師模式、明星模式、社區模式、業余劇團模式、秘密團隊、特工團隊、交響樂團模式、爵士樂模式、功能團隊模式、官僚模式。 瀑布模型的特點: 強調階段的順序性和依賴性,即下一個階段的開始必須以上一個階段

團隊流程

成員 指揮 規模 聊天 局限性 功能 其他 分析 混沌 團隊有一致的集體目標,團隊要一起完成這目標。一個團隊的成員不一定要同時工作,例如接力賽跑。 團隊成員有各自的分工,互相依賴合作,共同完成任務。 軟件團隊有各種形式,適用於不同的人員和需求。基於直覺形成的團隊模式未必是最

構建之法( 團隊流程)

功能 實用 運用 驗證 的人 秘密 開發 個性化 社區 第五章主要講了典型的軟件團隊模式和開發流程。以及我們也將討論團隊模式和開發效率之間的一些關系。 1.非團隊和團隊 團隊的主要特點: 1) 團隊有一致的集體目標,團隊要一起完成這個目標。一個團

《C++ Primer Plus》學習筆記—— 迴圈關係表示式(一)

本章內容: for迴圈和while迴圈 表示式和語句 運算子組合 複合語句 逗號運算子以及關係運算符 typedef工具 字元輸入方法get() 檔案尾條件 巢狀迴圈和二維陣列 計算機除了儲存資料外,還可以做很多其他工作。可以對資料進

LinuxC預習——陣列指標

1、陣列和指標的不同 答: 陣列和指標在很多情況下是可以等效使用,但是本質還是不同的。比如在定義了一個數組 char a1[MAX]; 之後,不能宣告一個 extertn char *a1; 2、陣列使用常見一些問題 2.1 陣列下標都是從0開始的嗎? 答: 不都是。在使用陣列的時候

Oracle Database 12c DBA文官手冊(8版)——5 開發實現應用程式(續)

5.2、資源管理5.2.1、實現資料庫資源管理需要建立資源計劃、資源消費者組和資源計劃指令。使用資源管理器命令前須建立“未決區域”。針對會話啟用ADMINISTRATOR_RESOURCE_MAANAGER系統許可權將使用者賦給資源消費者組建立資源計劃指令分配相關資源1 切換消費者組2 使用SQL配置檔案5.

Oracle Database 12c DBA文官手冊(8版)——5 開發實現應用程式

1 調整設計:最佳實踐         1.1做盡可能 少的工作             應該簡化應用

[BX]loop指令

[BX] mov ax,[bx] 功能:bx中存放的資料作為一個偏移地址EA,段地址SA預設在ds中,將SA:EA處的資料送入ax中,即:(ax)=((ds)*16+(bx)) mov [bx],ax 功能:bx中存放的資料作為一個偏移地址EA,段地址SA預設在ds中,將ax中的資料送入記憶體SA:E

[BX]loop指令

<1>[BX] 想要完整地描述一個記憶體單元,需要兩種資訊:(1)記憶體單元的地址(2)記憶體單元的長度(型別)。[BX]和[0]有些相似,表示一個記憶體單元,它的偏移地址在bx中。指令mov ax,[bx]的功能為將bx中存放的資料作為一個偏移地址EA,段地址SA預設在ds中,將SA:EA處的

事務遊標

什麼是事務? 1.在資料庫的實際應用中,有時候要把包含有多個步驟的指令當作一個整體來執行。這個整體要麼全部執行成功,要麼全部執行失敗,這就需要考慮事務。 2.事務(TRANSACTION)是由若干條T_SQL指令組成的作為單個邏輯工作單元執行的一系列操作,這些操作作為一個

《C++ Primer Plus》學習筆記—— 迴圈關係表示式(二)

while迴圈 while迴圈是沒有初始化和更新部分的for迴圈,它只有測試條件和迴圈體。 while (test-condition) { body; } //當test-condition為true,即不為0時,執行迴圈體。 編寫延時迴圈 long wai

《C++ Primer Plus》學習筆記—— 迴圈關係表示式(三)

迴圈與文字輸入 迴圈完成的一項最常見最重要的任務:逐字元地讀取來自檔案或鍵盤的文字。 cin物件支援三種不同模式的單字元輸入,其使用者介面各不相同。 使用原始的cin進行輸入: 通過迴圈來讀取鍵盤的文字輸入,則必須有辦法停止讀取。 一種方法是選擇某個特殊的字元(哨兵

《C++ Primer Plus》學習筆記—— 迴圈關係表示式(四)

程式設計練習 1.編寫一個要求使用者輸入兩個整數的程式。該程式將計算並輸出這兩個整數之間(包括這兩個整數)所有整數的和。這裡假設先輸入較小的整數。例如,如果使用者輸入的是2和9,則程式將指出2~9之間的所有整數的和為44. #include <iostream>

分類標註詞彙 ----5.1、5.2節

將詞彙按它們的詞性(parts-of-speech,POS)分類並相應地對他們進行標註,這個過程叫做詞形標註(POS tagging)或者標註。詞性也成為詞類,在本章中重點是利用標記和自動標註文字。 5.1使用詞性標註器 詞形標註器處理一個詞序列,為每個詞附加的

C++ primer Plus(六版)中文版 迴圈關係表示式 程式設計練習答案

第五章 程式設計練習 1. 編寫一個要求使用者輸入兩個整數的程式。該程式將計算並輸出兩個整數之間(包括這兩個整數)所有整數的和。    這裡假設先輸入較小的整數。例如:如果使用者輸入的是2和9,則程式將指出2~9 之間所有的整數的和為44. 1.1 for 迴圈版 #incl

Linux學習之路:檔案目錄管理(1)

備註:屬於個人分享,文章如有問題請留言,謝謝! 第五章檔案和目錄管理 1、絕對路徑和相對路徑 絕對路徑:一定是由根目錄(/)寫起的,例如:cd /etc/sysconfig 相對路徑:不是由根目錄(/)寫起,例如:cd etc 命令cd          cd切換

考研題目 陣列廣義表

導讀:   一、選擇題   1.設有一個10階的對稱矩陣A,採用壓縮儲存方式,以行序為主儲存,a11為第一元素,其儲存地址為1,每個元素佔一個地址空間,則a85的地址為( )。【燕山大學2001 一、2 (2分)】   A. 13 B. 3

Kotlin 從學習到 Android 返回跳轉

在 Kotlin 中,有三種返回和跳轉語句: return 從最近的一個封閉函式或匿名函式中返回; break 跳出最近的封閉迴圈; continue 繼續執行最近封閉迴圈的下一步; 上面這三個表示式也能夠作為其他表示式的一部分: val s = pe

《資料結構》二叉樹 教學設計

第五章節,是很重要的一章節,本設計屬於遲到的了。抱歉。 本章學習總時問分為2周,共四次課來來學習。兩次上課(10週週一和11週一和週四),一次實驗(12週週四)。以下是教學設計。 第五章 樹和二叉樹   教學設計 一、課前預習任務 學習資料   資料1. 教材第三章P