在軟件開(kāi)發(fā)中任務(wù)經(jīng)常由于某種條件沒(méi)有得到滿足而不得不進(jìn)入睡眠狀態(tài),然后等待條件得到滿足的時(shí)候再繼續(xù)運(yùn)行,進(jìn)入運(yùn)行狀態(tài)。這種需求需要等待隊(duì)列機(jī)制的支持。Linux中提供了等待隊(duì)列的機(jī)制,該機(jī)制在內(nèi)核中應(yīng)用很廣泛。
在Linux內(nèi)核中使用等待隊(duì)列的過(guò)程很簡(jiǎn)單,首先定義一個(gè)wait_queue_head,然后如果一個(gè)task想等待某種事件,那么調(diào)用wait_event(等待隊(duì)列,事件)就可以了。
等待隊(duì)列應(yīng)用廣泛,但是內(nèi)核實(shí)現(xiàn)卻十分簡(jiǎn)單。其涉及到兩個(gè)比較重要的數(shù)據(jù)結(jié)構(gòu):__wait_queue_head,該結(jié)構(gòu)描述了等待隊(duì)列的鏈頭,其包含一個(gè)鏈表和一個(gè)原子鎖,結(jié)構(gòu)定義如下:
struct __wait_queue_head {
spinlock_t lock; /* 保護(hù)等待隊(duì)列的原子鎖 */
struct list_head task_list; /* 等待隊(duì)列 */
};
__wait_queue,該結(jié)構(gòu)是對(duì)一個(gè)等待任務(wù)的抽象。每個(gè)等待任務(wù)都會(huì)抽象成一個(gè)wait_queue,并且掛載到wait_queue_head上。該結(jié)構(gòu)定義如下:
struct __wait_queue {
unsigned int flags;
void *private; /* 通常指向當(dāng)前任務(wù)控制塊 */
/* 任務(wù)喚醒操作方法,該方法在內(nèi)核中提供,通常為autoremove_wake_function */
wait_queue_func_t func;
struct list_head task_list; /* 掛入wait_queue_head的掛載點(diǎn) */
};
Linux中等待隊(duì)列的實(shí)現(xiàn)思想如下圖所示,當(dāng)一個(gè)任務(wù)需要在某個(gè)wait_queue_head上睡眠時(shí),將自己的進(jìn)程控制塊信息封裝到wait_queue中,然后掛載到wait_queue的鏈表中,執(zhí)行調(diào)度睡眠。當(dāng)某些事件發(fā)生后,另一個(gè)任務(wù)(進(jìn)程)會(huì)喚醒wait_queue_head上的某個(gè)或者所有任務(wù),喚醒工作也就是將等待隊(duì)列中的任務(wù)設(shè)置為可調(diào)度的狀態(tài),并且從隊(duì)列中刪除。
使用等待隊(duì)列時(shí)首先需要定義一個(gè)wait_queue_head,這可以通過(guò)DECLARE_WAIT_QUEUE_HEAD宏來(lái)完成,這是靜態(tài)定義的方法。該宏會(huì)定義一個(gè)wait_queue_head,并且初始化結(jié)構(gòu)中的鎖以及等待隊(duì)列。當(dāng)然,動(dòng)態(tài)初始化的方法也很簡(jiǎn)單,初始化一下鎖及隊(duì)列就可以了。
一個(gè)任務(wù)需要等待某一事件的發(fā)生時(shí),通常調(diào)用wait_event,該函數(shù)會(huì)定義一個(gè)wait_queue,描述等待任務(wù),并且用當(dāng)前的進(jìn)程描述塊初始化wait_queue,然后將wait_queue加入到wait_queue_head中。函數(shù)實(shí)現(xiàn)流程說(shuō)明如下:
1、用當(dāng)前的進(jìn)程描述塊(PCB)初始化一個(gè)wait_queue描述的等待任務(wù)。
2、在等待隊(duì)列鎖資源的保護(hù)下,將等待任務(wù)加入等待隊(duì)列。
3、判斷等待條件是否滿足,如果滿足,那么將等待任務(wù)從隊(duì)列中移出,退出函數(shù)。
4、 如果條件不滿足,那么任務(wù)調(diào)度,將CPU資源交與其它任務(wù)。
5、 當(dāng)睡眠任務(wù)被喚醒之后,需要重復(fù)(2)、(3)步驟,如果確認(rèn)條件滿足,退出等待事件函數(shù)。
等待隊(duì)列編程接口
1
wait_event
這是一個(gè)宏,讓當(dāng)前任務(wù)處于等待事件狀態(tài)。輸入?yún)?shù)如下:
@wq:等待隊(duì)列
@conditions:等待條件
2
wait_event_timeout
功能與wait_event類(lèi)似,多了一個(gè)超時(shí)機(jī)制。參數(shù)中多了一項(xiàng)超時(shí)時(shí)間。
3
wait_event_interruptible
這是一個(gè)宏,與前兩個(gè)宏相比,該宏定義的等待能夠被消息喚醒。如果被消息喚醒,那么返回- ERESTARTSYS.輸入?yún)?shù)如下:
@wq:等待隊(duì)列
@condition:等待條件
@rt:返回值
4
wait_event_interruptible_timeout
與(3)相比,多了超時(shí)機(jī)制
5
wake_up
喚醒等待隊(duì)列中的一個(gè)任務(wù)
6
wake_up_all
喚醒等待隊(duì)列中的所有任務(wù)
本文出自:億恩科技【www.ypdoo.com.cn】
本文出自:億恩科技【www.enidc.com】 -->
服務(wù)器租用/服務(wù)器托管中國(guó)五強(qiáng)!虛擬主機(jī)域名注冊(cè)頂級(jí)提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM]
|