每當有外部中斷到來時,cpu會停止當前任務的執行而去執行中斷程式,為了提高效率,中斷服務程式不宜太大。
對於乙個較大的外部中斷服務程式,linux將其劃分成2個部分:
(1) 頂半部,不可中斷,不可搶占,執行在(硬)中斷上下文,一般是讀取暫存器狀態,執行內容較少
(2)底半部,可中斷,可搶占,執行在軟中斷上下文,執行大部分的中斷服務程式
它們的關係用圖表示如下:
該機制執行流程如下:
1、tasklet使用tasklet結構體來執行操作
2、建立乙個tasklet執行函式來實現底半部工作
3、建立tasklet結構體:
4、主要函式:
void my_tasklet_func(unsigned long) // 宣告乙個tasklet任務函式
declare_tasklet(my_tasklet.my_tasklet_func,data) // 定義tasklet結構體
tasklet_schedule(&my_tasklet)tasklet任務排程
5、通用模板:
void ***_do_tasklet(unsigned long); //tasklet任務
declare_tasklet(***_tasklet,***_do_tasklet,0); //定義tasklet結構體
void ***_do_tasklet(unsigned long)
irqreturn_t ***_interrupt(int irq,void *dev_id,struct pt_regs *regs)
int _init ***_init(void)
void _exit ***_exit(void)
6、示例:
#include #include #include module_license("gpl");
struct tasklet_struct tasklet_test;
void tasklet_hander_function(unsigned long data)
static int __init tasklet_test_init(void)
static void __exit tasklet_test_exit(void)
module_init(tasklet_test_init);
module_exit(tasklet_test_exit);
1、流程:
2、主要函式:
struct work_struct my_wq; // 定義乙個工作佇列
void my_wq_func(unsigned long); // 宣告乙個處理函式
init_work(&my_wq,(void(*)(void*))my_wq_func,null) // 初始化這個工作佇列並將工作佇列與處理函式繫結
schedule_work(&my_wq) // 排程工作佇列
3、通用模板
struct work_struct ***_wq;
void ***_do_work(unsigned long);
void ***_do_work(unsigned long)
irqreturn_t ***_interrupt(int irq,void *dev_id,struct pt_regs *regs)
int init(void)
void ***_exit(void)
參考: 底半部機制
1 tasklet 只需要定義三段 功能函式 void my tasklet unsigned long data 定義cdd tasklet 變數,繫結my tasklet函式 declare tasklet cdd tasklet,my tasklet,0 tasklet schedule cd...
Linux 中斷底半部
裝置中斷會打斷核心程序的正常執行,系統對更高吞吐率的追求勢必會要求中斷服務程式盡量短小精悍。但是在現實中,中斷服務程式往往要進行大量耗時操作。linux將中斷處理程式分解為兩個部分 頂半部和底半部。頂半部用於完成盡量少的比較緊急的工作,往往只是簡單的讀取暫存器的中斷狀態,並清除中斷標誌後,就進行 登...
底半部機制之work struct(二)
工作佇列 工作佇列的實現和 tasklet 很相似,只是工作佇列的執行上下文在核心執行緒,所以可以排程和睡眠。首先是定義乙個工作佇列和乙個底半部執行函式 structwork struct my wq void my wq func structwork struct work 通過init wor...