Linux裝置驅動中的阻塞和非阻塞I O

2021-08-01 18:34:04 字數 2563 閱讀 5124

阻塞操作 : 是指在執行裝置操作時,若不能獲得資源,則掛起程序直到滿足操作條件後再進行操作。被掛起的程序進入休眠, 被從排程器移走,直到條件滿足。

非阻塞操作 :在不能進行裝置操作時,並不掛起,它或者放棄,或者不停地查詢,直到可以進行操作。非阻塞應用程式通常使用select系統呼叫查詢是否可以對裝置進行無阻塞的訪問最終會引發裝置驅動中 poll函式執行。

阻塞地讀取串列埠乙個字元:

char buf;   

fd = open("/dev/ttys",o_rdwr);

.. ..

res = read(fd,&buf,1);//當串列埠上有輸入時才返回

if(res == 1)

非阻塞地讀取串列埠乙個字元:

char buf; 

fd = open("/dev/ttys",o_rdwr | o_nonblock);

.. ..

while( read(fd,&buf,1) !=1);//當串列埠上無輸入也返回,所以要迴圈嘗試讀取串列埠

printf("%c\n",buf);

在linux裝置驅動中,可以使用等待隊 列(wait queue)來實現阻塞程序的喚醒.等待佇列能夠用於實現核心中的非同步事件通知機制。

linux提供了有關等待佇列的操作:

①: wait_queue_head_t my_queue; //定義等待佇列頭

wait_queue_head_t是wait_queue_head 結構體中的乙個typedef

②: init_waitqueue_head(&my_queue); //初始化佇列頭

如果覺得上邊兩步來的麻煩,可以直接使用「快捷方式」:

declare_wait_queue_head(name)

③:declare_waitqueue(name,tsk); //定義等待佇列

④:void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

用於將等待佇列wait新增到等待佇列頭指向的等待佇列鍊錶中 。

wait_event(queue, conditon);//不能被訊號打斷

wait_event_interruptible(queue, condition);//可以被訊號打斷

wait_event_timeout(queue, condition, timeout);

wait_event_interruptible_timeout(queue, condition, timeout);

wait_event()和wait_event_interruptible()的區別在於後者可以被訊號打斷,前者不能

queue:作為等待佇列頭的等待佇列被喚醒

conditon:必須滿足,否則阻塞

timeout和conditon相比,有更高優先順序,就是在第三個引數的timeout到達時,無論condition是否滿足,均返回。

⑥: void wake_up(wait_queue_head_t *queue);

void wake_up_interruptible(wait_queue_head_t *queue);

上述操作會喚醒以queue作為等待佇列頭的所有等待佇列中所有屬於該等待佇列頭的等待佇列對應的程序。
⑦: sleep_on(wait_queue_head_t *q);

interruptible_sleep_on(wait_queue_head_t *q);

sleep_on作用是把目前程序的狀態置成task_uninterruptible,並定義乙個等待佇列,之後把他掛到等待佇列頭q指向的雙向鍊錶,直到資源可用,q引導的等待佇列被喚醒。

interruptible_sleep_on作用是一樣的, 只不過它把程序狀態置為task_interruptible,並定義乙個等待佇列,之後把他掛到等待佇列頭q指向的佇列,直到資源可獲得(q指引的等待佇列被喚醒),或者程序收到訊號。

sleep_on()和wake_up()成對使用;interruptible_sleep_on與wake_up_interruptible()成對使用;

這兩個函式的流程是首先,定義並初始化等待佇列,把程序的狀態置成task_uninterruptible或task_interruptible,並將對待佇列新增到等待佇列頭。

然後通過schedule(放棄cpu,排程其他程序執行。最後,當程序被其他地方喚醒,將等待佇列移除等待佇列頭。

在linux核心中,使用set_current_state()和__add_wait_queue()函式來實現目前程序狀態的改變,直接使用current->state = task_uninterruptible

類似的語句也是可以的。

因此我們有時也可能在許多驅動中看到,它並不呼叫sleep_on或interruptible_sleep_on(),而是親自進行程序的狀態改變和切換。

Linux 裝置驅動阻塞 非阻塞IO 等待佇列

阻塞 顧名思義,就是指在執行裝置操作時若不能獲得資源則掛起操作,直到滿足可操作的條件後再進行操作,被掛起的程序進入休眠狀態,被從排程器的執行佇列移 走,直到等待的條件滿足。非阻塞 就是反過來,程序在不能進行裝置操作時並不掛起,它或者放棄,或者不停的查詢,直到可以進行位置。小王,明白了沒這兩個基本的概...

第8章 Linux裝置驅動中的阻塞與非阻塞I O

本文摘自 偶有較小改動 linux 裝置驅動開發詳解 宋寶華 編著 人民郵電出版社 留作紀念。living park 第8章 linux裝置驅動中的阻塞與非阻塞i o 8.1 阻塞與非阻塞i o 阻塞操作是指在執行裝置操作時若不能獲得資源則掛起程序,直到滿足可操作的條件後再進行操作。因為阻塞的程序會...

蛻變成蝶 Linux裝置驅動中的阻塞和非阻塞I O

今天意外收到乙個訊息,真是驚呆我了,部落格軒給我發了資訊,說是俺的部落格文章有特色可以出本書,這簡直讓我受寵若驚,俺只是個大三的技術宅,寫的部落格也是自己所學的一些見解和在網上看到我一些博文以及帖子裡綜合起來寫的,總之這又給了額外的動力,讓自己繼續前進,希望和大家能夠分享一些自己的經驗,在最需要奮鬥...