1.linux核心等待佇列機制
1.1.概念
明確:等待分為忙等待和休眠等待
"等待":期望某個事件發生
「事件」:比如按鍵有操作,串列埠有資料,網路有資料;
明確:阻塞一般是指休眠等待
明確:程序的狀態
1.程序的準備就緒狀態
task_ready;
2.程序的執行狀態
task_running;
3.程序的休眠狀態
不可中斷的休眠:
task_uninterruptible
可中斷的休眠:
task_interruptible
4.注意:程序的切換,排程都是利用核心的排程器來實現的,排程器管理的物件是程序;
明確:休眠只能用於程序
程序休眠的方法:
1.在使用者層呼叫sleep函式
2.在核心層呼叫msleep/ssleep/schedule/schedule_timeout
說明:以上休眠的方法的缺點在於一旦事件到來,程序無法及時被喚醒(除非發訊號),那麼造成事件無法得到及時的處理;
問:事件一旦到來,如何及時喚醒休眠的程序呢?
問:乙個程序如果發現裝置不可用,程序將進入休眠等待,一旦裝置可用,如何及時喚醒休眠的程序呢?
答:利用linux核心的等待佇列機制;
2.等待佇列機制
特點:
1.等待佇列機制本質目的就是實現程序在核心空間進行休眠操作;當然休眠的原因是等待某個事件到來!
2.一旦事件到來,驅動能夠主動喚醒休眠的程序,當然也可以通過訊號來喚醒;
3.訊號量機制就是靠等待佇列機制來實現的!
使用等待佇列機制實現程序休眠的步驟:
1.等待佇列 = 等待 + 佇列
模型:程序排程器->老鷹(核心實現)
等待佇列頭->雞媽媽(驅動實現)
要休眠的程序->小雞(驅動實現)
2.相關的資料結構
linux核心描述等待佇列頭的資料型別:
wait_queue_head_t
linux核心描述裝載休眠程序的容器的資料型別:
wait_queue_t
切記:此資料型別描述的裝載程序的容器
linux核心描述程序(執行緒)的資料型別:
struct task_struct ;//核心會為每乙個程序建立乙個對應的物件
linux核心描述"當前程序"的核心全域性指標變數: current
"當前程序":只是當時獲取cpu資源,正在執行中中的程序,
而此時核心全域性指標變數current就指向當前這個程序的struct task_struct物件;
3.使用等待佇列實現程序在核心休眠的程式設計步驟:
3.1.定義初始化等待佇列頭(造雞媽媽)
wait_queue_head_t wq;
init_waitqueue_head(&wq);
3.2.定義初始化裝載休眠程序的容器(造小雞)
wait_queue_t wait;
init_waitqueue_entry(&wait, current);
說明:把當前要休眠的程序新增到容器wait中
3.3.將當前要休眠的程序新增到休眠佇列中去
add_wait_queue(&wq, &wait);
3.4.設定當前要休眠程序的休眠狀態
set_current_state(task_interruptible);
//設定為可中斷休眠狀態 或者
set_current_state(task_uninterruptible);
//設定為不可中斷的休眠狀態
注意:此時當前程序還沒有進入休眠狀態,還沒有釋放cpu資源;
3.5.當前程序進入真正的休眠狀態(釋放cpu資源)
schedule();
注意:此時程式就執行到此停止不前,等待某個事件的到來!
注意:1.此休眠函式和休眠狀態(可中斷的),休眠程序被喚醒的方法有兩種:
第一種通過訊號來喚醒
第二種通過事件到來,驅動主動喚醒
2.此休眠函式和休眠狀態(不可中斷的),休眠程序被喚醒的方法有一種:
第一種通過事件到來,驅動主動喚醒
總結:呼叫此函式,靜靜等待訊號或者驅動主動來喚醒;
3.6.一旦休眠程序被喚醒,記得要將休眠程序從休眠佇列中移除,在移除前設定當前程序的狀態為執行態:
set_current_state(task_running);
remove_wait_queue(&wq, &wait);
3.7.判斷喚醒的原因:
if (signal_pending(current)) else
3.8.事件到來,驅動主動喚醒的方法:
wake_up(&wq); //喚醒休眠佇列中所有的休眠程序;
或者wake_up_interruptible(&wq);//喚醒休眠佇列中所有睡眠型別為可中斷的休眠程序
案例:寫程序喚醒讀程序
實驗步驟:
1.insmod led_drv.ko
2../led_test r & //啟動讀程序
3../led_test w //啟動寫程序 ,主動喚醒
4../led_test r & //啟動讀程序
5.kill 讀程序的pid //接受訊號喚醒
#include #include #include #include #include //定義等待佇列頭
static wait_queue_head_t wq;
static ssize_t led_read(struct file *file,
char __user *buf,
size_t count,
loff_t *ppos)
else
return count;
}static ssize_t led_write(struct file *file,
char __user *buf,
size_t count,
loff_t *ppos)
//定義初始化操作介面
static struct file_operations led_fops = ;
//定義初始化混雜裝置物件
static struct miscdevice led_misc = ;
static int led_init(void)
static void led_exit(void)
module_init(led_init);
module_exit(led_exit);
module_license("gpl");
#include #include #include #include int main(int argc, char *argv)
fd = open("/dev/myled", o_rdwr);
if (fd < 0)
return -1;
if (!strcmp(argv[1], "r")) else
close(fd);
return 0;
}
3.linux核心等待佇列程式設計方法2:
明確:等待佇列機制是實現程序在核心空間進行休眠操作;
驅動要做的步驟:
1.定義初始化等待佇列頭
wait_queue_head_t wq;
init_waitqueue_head(&wq);
2.呼叫以下方法實現程序的休眠
wait_event(wq,condition);
說明:
引數:
wq:等待佇列頭
condition:
condition如果為假,表示事件沒有滿足,程序需要進行休眠;
condition如果為真,表示事件滿足,程序不進行休眠,立即返回
1.核心會幫你定義初始化乙個裝載當前程序的容器
2.核心也會幫你將當前程序新增到wq的休眠佇列中
3.核心也會幫你設定程序的休眠狀態,此休眠狀態為不可中斷;
4.核心也會幫你進入真正的休眠;
5.核心也會幫你判斷喚醒的原因;
6.核心也會幫你移除
或者
wait_event_interruptible(wq,condition);
說明:
引數:
wq:等待佇列頭
condition:
condition如果為假,表示事件沒有滿足,程序需要進行休眠;
condition如果為真,表示事件滿足,程序不進行休眠,立即返回
1.核心會幫你定義初始化乙個裝載當前程序的容器
2.核心也會幫你將當前程序新增到wq的休眠佇列中
3.核心也會幫你設定程序的休眠狀態,此休眠狀態 為可中斷;
4.核心也會幫你進入真正的休眠;
5.核心也會幫你判斷喚醒的原因;
6.核心也會幫你移除
程式設計框架:
//剛開始condition為假
wait_event_interruptible(wq, condition);
將condition再次設定為假,為了下一次休眠
...
//在別處,發現事件滿足,喚醒
condition設定為真;
wake_up_interruptible(&wq);
案例:編寫乙個真實有用的按鍵驅動!
Linux中等待佇列機制分析
linux中等待佇列機制分析 在軟體開發中任務經常由於某種條件沒有得到滿足而不得不進入睡眠狀態,然後等待條件得到滿足的時候再繼續執行,進入執行狀態。這種需求需要等待佇列機制的支援。linux 中提供了等待佇列的機制,該機制在核心中應用很廣泛。在linux 核心中使用等待佇列的過程很簡單,首先定義乙個...
Linux中等待佇列機制分析
在軟體開發中任務經常由於某種條件沒有得到滿足而不得不進入睡眠狀態,然後等待條件得到滿足的時候再繼續執行,進入執行狀態。這種需求需要等待佇列機制的支援。linux 中提供了等待佇列的機制,該機制在核心中應用很廣泛。在linux 核心中使用等待佇列的過程很簡單,首先定義乙個wait queue head...
linux 等待佇列
linux 核心的等待佇列是以雙迴圈鍊錶為基礎資料結構,與程序排程機制緊密結合,能夠用於實現核心的非同步事件通知機制。在這個鍊錶中,有兩種資料結構 等待佇列頭 wait queue head t 和等待佇列項 wait queue t 等待佇列頭和等待佇列項中都包含乙個 list head 型別的域...