技術(shù)員聯(lián)盟提供win764位系統(tǒng)下載,win10,win7,xp,裝機(jī)純凈版,64位旗艦版,綠色軟件,免費(fèi)軟件下載基地!

當(dāng)前位置:主頁 > 教程 > 服務(wù)器類 >

linux中斷編程&.amp

來源:技術(shù)員聯(lián)盟┆發(fā)布時間:2018-08-09 12:25┆點(diǎn)擊:

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

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

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

  這樣劃分是有一定原因的,因?yàn)槲覀儽仨氂幸粋€快速、異步而且簡單的處理程序?qū)iT來負(fù)責(zé)對硬件的中斷請求做出快速響應(yīng),與此同時也要完成那些對時間要求很嚴(yán)格的操作。而那些對時間要求相對寬松,其他的剩余工作則會在稍候的任意時間執(zhí)行,也就是在所謂的下半部分去執(zhí)行。

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

  和上半段只能通過中斷處理程序?qū)崿F(xiàn)不同的是,下半部可以通過多種機(jī)制來完成:小任務(wù)(tasklet),工作隊(duì)列,軟中斷。在本博客后續(xù)的文章當(dāng)中你會看到,不管是那種機(jī)制,它們均為下半部提供了一種執(zhí)行機(jī)制,比上半部靈活多了。至于何時執(zhí)行,則由內(nèi)核負(fù)責(zé)。

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

  tasklet的實(shí)現(xiàn)

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

linux中斷編程@amp 三聯(lián)

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

  1tasklet_struct

  2{

  3structtasklet_struct *next;

  4unsigned long state;

  5atomic_t count;

  6void(*func)(unsignedlong);

  7unsigned long data;

  8};

  在這個結(jié)構(gòu)體中,第一個成員代表鏈表中的下一個tasklet。第二個變量代表此刻tasklet的狀態(tài),一般為TASKLET_STATE_SCHED,表示此tasklet已被調(diào)度且正準(zhǔn)備運(yùn)行;此變量還可取TASKLET_STATE_RUN,表示正在運(yùn)行,但只用在多處理器的情況下。count成員是一個引用計(jì)數(shù)器,只有當(dāng)其值為0時候,tasklet才會被激活;否則被禁止,不能被執(zhí)行。而接下來的func變量很明顯是一個函數(shù)指針,它指向tasklet處理函數(shù),這個處理函數(shù)的唯一參數(shù)為data。

  使用tasklet

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

  在中的兩個宏:

  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 }

  就是我們進(jìn)行靜態(tài)創(chuàng)建tasklet的兩種方法。通過第一個宏創(chuàng)建的tasklet處于激活狀態(tài),再通過調(diào)度函數(shù)被掛起盡而被內(nèi)核執(zhí)行;而通過第二個宏創(chuàng)建的tasklet處于禁止?fàn)顟B(tài)。從兩個宏的定義可以看到,所謂的靜態(tài)創(chuàng)建就是直接定義個一個名為name的tasklet_struct類型的變量,并將宏中各個參數(shù)相應(yīng)的賦值給這個name變量的各個成員。注意,兩個宏在功能上差異就在于對name變量count成員的賦值上,具體原因在第一部分已經(jīng)說明。也許你對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;

  與靜態(tài)創(chuàng)建相對的是動態(tài)創(chuàng)建,通過給tasklet_init函數(shù)傳遞一個事先定義的指針,來動態(tài)創(chuàng)建一個tasklet。這個函數(shù)源碼如下。

  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函數(shù):

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

  235static inlinevoidatomic_set(atomic_t *v,inti)

  336{

  437 v->counter = i;

  538}