阻塞型驅動設計
1.阻塞的必要性
當乙個裝置無法立刻滿足使用者的讀寫請
求時應當如何處理? 例如:呼叫read
時,裝置沒有資料提供, 但以後可能會
有;或者乙個程序試圖向裝置寫入資料,
但是裝置暫時沒有準備好接收資料。當
上述情況發生的時候,
驅動程式應當
(預設地)阻塞程序,使它進入等待(睡
眠)狀態,直到請求可以得到滿足
。a準備對b(驅動程式)讀取資料,b說現在還沒資料。請a先進候車室等待,b之後有了資料。b就將a喚醒。
2.核心等待佇列
在實現阻塞驅動的過程中,也
需要有乙個「候車室」來安排
被阻塞的程序「休息」,當喚
醒它們的條件成熟時,則可以
從「候車室」中將這些程序喚
醒。而這個「候車室」就是等
待佇列。
1、定義等待佇列
wait_queue_head_t my_queue
2、初始化等待佇列
init_waitqueue_head(&my_queue);
3、定義+初始化等待佇列
declare_wait_queue_head(my_queue);
3.進入等待佇列,睡眠
wait_event(queue,condition)
當condition(布林表示式)為真時,立即返回;否則讓程序
進入task_uninterruptible
模式的睡眠,並掛在queue參
數所指定的等待佇列上。
wait_event_interruptible(queue,condition)
當condition(布林表示式)為真時,立即返回;否則讓
程序進入
task_interruptible
的睡眠,並掛在queue引數
所指定的等待佇列上。
int wait_event_killable(queue, condition)
當condition(乙個布林表示式)為真時,立即返回;
否則讓程序進入
task_killable
的睡眠,並掛
在queue引數所指定的等待佇列上。
4.從等待佇列中喚醒程序
wake_up(wait_queue_t *q)
從等待佇列q中喚醒狀態為task_uninterruptible,
task_interruptible,task_killable
的所有程序。
wake_up_interruptible(wait_queue_t *q)
從等待佇列q中喚醒狀態為task_interruptible 的程序。
5.對按鍵程式進行改造
key.c
#include
<
linux
/module.h
>
#include
<
linux
/init.h
>
#include
<
linux
/miscdevice.h
>
#include
<
linux/fs
.h>
#include
<
asm/
uaccess.h
>
#include
<
linux/io
.h>
#include
<
linux
/irqreturn.h
>
#include
<
linux
/interrupt.h
>
#include
<
linux
/uaccess.h
>
#define gpfcon
(volatile unsigned long*)
0x56000050
#define gpfdat
(volatile unsigned long*)
0x56000054
unsigned
int*
gpio_data
;struct work_struct
*work1
;struct timer_list key_timer
;wait_queue_head_t key_q
;unsigned
intkey_num =0
;void key_timer_func
(unsigned long data
)elseif(
(key_val
&0x02)=
=0)elseif(
(key_val
&0x04)=
=0)elseif(
(key_val
&0x10)=
=0)wake_up(&
key_q
); //喚醒程序
}void work1_func
(struct work_struct
*work
)irqreturn_t key_int
(int
irq,
void
*dev_id
)void key_hw_init()
intkey_open
(struct inode
*inode
,struct file
*filp
)ssize_t key_read
(struct file
*filp
,char __user
*buf
,size_t size
,loff_t
*pos
)struct file_operations key_fops =;
struct miscdevice key_miscdev =;
static
intbutton_init()
//按鍵初始化
key_hw_init()
;//註冊中斷處理程式
ret
=request_irq
(irq_eint0,&
key_int
,irqf_trigger_falling
,"tq2440key",0
);ret
=request_irq
(irq_eint1,&
key_int
,irqf_trigger_falling
,"tq2440key",0
);ret
=request_irq
(irq_eint2,&
key_int
,irqf_trigger_falling
,"tq2440key",0
);ret
=request_irq
(irq_eint4,&
key_int
,irqf_trigger_falling
,"tq2440key",0
);//
建立工作
work1
=kmalloc
(sizeof
(struct work_struct),
gfp_kernel);
init_work
(work1
,work1_func);
//初始化定時器
init_timer(&
key_timer);
key_timer
.function
=key_timer_func;/
/註冊定時器
add_timer(&
key_timer);
//初始化等待佇列
init_waitqueue_head(&
key_q
); //初始化等待佇列
return 0;}
static void button_exit()
module_init
(button_init);
module_exit
(button_exit);
0
給主人留下些什麼吧!~~
核心驅動 阻塞型驅動
1 定義 等待佇列頭部 wait queue head t key q 2 初始化 等待佇列頭部 init waitqueue head key q 3 等待事件發生 wait event key q,key num 4 喚醒等待事件 wake up key q 查詢按鍵狀態 key.c inclu...
linux裝置驅動(8)阻塞型IO
當驅動程式無法立即滿足請求,該如何響應?如當我們想要寫入的時候,裝置對應的緩衝區已滿,或者是當我們想要讀的時候當前緩衝區是空的。為了提高cpu的效率,我們的驅動程式應該阻塞等待該程序,將其置於休眠狀態直到請求可繼續。休眠 sleep 對於程序來講意味著什麼?當乙個程序被置入休眠時,他會被標記為一種特...
驅動開發之始,(四)阻塞型I O,程序休眠
在前面的章節中,我們講述了read和write方法。當資料不可用時,使用者呼叫read,或者使用者使用寫入資料,但輸出緩衝區已滿,驅動程式該如何相應呢?在這種情況下,驅動程式應該 預設 阻塞該程序,將其置入休眠狀態直到請求可繼續。1.休眠 sleep 當乙個程序被置入休眠時,它會被標記為一種特殊狀態...