linux设备驱动归纳总结(六):3.中断下半部之tasklet
- 博客訪(fǎng)問(wèn):74424
- 博文數(shù)量:42
- 博客積分:687
- 博客等級(jí):中校
- 關(guān)注人氣: 4
- 注冊(cè)時(shí)間:2010-12-01 18:55:26
-
tekkama
-
小雅貝貝
-
luozhiy
-
Knivo
-
embedtek
-
sillybo
-
wang2kk
-
嵌入小凱
-
send_li
-
CU官方博
-
songtao
-
lxhhust
-
fh265
1小時(shí)前 -
shenhai
10月30日 -
a275532
10月14日 -
Knivo
10月13日 -
10月13日 -
lxr215
10月10日 -
luozhiy
10月9日 -
chafe
10月8日 -
mournju
10月7日 -
zotozo
10月7日 -
high_way
10月7日 -
wangxin
10月4日
linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(六):3.中斷的上半部和下半部——tasklet
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
一、什么是下半部
中斷是一個(gè)很霸道的東西,處理器一旦接收到中斷,就會(huì)打斷正在執(zhí)行的代碼,調(diào)用中斷處理函數(shù)。如果在中斷處理函數(shù)中沒(méi)有禁止中斷,該中斷處理函數(shù)執(zhí)行過(guò)程中仍有可能被其他中斷打斷。出于這樣的原因,大家都希望中斷處理函數(shù)執(zhí)行得越快越好。
另外,中斷上下文中不能阻塞,這也限制了中斷上下文中能干的事。
基于上面的原因,內(nèi)核將整個(gè)的中斷處理流程分為了上半部和下半部。上半部就是之前所說(shuō)的中斷處理函數(shù),它能最快的響應(yīng)中斷,并且做一些必須在中斷響應(yīng)之后馬上要做的事情。而一些需要在中斷處理函數(shù)后繼續(xù)執(zhí)行的操作,內(nèi)核建議把它放在下半部執(zhí)行。
拿網(wǎng)卡來(lái)舉例,在linux內(nèi)核中,當(dāng)網(wǎng)卡一旦接受到數(shù)據(jù),網(wǎng)卡會(huì)通過(guò)中斷告訴內(nèi)核處理數(shù)據(jù),內(nèi)核會(huì)在網(wǎng)卡中斷處理函數(shù)(上半部)執(zhí)行一些網(wǎng)卡硬件的必要設(shè)置,因?yàn)檫@是在中斷響應(yīng)后急切要干的事情。接著,內(nèi)核調(diào)用對(duì)應(yīng)的下半部函數(shù)來(lái)處理網(wǎng)卡接收到的數(shù)據(jù),因?yàn)閿?shù)據(jù)處理沒(méi)必要在中斷處理函數(shù)里面馬上執(zhí)行,可以將中斷讓出來(lái)做更緊迫的事情。
可以有三種方法來(lái)實(shí)現(xiàn)下半部:軟中斷、tasklet和等待隊(duì)列。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
二、軟中斷
軟中斷一般很少用于實(shí)現(xiàn)下半部,但tasklet是通過(guò)軟中斷實(shí)現(xiàn)的,所以先介紹軟中斷。字面理解,軟中斷就是軟件實(shí)現(xiàn)的異步中斷,它的優(yōu)先級(jí)比硬中斷低,但比普通進(jìn)程優(yōu)先級(jí)高,同時(shí),它和硬中斷一樣不能休眠。
軟中斷是在編譯時(shí)候靜態(tài)分配的,要用軟中斷必須修改內(nèi)核代碼。
在kernel/softirq.c中有這樣的一個(gè)數(shù)組:
51?static struct softirq_action softirq_vec[NR_SOFTIRQS]?__cacheline_aligned_in_smp;
內(nèi)核通過(guò)一個(gè)softirq_action數(shù)組來(lái)維護(hù)的軟中斷,NR_SOFTIRQS是當(dāng)前軟中斷的個(gè)數(shù),待會(huì)再看他在哪里定義。
先看一下softirq_action結(jié)構(gòu)體:
/*include/linux/interrupt.h*/
265 struct softirq_action
266 {
267 void (*action)(struct softirq_action *); //軟中斷處理函數(shù)
268 };
一看發(fā)現(xiàn),結(jié)構(gòu)體里面就一個(gè)軟中斷函數(shù),他的參數(shù)就是本身結(jié)構(gòu)體的指針。之所以這樣設(shè)計(jì),是為了以后的拓展,如果在結(jié)構(gòu)體中添加了新成員,也不需要修改函數(shù)接口。在以前的內(nèi)核,該結(jié)構(gòu)體里面還有一個(gè)data的成員,用于傳參,不過(guò)現(xiàn)在沒(méi)有了。
接下來(lái)看一下如何使用軟中斷實(shí)現(xiàn)下半部
一、要使用軟中斷,首先就要靜態(tài)聲明軟中斷:
/*include/linux/interrupt.h*/
246 enum
247 {
248 HI_SOFTIRQ=0, //用于tasklet的軟中斷,優(yōu)先級(jí)最高,為0
249 TIMER_SOFTIRQ, //定時(shí)器的下半部
250 NET_TX_SOFTIRQ, //發(fā)送網(wǎng)絡(luò)數(shù)據(jù)的軟中斷
251 NET_RX_SOFTIRQ, //接受網(wǎng)絡(luò)數(shù)據(jù)的軟中斷
252 BLOCK_SOFTIRQ,
253 TASKLET_SOFTIRQ, //也是用于實(shí)現(xiàn)tasklet
254 SCHED_SOFTIRQ,
255 HRTIMER_SOFTIRQ,
256 RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
257 //add by xiaobai 2011.1.18
258 XIAOBAI_SOFTIRQ, //這是我添加的,優(yōu)先級(jí)最低
259
260 NR_SOFTIRQS, //這個(gè)就是上面所說(shuō)的軟中斷結(jié)構(gòu)體數(shù)組成員個(gè)數(shù)
261 };
上面通過(guò)枚舉定義了NR_SOFTIRQS(10)個(gè)軟中斷的索引號(hào),優(yōu)先級(jí)最高是0(HI_SOFTIRQ),最低是我剛添加上去的XIAOBAI_SOFTIRQ,優(yōu)先級(jí)為9。
二、定義了索引號(hào)后,還要注冊(cè)處理程序。
通過(guò)函數(shù)open_sofuirq來(lái)注冊(cè)軟中斷處理函數(shù),使軟中斷索引號(hào)與中斷處理函數(shù)對(duì)應(yīng)。該函數(shù)在kernel/softirq.c中定義:
/*kernel/softirq.c */
321 void open_softirq(int nr, void (*action)(struct softirq_action *))
322 {
323 softirq_vec[nr].action = action;
324 }
其實(shí)該函數(shù)就是把軟中斷處理函數(shù)的函數(shù)指針存放到對(duì)應(yīng)的結(jié)構(gòu)體中,一般的,我們自己寫(xiě)的模塊是不能調(diào)用這個(gè)函數(shù)的,為了使用這個(gè)函數(shù),我修改了內(nèi)核:
322 void open_softirq(int nr, void (*action)(struct softirq_action *))
323 {
324 softirq_vec[nr].action = action;
325 }
326 EXPORT_SYMBOL(open_softirq); //這是我添加的,導(dǎo)出符號(hào),這樣我編寫(xiě)的程序就能調(diào)用
在我的程序中如下調(diào)用:
/*6th_irq_3/1st/test.c*/
13 void xiaobai_action(struct softirq_action *t) //軟中斷處理函數(shù)
14 {
15 printk("hello xiaobai!\n");
16 }
。。。。。。。。
48 open_softirq(XIAOBAI_SOFTIRQ, xiaobai_action);
三、在中斷處理函數(shù)返回前,觸發(fā)對(duì)應(yīng)的軟中斷。
在中斷處理函數(shù)完成了必要的操作后,就應(yīng)該調(diào)用函數(shù)raise_sotfirq觸發(fā)軟中斷,讓軟中斷執(zhí)行中斷下半部的操作。
/*kernel/softirq.c*/
312 void raise_softirq(unsigned int nr)
313 {
314 unsigned long flags;
315
316 local_irq_save(flags);
317 raise_softirq_irqoff(nr);
318 local_irq_restore(flags);
319 }
所謂的觸發(fā)軟中斷,并不是指馬上執(zhí)行該軟中斷,不然和在中斷上執(zhí)行沒(méi)什么區(qū)別。它的作用只是告訴內(nèi)核:下次執(zhí)行軟中斷的時(shí)候,記得執(zhí)行我這個(gè)軟中斷處理函數(shù)。
當(dāng)然,這個(gè)函數(shù)也得導(dǎo)出符號(hào)后才能調(diào)用:
/*kernel/softirq.c*/
312 void raise_softirq(unsigned int nr)
313 {
314 unsigned long flags;
315
316 local_irq_save(flags);
317 raise_softirq_irqoff(nr);
318 local_irq_restore(flags);
319 }
320 EXPORT_SYMBOL(raise_softirq);
在我的程序中如下調(diào)用:
/*6th_irq_3/1st/test.c*/
18 irqreturn_t irq_handler(int irqno, void *dev_id) //中斷處理函數(shù)
19 {
20 printk("key down\n");
21 raise_softirq(XIAOBAI_SOFTIRQ);
22 return IRQ_HANDLED;
23 }
經(jīng)過(guò)三步,使用軟中斷實(shí)現(xiàn)下半部就成功了,看一下完整的函數(shù):
/*6th_irq_3/1st/test.c*/
1 #include <linux/module.h>
2 #include <linux/init.h>
3
4 #include <linux/interrupt.h>
5
6 #define DEBUG_SWITCH 1
7 #if DEBUG_SWITCH
8 #define P_DEBUG(fmt, args...) printk("<1>" "<kernel>[%s]"fmt, __FUNCTI ON__, ##args)
9 #else
10 #define P_DEBUG(fmt, args...) printk("<7>" "<kernel>[%s]"fmt, __FUNCTI ON__, ##args)
11 #endif
12
13 void xiaobai_action(struct softirq_action *t) //軟中斷處理函數(shù)
14 {
15 printk("hello xiaobai!\n");
16 }
17
18 irqreturn_t irq_handler(int irqno, void *dev_id) //中斷處理函數(shù)
19 {
20 printk("key down\n");
21 raise_softirq(XIAOBAI_SOFTIRQ); //觸發(fā)軟中斷
22 return IRQ_HANDLED;
23 }
24
25 static int __init test_init(void) //模塊初始化函數(shù)
26 {
27 int ret;
28
29 /*注冊(cè)中斷處理函數(shù):
30 * IRQ_EINT1:中斷號(hào),定義在"include/mach/irqs.h"中
31 * irq_handler:中斷處理函數(shù)
32 * IRQ_TIRGGER_FALLING:中斷類(lèi)型標(biāo)記,下降沿觸發(fā)中斷
33 * ker_INT_EINT1:中斷的名字,顯示在/proc/interrupts等文件中
34 * NULL;現(xiàn)在我不使用dev_id,所以這里不傳參數(shù)
35 */
36 ret = request_irq(IRQ_EINT1, irq_handler,
37 IRQF_TRIGGER_FALLING, "key INT_EINT1", NULL);
38 if(ret){
39 P_DEBUG("request irq failed!\n");
40 return ret;
41 }
42
43 /*fostirq*/
44 open_softirq(XIAOBAI_SOFTIRQ, xiaobai_action); //注冊(cè)軟中斷處理程序
45
46 printk("hello irq\n");
47 return 0;
48 }
49
50 static void __exit test_exit(void) //模塊卸載函數(shù)
51 {
52 free_irq(IRQ_EINT1, NULL);
53 printk("good bye irq\n");
54 }
55
56 module_init(test_init);
57 module_exit(test_exit);
58
59 MODULE_LICENSE("GPL");
60 MODULE_AUTHOR("xoao bai");
61 MODULE_VERSION("v0.1");
注意。在上面的程序,只是為了說(shuō)明如何實(shí)現(xiàn)上下半步,而我的中斷上下半步里面的操作是毫無(wú)意義的(只是打印)。上下半步的作用我在一開(kāi)始就有介紹。
接下來(lái)驗(yàn)證一下:
[root: 1st]# insmod test.ko
hello irq
[root: 1st]# key down //上半部操作
hello xiaobai! //下半部操作
key down
hello xiaobai!
key down
hello xiaobai!
[root: 1st]# rmmod test
good bye irq
上面介紹,觸發(fā)軟中斷函數(shù)raise_softirq并不會(huì)讓軟中斷處理函數(shù)馬上執(zhí)行,它只是打了個(gè)標(biāo)記,等到適合的時(shí)候再被實(shí)行。如在中斷處理函數(shù)返回后,內(nèi)核就會(huì)檢查軟中斷是否被觸發(fā)并執(zhí)行觸發(fā)的軟中斷。
軟中斷會(huì)在do_softirq中被執(zhí)行,其中核心部分在do_softirq中調(diào)用的__do_softirq中:
/*kernel/softirq.c*/
172 asmlinkage void __do_softirq(void)
173 {
。。。。。。
194 do {
195 if (pending & 1) { //如果被觸發(fā),調(diào)用軟中斷處理函數(shù)
196 int prev_count = preempt_count();
197
198 h->action(h); //調(diào)用軟中斷處理函數(shù)
199
200 if (unlikely(prev_count != preempt_count())) {
201 printk(KERN_ERR "huh, entered softirq %td %p"
202 "with preempt_count %08x,"
203 " exited with %08x?\n", h - softirq_vec,
204 h->action, prev_count, preempt_count());
205 preempt_count() = prev_count;
206 }
207
208 rcu_bh_qsctr_inc(cpu);
209 }
210 h++; //下移,獲取另一個(gè)軟中斷
211 pending >>= 1;
212 } while (pending); //大循環(huán)內(nèi)執(zhí)行,知道所有被觸發(fā)的軟中斷都執(zhí)行完
。。。。。。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
三、tasklet
上面的介紹看到,軟中斷實(shí)現(xiàn)下半部的方法很麻煩,一般是不會(huì)使用的。一般,我們使用tasklet——利用軟中斷實(shí)現(xiàn)的下半部機(jī)制。
在介紹軟中斷索引號(hào)的時(shí)候,有兩個(gè)用于實(shí)現(xiàn)tasklet的軟中斷索引號(hào):HI_SOFTIRQ和TASKLET_SOFTIRQ。兩個(gè)tasklet唯一的區(qū)別就是優(yōu)先級(jí)的大小,一般使用TAKSLET_SOFTIRQ。
先看一下如何使用tasklet,用完之后再看內(nèi)核中是如何實(shí)現(xiàn)的:
步驟一、編寫(xiě)tasklet處理函數(shù),定義并初始化結(jié)構(gòu)體tasklet_struct:
內(nèi)核中是通過(guò)tasklet_struct來(lái)維護(hù)一個(gè)tasklet,介紹一下tasklet_struct里面的兩個(gè)成員:
/*linux/interrupt.h*/
319 struct tasklet_struct
320 {
321 struct tasklet_struct *next;
322 unsigned long state;
323 atomic_t count;
324 void (*func)(unsigned long); //tasklet處理函數(shù)
325 unsigned long data; //給處理函數(shù)的傳參
326 };
所以,在初始化tasklet_struct之前,需要先寫(xiě)好tasklet處理函數(shù),如果需要傳參,也需要指定傳參,你可以直接傳數(shù)據(jù),也可以傳地址。我定義的處理函數(shù)如下:
/*6th_irq_3/2nd/test.c*/
15 void xiaobai_func(unsigned long data)
16 {
17 printk("hello xiaobai!, data[%d]\n", (int)data); //也沒(méi)干什么事情,僅僅打印。
18 }
同樣,可以通過(guò)兩種辦法定義和初始化tasklet_struct。
1、靜態(tài)定義并初始化
/*linux/interrupt.h*/
328 #define?DECLARE_TASKLET(name, func, data)?\
329 struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
330
331 #define?DECLARE_TASKLET_DISABLED(name, func, data)?\
332 struct tasklet_struct name = { NULL, 0, ATOMIC_INIT
上面兩個(gè)函數(shù)都是定義一個(gè)叫name的tasklet_struct,并指定他的處理函數(shù)和傳參分別是func和data。唯一的區(qū)別是,DCLARE_TASKLET_DISABLED初始化后的處于禁止?fàn)顟B(tài),暫時(shí)不能被使用。
2、動(dòng)態(tài)定義并初始化
跟以往的一樣,需要先定義結(jié)構(gòu)體,然后把結(jié)構(gòu)體指針傳給tasklet_init來(lái)動(dòng)態(tài)初始化:
/*kernel/softirq.c*/
435 void tasklet_init(struct tasklet_struct *t,
436 void (*func)(unsigned long), unsigned long data)
在我的程序中,使用動(dòng)態(tài)定義并初始化:
/*6th_irq_3/2nd/test.c*/
13 struct tasklet_struct xiaobai_tasklet; //定義tasklet結(jié)構(gòu)體
32 tasklet_init(&xiaobai_tasklet, xiaobai_func, (unsigned long)123);
我這里的傳參直接傳一個(gè)數(shù)值123。這操作也相當(dāng)于:
DECLEAR_TASKLET(xiaobai_tasklet, xiaobai_func, (unsigned long)123);
步驟二、在中斷返回前調(diào)度tasklet:
跟軟中斷一樣(其實(shí)tasklet就是基于軟中斷實(shí)現(xiàn)),這里說(shuō)的調(diào)度并不是馬上執(zhí)行,只是打個(gè)標(biāo)記,至于什么時(shí)候執(zhí)行就要看內(nèi)核的調(diào)度。
調(diào)度使用函數(shù)tasklet_schedule或者tasklet_hi_schedule,兩個(gè)的區(qū)別是一個(gè)使用TASKLET_SOFTIRQ,另一個(gè)使用HI_SOFTIRQ。這兩個(gè)函數(shù)都是一tasklet_struct指針為參數(shù):
/*linux/interrupt.h*/
365 static inline void tasklet_schedule(struct tasklet_struct *t)
373 static inline void tasklet_hi_schedule(struct tasklet_struct *t)
在我的函數(shù)中,使用tasklet_schedule:
/*6th_irq_3/2nd/test.c*/
23 tasklet_schedule(&xiaobai_tasklet);
步驟三、當(dāng)模塊卸載時(shí),將tasklet_struct結(jié)構(gòu)體移除:
/*kernel/softirq.c*/
447 void tasklet_kill(struct tasklet_struct *t)
確保了?tasklet?不會(huì)被再次調(diào)度來(lái)運(yùn)行,通常當(dāng)一個(gè)設(shè)備正被關(guān)閉或者模塊卸載時(shí)被調(diào)用。如果?tasklet?正在運(yùn)行,?程序會(huì)休眠,等待直到它執(zhí)行完畢
另外,還有禁止與激活tasklet的函數(shù)。被禁止的tasklet不能被調(diào)用,直到被激活:
/*linux/interrupt.h*/
386 static inline void tasklet_disable(struct tasklet_struct *t) //禁止
393 static inline void tasklet_enable(struct tasklet_struct *t) //激活
最后附上程序:
/*6th_irq_3/2nd/test.c*/
1 #include <linux/module.h>
2 #include <linux/init.h>
3
4 #include <linux/interrupt.h>
5
。。。。省略。。。。
13 struct tasklet_struct xiaobai_tasklet; //定義tasklet結(jié)構(gòu)體
14
15 void xiaobai_func(unsigned long data)
16 {
17 printk("hello xiaobai!, data[%d]\n", (int)data);
18 }
19
20 irqreturn_t irq_handler(int irqno, void *dev_id) //中斷處理函數(shù)
21 {
22 printk("key down\n");
23 tasklet_schedule(&xiaobai_tasklet);
24 return IRQ_HANDLED;
25 }
26
27 static int __init test_init(void) //模塊初始化函數(shù)
28 {
29 int ret;
30
31 /*tasklet*/
32 tasklet_init(&xiaobai_tasklet, xiaobai_func, (unsigned long)123);
33
41 ret = request_irq(IRQ_EINT1, irq_handler,
42 IRQF_TRIGGER_FALLING, "key INT_EINT1", NULL);
43 if(ret){
44 P_DEBUG("request irq failed!\n");
45 return ret;
46 }
47
48 printk("hello irq\n");
49 return 0;
50 }
51
52 static void __exit test_exit(void) //模塊卸載函數(shù)
53 {
54 tasklet_kill(&xiaobai_tasklet);
55 free_irq(IRQ_EINT1, NULL);
56 printk("good bye irq\n");
57 }
58
59 module_init(test_init);
60 module_exit(test_exit);
最后驗(yàn)證一下,還是老樣子,上下半步只是打印一句話(huà),沒(méi)有實(shí)質(zhì)操作:
[root: 2nd]# insmod test.ko
hello irq
[root: 2nd]# key down //上半部操作
hello xiaobai!, data[123] //下半部操作
key down
hello xiaobai!, data[123]
[root: 2nd]# rmmod test
good bye irq
既然知道怎么使用tasklet,接下來(lái)就要看看它是怎么基于軟中斷實(shí)現(xiàn)的
上面說(shuō)明的是單處理器的情況下,如果是多處理器,每個(gè)處理器都會(huì)有一個(gè)tasklet_vec和tasklet_hi_vec鏈表,這個(gè)情況我就不介紹了。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
四、總結(jié)
這節(jié)介紹了如何通過(guò)軟中斷(tasklet也是軟中斷的一種實(shí)現(xiàn)形式)機(jī)制來(lái)實(shí)現(xiàn)中斷下半部。使用軟中斷實(shí)現(xiàn)的優(yōu)缺點(diǎn)很明顯:
優(yōu)點(diǎn):運(yùn)行在軟中斷上下文,優(yōu)先級(jí)比普通進(jìn)程高,調(diào)度速度快。
缺點(diǎn):由于處于中斷上下文,所以不能睡眠。
也許有人會(huì)問(wèn),那軟中斷和tasklet有什么區(qū)別?
個(gè)人理解,tasklet是基于軟中斷實(shí)現(xiàn)的,基本上和軟中斷相同。但有一點(diǎn)不一樣,如果在多處理器的情況下,內(nèi)核不能保證軟中斷在哪個(gè)處理器上運(yùn)行(聽(tīng)起來(lái)像廢話(huà)),所以,軟中斷之間需要考慮共享資源的保護(hù)。而在tasklet,內(nèi)核可以保證,兩個(gè)同類(lèi)型(TASKLET_SOFTIRQ和HI_SOFTIRQ)的tasklet不能同時(shí)執(zhí)行,那就說(shuō)明,同類(lèi)型tasklet之間,可以不考慮同類(lèi)型tasklet之間的并發(fā)情況。
一般的,優(yōu)先考慮使用tasklet。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
源代碼:?6th_irq_3(1).rar???
分享到:新浪微博QQ空間開(kāi)心網(wǎng)豆瓣人人網(wǎng)twitterfb 0?
???頂 閱讀(975)┊?評(píng)論?(1)┊收藏(0)┊舉報(bào)┊打印 前一篇:linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(六):2.分享中斷號(hào) [發(fā)評(píng)論]?評(píng)論?重要提示:警惕虛假中獎(jiǎng)信息!
- 回復(fù)?舉報(bào) songtao0728?2011-08-09 15:10 請(qǐng)教一個(gè)問(wèn)題:
我在按你的方面試驗(yàn)軟中斷,編譯通過(guò)后,下載到開(kāi)發(fā)板后,加載出現(xiàn):
soft: Unknown symbol raise_softirq
soft: Unknown symbol open_softirq
insmod: cannot insert 'soft.ko':unknown symbol in module or invalid parameter
這是不是因?yàn)槲业拈_(kāi)發(fā)板的系統(tǒng)沒(méi)有這兩個(gè)函數(shù)的導(dǎo)出符號(hào)所導(dǎo)致的?
我如果不重新編譯開(kāi)發(fā)板的內(nèi)核的話(huà),是不是還有別的辦法解決?
京ICP證041476號(hào) 京ICP證060528號(hào)
總結(jié)
以上是生活随笔為你收集整理的linux设备驱动归纳总结(六):3.中断下半部之tasklet的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: profit from/prove to
- 下一篇: GC0053-STM32单片机NTC热敏