久久96国产精品久久久-久久发布国产伦子伦精品-久久精品国产精品青草-久久天天躁夜夜躁狠狠85麻豆

技術員聯盟提供win764位系統下載,win10,win7,xp,裝機純凈版,64位旗艦版,綠色軟件,免費軟件下載基地!

當前位置:主頁 > 教程 > 服務器類 >

linux中斷編程&.amp

來源:技術員聯盟┆發布時間:2018-08-09 12:25┆點擊:

  1.中斷可以隨時的打斷處理機對其他程序的執行,如果被打斷的代碼對系統很重要,那么此時中斷處理程序的執行時間應該是越短越好。

  2.通過上文我們知道,中斷處理程序正在執行時,會屏蔽同條中斷線上的中斷請求;而更嚴重的是,如果設置了IRQF_DISABLED,那么該中斷服務程序執行是會屏蔽所有其他的中斷請求。那么此時應該讓中斷處理程序執行的越快越好。

  上面的幾個例子都要求中斷服務程序的執行時間越短越好。一般的,中斷處理程序會在上半部分執行。而事實上,幾乎所有的情況,上半部分就只執行中斷處理程序。因此,我們可以這樣認為:一個完整的中斷處理流程是由中斷處理程序和下半部分共同完成的。

  這樣劃分是有一定原因的,因為我們必須有一個快速、異步而且簡單的處理程序專門來負責對硬件的中斷請求做出快速響應,與此同時也要完成那些對時間要求很嚴格的操作。而那些對時間要求相對寬松,其他的剩余工作則會在稍候的任意時間執行,也就是在所謂的下半部分去執行。

  總之,這樣劃分一個中斷處理過程主要是希望減少中斷處理程序的工作量(當然了,理想情況是將全部工作都拋給下半段。但是中斷處理程序至少應該完成對中斷請求的相應。),因為在它運行期間至少會使得同級的中斷請求被屏蔽,這些都直接關系到整個系統的響應能力和性能。而在下半段執行期間,則會允許響應所有的中斷。

  和上半段只能通過中斷處理程序實現不同的是,下半部可以通過多種機制來完成:小任務(tasklet),工作隊列,軟中斷。在本博客后續的文章當中你會看到,不管是那種機制,它們均為下半部提供了一種執行機制,比上半部靈活多了。至于何時執行,則由內核負責。

  以上是上下部分劃分的基本概述,通過tasklet和工作隊列機制,你可以更深刻的理解下部分的執行。

  tasklet的實現

  tasklet(小任務)機制是中斷處理下半部分最常用的一種方法,其使用也是非常簡單的。正如在前文中你所知道的那樣,一個使用tasklet的中斷程序首先會通過執行中斷處理程序來快速完成上半部分的工作,接著通過調用tasklet使得下半部分的工作得以完成。可以看到,下半部分被上半部分所調用,至于下半部分何時執行則屬于內核的工作。對應到我們此刻所說的tasklet就是,在中斷處理程序中,除了完成對中斷的響應等工作,還要調用tasklet,如下圖示。

linux中斷編程@amp 三聯

  tasklet由tasklet_struct結構體來表示,每一個這樣的結構體就表示一個tasklet。在中可以看到如下的定義:

  1tasklet_struct

  2{

  3structtasklet_struct *next;

  4unsigned long state;

  5atomic_t count;

  6void(*func)(unsignedlong);

  7unsigned long data;

  8};

  在這個結構體中,第一個成員代表鏈表中的下一個tasklet。第二個變量代表此刻tasklet的狀態,一般為TASKLET_STATE_SCHED,表示此tasklet已被調度且正準備運行;此變量還可取TASKLET_STATE_RUN,表示正在運行,但只用在多處理器的情況下。count成員是一個引用計數器,只有當其值為0時候,tasklet才會被激活;否則被禁止,不能被執行。而接下來的func變量很明顯是一個函數指針,它指向tasklet處理函數,這個處理函數的唯一參數為data。

  使用tasklet

  在使用tasklet前,必須首先創建一個tasklet_struct類型的變量。通常有兩種方法:靜態創建和動態創建。這樣官方的說法仍然使我們不能理解這兩種創建到底是怎么一回事。不夠透過源碼來分析倒是可以搞明白。

  在中的兩個宏:

  1464#define DECLARE_TASKLET(name, func, data)

  2465struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

  3466

  4467#define DECLARE_TASKLET_DISABLED(name, func, data)

  5468struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

  就是我們進行靜態創建tasklet的兩種方法。通過第一個宏創建的tasklet處于激活狀態,再通過調度函數被掛起盡而被內核執行;而通過第二個宏創建的tasklet處于禁止狀態。從兩個宏的定義可以看到,所謂的靜態創建就是直接定義個一個名為name的tasklet_struct類型的變量,并將宏中各個參數相應的賦值給這個name變量的各個成員。注意,兩個宏在功能上差異就在于對name變量count成員的賦值上,具體原因在第一部分已經說明。也許你對ATOMIC_INIT這樣的初始化方式感到疑惑,那么看完定義后,你就會一目了然:

  1//在arch/x86/include/asm/atomic.h中

  215#define ATOMIC_INIT(i) { (i) }

  3//在linux/types.h中

  4190typedef struct{

  5191 intcounter;

  6192} atomic_t;

  與靜態創建相對的是動態創建,通過給tasklet_init函數傳遞一個事先定義的指針,來動態創建一個tasklet。這個函數源碼如下。

  1470void tasklet_init(structtasklet_struct *t,

  2471 void(*func)(unsignedlong), unsignedlongdata)

  3472{

  4473 t->next = NULL;

  5474 t->state = 0;

  6475 atomic_set(&t->count, 0);

  7476 t->func = func;

  8477 t->data = data;

  9478}

  相信你在閱讀上面的代碼是基本上沒有什么難以理解的地方,不過這里還是要特別說明一下atomic_set函數:

  1//在arch/x86/include/asm/atomic.h中

  235static inlinevoidatomic_set(atomic_t *v,inti)

  336{

  437 v->counter = i;

  538}