1. 程式人生 > 其它 >Linux等待佇列介紹及其操作函式

Linux等待佇列介紹及其操作函式

技術標籤:Linux等待佇列阻塞IO

Linux等待佇列介紹及其操作函式

等待佇列

等待佇列一般應用在阻塞IO中,當裝置不可用或資料未準備好的時候就會進入到休眠態。等裝置可用的時候就會從休眠態喚醒,然後從裝置中讀取資料返回給應用程式。
非阻塞IO簡介:https://blog.csdn.net/weixin_45309916/article/details/111937086

1、等待佇列頭

阻塞訪問最大的好處就是當裝置檔案不可操作的時候程序可以進入休眠態,這樣可以將CPU 資源讓出來。但是,當裝置檔案可以操作的時候就必須喚醒程序,一般在中斷函式裡面完成喚醒工作。 Linux 核心提供了等待佇列(wait queue)來實現阻塞程序的喚醒工作,如果我們要在驅動中使用等待佇列,必須建立並初始化一個等待佇列頭,等待佇列頭使用結構體wait_queue_head_t 表示, wait_queue_head_t 結構體定義在檔案 include/linux/wait.h 中,結構體內容如下所示:

在這裡插入圖片描述

定義好等待佇列頭以後需要初始化, 使用 init_waitqueue_head 函式初始化等待佇列頭,函式原型如下:

函式原型引數
void init_waitqueue_head(wait_queue_head_t *q)就是要初始化的等待佇列頭。

也可以使用巨集 DECLARE_WAIT_QUEUE_HEAD 來一次性完成等待佇列頭的定義的初始化。

2、等待佇列項

等待佇列頭就是一個等待佇列的頭部,每個訪問裝置的程序都是一個佇列項,當裝置不可用的時候就要將這些程序對應的等待佇列項新增到等待佇列裡面。結構體 wait_queue_t 表示等待佇列項,結構體內容如下:
在這裡插入圖片描述
使用巨集 DECLARE_WAITQUEUE 定義並初始化一個等待佇列項,巨集的內容如下:

DECLARE_WAITQUEUE(name, tsk)

引數:

name : 就是等待佇列項的名字
tsk :表示這個等待佇列項屬於哪個任務(程序),一般設定為current

在 Linux 內 核 中 current 相 當 於 一 個 全 局 變 量 , 表 示 當 前 進 程 。 因 此 巨集DECLARE_WAITQUEUE 就是給當前正在執行的程序建立並初始化了一個等待佇列項。

3、將佇列項新增/移除等待佇列頭

當裝置不可訪問的時候就需要將程序對應的等待佇列項新增到前面建立的等待佇列頭中,只有新增到等待佇列頭中以後程序才能進入休眠態。當裝置可以訪問以後再將程序對應的等待佇列項從等待佇列頭中移除即可。

新增/刪除等待佇列函式:

函式原型作用
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)等待佇列項移除

等待佇列項新增引數說明:

q: 等待佇列項要加入的等待佇列頭。
wait:要加入的等待佇列項。

等待佇列項刪除引數說明:

q: 要刪除的等待佇列項所處的等待佇列頭。
wait:要刪除的等待佇列項。

兩個函式都沒有返回值

4、等待喚醒

當裝置可以使用的時候就要喚醒進入休眠態的程序,喚醒可以使用如下兩個函式:

void wake_up(wait_queue_head_t *q)
void wake_up_interruptible(wait_queue_head_t *q)

引數 q 就是要喚醒的等待佇列頭,這兩個函式會將這個等待佇列頭中的所有程序都喚醒。wake_up 函式可以喚醒處於 TASK_INTERRUPTIBLE 和 TASK_UNINTERRUPTIBLE 狀態的程序,而 wake_up_interruptible 函式只能喚醒處於 TASK_INTERRUPTIBLE 狀態的程序。

5、等待事件

除了主動喚醒以外,也可以設定等待佇列等待某個事件,當這個事件滿足以後就自動喚醒等待佇列中的程序,和等待事件有關的 API 函式如表所示:

函式描述
wait_event(wq, condition)等待以 wq 為等待佇列頭的等待佇列被喚醒,前提是 condition 條件必須滿足(為真),否則一直阻塞 。 此 函 數 會 將 進 程 設 置 為TASK_UNINTERRUPTIBLE 狀態
wait_event_timeout(wq, condition, timeout)功能和 wait_event 類似,但是此函式可以新增超時時間,以 jiffies 為單位。此函式有返回值,如果返回 0 的話表示超時時間到,而且 condition為假。為 1 的話表示 condition 為真,也就是條件滿足了。
wait_event_interruptible(wq, condition)與 wait_event 函式類似,但是此函式將程序設定為 TASK_INTERRUPTIBLE,就是可以被訊號打斷。
wait_event_interruptible_timeout(wq,condition, timeout)與 wait_event_timeout 函式類似,此函式也將程序設定為 TASK_INTERRUPTIBLE,可以被訊號打斷。