




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、linux 內(nèi)核 -中斷處理程序一個設(shè)備的中斷處理程序是它設(shè)備驅(qū)動程序的一部分-設(shè)備驅(qū)動程序是用于對設(shè)備進行管理的內(nèi)核代碼。中斷處理程序與其他內(nèi)核函數(shù)的真正區(qū)別在于,中斷處理程序是被內(nèi)核調(diào)用來響應(yīng)中斷的,而它們運行于我們稱之為中斷上下文的特殊上下文中。中斷與定時器 :中斷的概念 :指 CPU 在執(zhí)行過程中,出現(xiàn)某些突發(fā)事件急待處理, CPU 暫停執(zhí)行當(dāng)前程序, 轉(zhuǎn)去處理突發(fā)事件, 處理完后 CPU 又返回原程序被中斷的位置繼續(xù)執(zhí)行中斷的分類 :內(nèi)部中斷和外部中斷內(nèi)部中斷 :中斷源來自 CPU 內(nèi)部 (軟件中斷指令、溢出、觸發(fā)錯誤等 )外部中斷 :中斷源來自 CPU 外部,由外設(shè)提出請求屏蔽中斷
2、和不可屏蔽中斷 :可屏蔽中斷 :可以通過屏蔽字被屏蔽,屏蔽后,該中斷不再得到響應(yīng)不可屏蔽中斷 :不能被屏蔽向量中斷和非向量中斷 :向量中斷 : CPU 通常為不同的中斷分配不同的中斷號,當(dāng)檢測到某中斷號的中斷到來后,就自動跳轉(zhuǎn)到與該中斷號對應(yīng)的地址執(zhí)行非向量中斷 :多個中斷共享一個入口地址。進入該入口地址后再通過軟件判斷中斷標志來識別具體哪個是中斷也就是說向量中斷由軟件提供中斷服務(wù)程序入口地址,非向量中斷由軟件提供中斷入口地址/* 典型的非向量中斷首先會判斷中斷源,然后調(diào)用不同中斷源的中斷處理程序 */irq_handler().int int_src = read_int_status();
3、/*讀硬件的中斷相關(guān)寄存器*/switch(int_src)/判斷中斷標志caseDEV_A:dev_a_handler();break;caseDEV_B:dev_b_handler();break;.default:break;.定時器中斷原理 :定時器在硬件上也以來中斷,PIT( 可編程間隔定時器)接收一個時鐘輸入,當(dāng)時鐘脈沖到來時,將目前計數(shù)值增1并與已經(jīng)設(shè)置的計數(shù)值比較,若相等,證明計數(shù)周期滿,產(chǎn)生定時器中斷,并復(fù)位計數(shù)值。如下圖所示:Linux 中斷處理程序架構(gòu) :Linux 將中斷分為 :頂半部 (top half) 和底半部(bottom half) 頂半部 :完成盡可能少的比
4、較緊急的功能,它往往只是簡單的讀取寄存器中的中斷狀態(tài)并清除中斷標志后就進行 “登記中斷” (也就是將底半部處理程序掛在到設(shè)備的底半部執(zhí)行隊列中)的工作特點: 響應(yīng)速度快底半部 :中斷處理的大部分工作都在底半部,它幾乎做了中斷處理程序的所有事情。特點:處理相對來說不是非常緊急的事件小知識 :Linux 中查看 /proc/interrupts 文件可以獲得系統(tǒng)中斷的統(tǒng)計信息。如下圖所示:第一列是中斷號第二列是向CPU產(chǎn)生該中斷的次數(shù)介紹完相關(guān)基礎(chǔ)概念后,讓我們一起來探討一下Linux 中斷編程 Linux 中斷編程 :內(nèi)核維護了一個中斷信號線的注冊表,該注冊表類似于I/O 端口的注冊表。驅(qū)動模塊
5、在使用中斷前要先請求一個中斷通道(或者中斷請求 IRQ ),然后在使用后釋放該通道。在頭文件<linux/interrupt.h>中申明了申請和釋放IRQ 的接口。 1.申請和釋放中斷申請中斷:int request_irq(unsigned intirq,irq_handler_t handler,unsigned long irqflags,const char*devname,void *dev_id)參數(shù)介紹:irq是要申請的硬件中斷號handler是向系統(tǒng)登記的中斷處理程序(頂半部),是一個回調(diào)函數(shù),中斷發(fā)生時, 系統(tǒng)調(diào)用它,將dev_id參數(shù)傳遞給它。irqflags:
6、是中斷處理的屬性,可以指定中斷的觸發(fā)方式和處理方式:觸發(fā)方式:IRQF_TRIGGER_RISING 、 IRQF_TRIGGER_FALLING、IRQF_TRIGGER_HIGH 、 IRQF_TRIGGER_LOW處理方式 :IRQF_DISABLE表明中斷處理程序是快速處理程序,快速處理程序被調(diào)用時屏蔽所有中斷IRQF_SHARED表示多個設(shè)備共享中斷dev_id在中斷共享時會用到,一般設(shè)置為NULL返回值:為0 表示成功,返回-EINV AL表示中斷號無效,返回-EBUSY表示中斷已經(jīng)被占用,且不能共享頂半部的handler 的類型 irq_handler_t 定義為 typedef
7、irqreturn_t (*irq_handler_t)(int,void*);typedef int irqreturn_t;2.釋放 IRQ 有請求當(dāng)然就有釋放了void free_irq(unsigned intirq,void *dev_id); 參數(shù)定義與request_irq 類似 3.使能和屏蔽中斷 void disable_irq(int irq);/ 等待目前中斷處理完成 (最好別在頂板部使用,你懂得 )void disable_irq_nosync(int irq);/ 立即返回 void enable_irq(int irq);/4. 屏蔽本 CPU 內(nèi)所有中斷 :#de
8、finelocal_irq_save(flags)./ 禁止中斷并保存狀態(tài)voidlocal_irq_disable(void);/ 禁止中斷, 不保存狀態(tài)下面來分別介紹一下頂半部和底半部的實現(xiàn)機制底半部機制:簡介 :底半部機制主要有tasklet、工作隊列、軟中斷1.底半部實現(xiàn)方法之一 tasklet(1) 我們需要定義 tasklet 機器處理器并將兩者關(guān)聯(lián)例如:void my_tasklet_func(unsigned long);/* 定義一個處理函數(shù)*/DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);/*上述代碼定義了名為my_tas
9、klet 的 tasklet 并將其與my_tasklet_func() 函數(shù)綁定,傳入的參數(shù)為data*/(2) 調(diào)度tasklet_schedule(&my_tasklet);/ 使用此函數(shù)就能在適當(dāng)?shù)臅r候進行調(diào)度運行tasklet 使用模板 /* 定義 tasklet 和底半部函數(shù)并關(guān)聯(lián) */void xxx_do_tasklet(unsigned long);DECLARE_TASKLET(xxx_tasklet,xxx_do_tasklet,0);/將xxx_tasklet與 xxx_do_tasklet綁定,傳入?yún)?shù)0/* 中斷處理底半部 */void xxx_do_tas
10、klet(unsigned long)./* 中斷處理頂半部*/irqreturn_t xxx_interrupt(int irq,void *dev_id).tasklet_schedule(&xxx_tasklet);/ 調(diào)度底半部./* 設(shè)備驅(qū)動模塊加載函數(shù)*/int _init xxx_init(void)./* 申請中斷 */*/result =request_irq(xxx_irq,xxx_interrupt,IRQF_DISABLED,xxx,NULL);.return IRQ_HANDLED;/* 設(shè)備驅(qū)動模塊卸載函數(shù)*/void _exit xxx_exit(void
11、)./* 釋放中斷 */free_irq(xxx_irq,xxx_interrupt);.2. 底半部實現(xiàn)方法之二- 工作隊列使用方法和tasklet 類似相關(guān)操作:struct work_struct my_wq;/*定義一個工作隊列*/void my_wq_func(unsigned long);/*定義一個處理函數(shù) */ 通過 INIT_WORK()可以初始化這個工作隊列并將工作隊列與處理函數(shù)綁定INIT_WORK(&my_wq,(void(*)(void *)my_wq_func,NULL);/*初始化工作隊列并將其與處理函數(shù)綁定 */schedule_work(&my
12、_wq);/*調(diào)度工作隊列執(zhí)行 */* 工作隊列使用模板*/* 定義工作隊列和關(guān)聯(lián)函數(shù)*/struct work_struct xxx_wq(unsigned long);voidxxx_do_work(unsigned long);/*中斷處理底半部*/void xxx_do_work(unsigned long)./* 中斷處理頂半部*/irqreturn_t xxx_interrupt(int irq,void *dev_id).schedule_work(&my_wq);/ 調(diào)度底半部.return IRQ_HANDLED;/* 設(shè)備驅(qū)動模塊加載函數(shù)*/int xxx_init
13、(void)./* 申請中斷 */result =request_irq(xxx_wq,xxx_interrupt,IRQF_DISABLED,xxx,N ULL);./* 初始化工作隊列*/INIT_WORK(&my_wq,(void (*)(void *)xxx_do_work,NULL); /* 設(shè)備驅(qū)動模塊卸載函數(shù)*/void xxx_exit(void)./* 釋放中斷 */free_irq(xxx_irq,xxx_interrupt);.中斷共享中斷共享是指多個設(shè)備共享一根中斷線的情況中斷共享的使用方法:(1). 在申請中斷時,使用IRQF_SHARED標識 (2).在中斷
14、到來時, 會遍歷共享此中斷的所有中斷處理程序,直到某一個函數(shù)返回IRQ_HANDLED ,在中斷處理程序頂半部中, 應(yīng)迅速根據(jù)硬件寄存器中的信息參照dev_id參數(shù)判斷是否為本設(shè)備的中斷,若不是立即返回IR1_NONE/*共享中斷編程模板*/irqreturn_t xxx_interrupt(int irq,void*dev_id,struct pt_regs *regs).int status = read_int_status();/* 獲知中斷源 */if(!is_myint(dev_id,status)/* 判斷是否為本設(shè)備中斷 */return IRQ_NONE;/* 不是本設(shè)備中斷
15、,立即返回 */* 是本設(shè)備中斷 ,進行處理 */.return IRQ_HANDLED;/* 返回 IRQ_HANDLER 表明中斷已經(jīng)被處理 */* 設(shè)備模塊加載函數(shù)*/int xxx_init(void)./* 申請共享中斷 */result =request_irq(sh_irq,xxx_interrupt,IRQF_SHARE,xxx,xxx_dev);./* 設(shè)備驅(qū)動模塊卸載函數(shù)*/void xxx_exit()./*釋放中斷*/free_irq(xxx_irq,xxx_interrupt);.內(nèi)核定時器內(nèi)核定時器編程:簡介 :軟件意義上的定時器最終是依賴于硬件定時器實現(xiàn)的,內(nèi)核在
16、時鐘中斷發(fā)生后檢測各定時器是否到期,到期后定時器處理函數(shù)作為軟中斷在底半部執(zhí)行。 Linux 內(nèi)核定時器操作: 1.timer_list 結(jié)構(gòu)體每一個 timer_list 對應(yīng)一個定時器struct timer_liststruct list_head entry;/*定時器列表 */unsignedlong expires;/* 定時器到期時間 */void (*function)(unsigned long);/* 定時器處理函數(shù) */unsigned long data;/* 作為參數(shù)被傳遞給定時器處理函數(shù) */struct timer_base_s *base;.; 當(dāng)定時器滿的時候
17、,定時器處理函數(shù)將被執(zhí)行2.初始化定時器voidinit_timer(struct timer_list * timer);/初始化 timer_list 的 entry的 next 為 NULL ,并給 base指針賦值。TIMER_INITIALIZER(_function,_expires,_data);/ 此宏用來 / 賦值定時器結(jié)構(gòu)體的 function 、 expires、 data 和 base成員 #define TIMER_INITIALIZER(function,_expires,_data).entry = .prev = TIMER_ENTRY_STATIC,.func
18、tion= (_function),.expires = (_expire), .data = (_data),.base =&boot_tvec_bases,DEFINE_TIMER(_name,_function,_expires,_data)/定義一個定時器結(jié)構(gòu)體變量/并為此變量取名_name/還有一個 setup_timer() 函數(shù)也可以用于定時器結(jié)構(gòu)體的初始化,此函數(shù)大家自己去網(wǎng)上查吧3.增加定時器voidadd_timer(struct timer_list * timer);/注冊內(nèi)核定時器,也就是將定時器加入到內(nèi)核動態(tài)定時器鏈表當(dāng)中4.刪除定時器del_timer(s
19、truct timer_list *timer);del_timer_sync()/在刪除一個定時器時等待刪除操作被處理完(不能用于中斷上下文中)5.修改定時器 expiresint mod_timer(struct timer_list *timer,unsigned long expires);/ 修改定時器的到期時間/* 內(nèi)核定時器使用模板*/*xxx設(shè)備結(jié)構(gòu)體 */struct xxx_devstructcdev cdev;.timer_list xxx_timer;/*設(shè)備要使用的定時器*/;/*xxx驅(qū)動中的某函數(shù)*/xxx_funcl(.)struct xxx_dev *dev=
20、 filp->private_data;./*初始化定時器*/init_timer(&dev->xxx_timer);dev->xxx_timer.func tion = &xxx_do_timer;dev->xxx_timer.data = (unsignedlong)dev;/* 設(shè)備結(jié)構(gòu)體指針作為定時器處理函數(shù)參數(shù)*/dev->xxx_timer.expires = jiffes + delays;/*添加 (注冊 )定時器*/add_timer(&dev->xxx_timer);./*xxx 驅(qū)動中的某函數(shù) */xxx_fun
21、c2(.)./* 刪除定時器*/del_timer(&dev->xxx_timer);./*定時器處理函數(shù)*/static void xxx_do_timer(unsigned long arg)structxxx_device *dev = (struct xxx_device *)(arg);./*調(diào)度定時器再執(zhí)行 */dev->xxx_timer.expires = jiffes +delay;add_timer(&dev -> xxx_timer);./定時器到期時間往往是在jiffies 的基礎(chǔ)上添加一個時延,若為HZ 則表示延遲一秒內(nèi)核中的延遲工作
22、:簡介 :對于這種周期性的工作, Linux 提供了一套封裝好的快捷機制,本質(zhì)上利用工作隊列和定時器實現(xiàn)這其中用到兩個結(jié)構(gòu)體:(1)structdelayed_workstruct work_struct work;struct timer_listtimer;(2)struct work_structatomic_long_t data;.相關(guān)操作:int schedule_delay_work(struct delayed_work*work,unsigned long delay);/ 當(dāng)指定的delay 到來時delay_work 中的 work 成員的 work_func_t 類型成
23、員 func() 會被執(zhí)行 work_func_t 類型定義如下 :typedef void(*work_func_t)(struct work_struct *work);/delay參數(shù)的單位是 jiffesmescs_to_jiffies(unsigned long mesc);/ 將毫秒轉(zhuǎn)化成jiffes 單位 int cancel_delayed_work(struct delayed_work*work);int cancel_delayed_work_sync(struct delayed_work*work);/ 等待直到刪除 (不能用于中斷上下文)內(nèi)核延遲:短延遲:Linux
24、 內(nèi)核提供了如下三個函數(shù)分別進行納秒、微妙和毫秒延遲 :void ndelay(unsigned long nsecs);void udelay(unsignedlong usecs);void mdelay(unsigned long msecs); 機制 :根據(jù) CPU頻率進行一定次數(shù)的循環(huán)(忙等待 ) 注意 :在 Linux 內(nèi)核中最好不要使用毫秒級的延時,因為這樣會無謂消耗CPU 的資源對于毫秒以上的延時, Linux 提供如下函數(shù)void msleep(unsignedint millisecs);unsigned long msleep_interruptible(unsigned
25、 intmillisecs);/ 可以被打斷void ssleep(unsigned int seconds);/ 上述函數(shù)使得調(diào)用它的進程睡眠指定的時間長延遲:機制 :設(shè)置當(dāng)前 jiffies 加上時間間隔的jiffies ,直到未來的jiffies 達到目標 jiffires/* 實例 :先延遲 100 個 jiffies 再延遲 2s*/unsigned longdelay = jiffies + 100;while(time_before(jiffies,delay);/*再延遲2s*/unsigned long delay =jiffies +2*Hz;while(time_befo
26、re(jiffies,delay);/循環(huán)直到到達指定的時間與 timer_before() 相對應(yīng)的還有一個time_after 睡著延遲 :睡著延遲是比忙等待更好的一種方法機制:在等待的時間到來之前進程處于睡眠狀態(tài),CPU 資源被其他進程使用實現(xiàn)函數(shù)有 :schedule_timeout()schedule_timeout_uninterruptible() 其實在短延遲中的msleep() msleep_interruptible() 本質(zhì)上都是依賴于此函數(shù)實現(xiàn)的下面兩個函數(shù)可以讓當(dāng)前進程加入到等待隊列中,從而在等待隊列上睡眠,當(dāng)超時發(fā)生時,進程被喚醒 sleep_on_timeout(wait_queue_head_t *q,unsigned longtimeout);interruptible_sleep_on_timeout(wait_queue_head_t *q,unsigned long timeout); 在基于 powerpc 的 linux 中, request_irq 里填的是軟件中斷號, 也就是 /proc/interrupts 里的編號很不幸的是他們不是一一對應(yīng),也沒有線性規(guī)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 心理健康調(diào)查問卷匯報
- 湖南省水平考試數(shù)學(xué)試卷
- 鶴壁高三數(shù)學(xué)試卷
- 紅河州中考二模數(shù)學(xué)試卷
- 《網(wǎng)絡(luò)綜合布線》教案 項目5任務(wù)2 施工前準備
- 鎂合金深加工項目可行性研究報告立項申請報告范文
- 中國電磁傳感器行業(yè)市場深度評估及投資策略咨詢報告
- 健康科普教育課件
- 連云港逆變器項目申請報告
- 基于 AI 的精準營銷創(chuàng)新商業(yè)計劃書
- 2025年非營利組織運營師考試試題及答案詳解
- 村干部考公務(wù)員試題及答案
- 校園食品安全和膳食經(jīng)費管理突出問題專項整治工作方案范文
- 住建局停工通知回復(fù)函
- 本地吃喝玩樂商業(yè)計劃書
- 造價咨詢應(yīng)急管理制度
- 2025年《鐵道概論》考試復(fù)習(xí)題庫(含答案)
- 2025農(nóng)商行借款合同模板
- 工商業(yè)光伏項目可行性研究報告
- 2025年福建福州地鐵春季校園招聘105人筆試參考題庫附帶答案詳解
- 公轉(zhuǎn)私提額合同范例
評論
0/150
提交評論