Linux設備驅動之阻塞與非阻塞IO

    阻塞是指在執行設備操做時若不能得到資源則掛起進程,直到知足可操做的條件後再進行操做。被掛起的進程將進入休眠狀態,被從調度器的運行隊列移走,直到條件被知足。而非阻塞操做的進程在不能進行設備操做時並不掛起,它或者放棄,或者不停的查詢(一直佔用CPU),直到能夠進行操做爲止。函數

Linux驅動程序中使用等待隊列(wait_queue)來實現阻塞進程的喚醒。線程

靜態方法定義並初始化一個等待隊列頭:code

DECLARE_WAIT_QUEUE_HEAD(name);隊列

或者使用動態方法:進程

wait_queue_head mane;事件

init_watiqueue_head(&name);資源

等待事件:it

conditions爲任意一個布爾值,若爲真,進程被喚醒,不然休眠。後兩個版本只會等待給定的時間,到期時,這兩個宏都會返回0值,而不管conditions如何求值。io

wait_event(queue, conditions);進程將被置於非中斷休眠,這一般不是咱們所指望的event

wait_event_interruptible(queue, conditions);最好選擇此方式,它能夠被信號中斷。返回非0表示被某個信號中斷。

wait_event_timeout(queue, conditions,timeout);

wait_event_interruptible_timeout(queue, conditions,timeout);

喚醒:

阻塞的另一半是喚醒。其它的某個執行線程(多是另外一個進程或者爲斷處理例程)必須爲咱們執行喚醒,由於咱們的進程正在休眠中。用來喚醒休眠進程的基本函數是wake_up,它有多種形式:

void wake_up(wait_queue_head_t *queue);

void wake_up_interruptible(wait_queue_head_t *queue);只會喚醒那些執行中可中斷休眠的進程。

在實踐中,約定做法是wait_event時使用wake_up,使用wait_event_interruptible時使用 wake_up_interruptible。

 示例代碼:任何試圖從該設備讀取的進程均被置於休眠,只要某個進程向該設備寫入,全部的休眠的進程將被喚醒。

static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag=0;
ssize_t sleepy_read(struct file *filp,char __user *buf,size_t count,loff_t *pos)
{
    wait_event_interruptible(wq,flag!=0);
    flag = 0;
    .....
    .....
    return 0;
}

ssize_t sleepy_write(struct file *filp,char __user *buf,size_t count,loff_t *pos)
{
    flag = 1 ;
    wake_up_interruptible(&wq);
    return count;
}
相關文章
相關標籤/搜索