欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
等待隊列分析
等待隊列分析 (2008-08-05 10:32)


等待隊列操作分析:     linux驅動(dòng)程序中可以用等待隊列(wiat queue)來(lái)實(shí)現阻塞的喚醒1)定義等待隊列頭等待隊列頭結構體的定義:struct __wait_queue_head {	spinlock_t  lock;          //自旋鎖變量,用于在對等待隊列頭
//指向的等待隊列鏈表進(jìn)行操作時(shí)鎖上,查看哪有對
lock
的操作?
struct list_head task_list; // 指向等待隊列的list_head};typedef struct __wait_queue_head wait_queue_head_t;#define DECLARE_WAIT_QUEUE_HEAD(name) \ \\聲明一個(gè)待隊列頭對象 name: wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \\\待隊列頭的初始化: .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ .task_list = { &(name).task_list, &(name).task_list } }lock賦為unlocked,將等待隊列頭指向的等待隊列鏈表指向name,從而將等待隊列頭和
等待隊列連起來(lái)
;2)等待隊列中存放的是在執行設備操作時(shí)不能獲得資源而掛起的進(jìn)程定義等待對列:struct __wait_queue { unsigned int flags; //prepare_to_wait()里有對flags的操作,查看以得出其含義#define WQ_FLAG_EXCLUSIVE 0x01 //一個(gè)常數,在prepare_to_wait()用于修改flags的值
wait_queue_func_t func; //喚醒阻塞任務(wù)的函數 struct list_head task_list; // 阻塞任務(wù)鏈表};typedef struct __wait_queue wait_queue_t;#define DECLARE_WAITQUEUE(name, tsk) \\\聲明一個(gè)等待隊列并初始化為name wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)#define __WAITQUEUE_INITIALIZER(name, tsk) { \ \\等待對列初始化: .private = tsk, \ .func = default_wake_function, \ .task_list = { NULL, NULL } }下列兩個(gè)函數用于對特定的成員進(jìn)行賦值(當傳入不同類(lèi)型的參數時(shí));static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p){ q->flags = 0; q->private = p; //私有數據指針 q->func = default_wake_function; //使用默認的喚醒函數}static inline void init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func){ q->flags = 0; q->private = NULL; q->func = func; // 自定義的喚醒函數}3)對等待隊列進(jìn)行操作 static inline int waitqueue_active(wait_queue_head_t *q){ return !list_empty(&q->task_list);} 判斷等待對列頭是否為空,當一個(gè)進(jìn)程訪(fǎng)問(wèn)設備而得不到資源時(shí)就會(huì )被放入等待隊列頭指
向的等待隊列中,當該它是第一個(gè)被阻塞的進(jìn)程,(等待隊列頭是一開(kāi)始就有的還
是有了第一個(gè)被阻塞的進(jìn)程后才創(chuàng )建的?)
若此時(shí)等待隊列頭還是空的,要先創(chuàng )建(見(jiàn)上面)
然后再插入新的等待隊列
。

對等待隊列的鏈表操作
static inline void __add_wait_queue(wait_queue_head_t *head,\
 wait_queue_t *new) /
{ list_add(&new->task_list, &head->task_list);}/增加一個(gè)等待隊列new到等待
隊列頭head指向的等待隊列鏈表中;
static inline void __add_wait_queue_tail(wait_queue_head_t *head, // wait_queue_t *new){ list_add_tail(&new->task_list, &head->task_list);}增加一個(gè)等待隊列到表尾 static inline void __remove_wait_queue \
(wait_queue_head_t *head,wait_queue_t *old)
{ list_del(&old->task_list);}刪除一個(gè)等待隊列4)等待事件當等待隊列加入到鏈表中以后,就要等待特定的condition來(lái) 喚醒它; #define __wait_event(wq, condition) \\\wq:在等待事件的等待隊列;condition:等待的條件do { \ DEFINE_WAIT(__wait); \定義并初始化一個(gè)wait_queue_t結構 \ for (;;) { \ prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ if (condition) \ //wait_queue:wq要等的condition是否滿(mǎn)足 break; \ schedule(); \//condition不成立,放棄cpu重新調度一個(gè)task } \ finish_wait(&wq, &__wait); \} while (0)等待condition在成立,否則進(jìn)程睡眠(TASK_UNINTERRUPTIBLE);condition滿(mǎn)足
后等待結束,跳出循環(huán)(后面調用
wake_up(x)
進(jìn)行喚醒)當任何能改變等待條件
的值的變量發(fā)生改變時(shí),要調用
wake_up()
;


wait_event(wq, condition) 			__wait_event()的基礎上多了一次查詢(xún)(每次被喚醒的時(shí)候)		

#define __wait_event_timeout(wq, condition, ret) \

condition滿(mǎn)足或ret使用完了時(shí)進(jìn)程被喚醒;返回值為:return timeout < 0 ? 0 : timeout

timeout是一個(gè)jiffies類(lèi)型的變量,當時(shí)間用完了,函數返回0,當等待的條件成立了,
timeout
還未用完,則將最后的jiffies保留下來(lái)。類(lèi)似的操作還有:
 #define __wait_event_interruptible_timeout(wq, condition, ret)
\
可中斷,有超時(shí)時(shí)間的__wait_event(),當timeout長(cháng)的時(shí)間完了后,函數返回0;當時(shí)間未完,
函數被信號中斷則返回
-ERESTARTSYS
;如果timeout isn't out,保留jiffies最后的值;
#define wait_event_interruptible_timeout(wq, condition, timeout) \

多了一次查詢(xún)


#define __wait_event_interruptible_exclusive(wq, condition, ret)	\#define wait_event_interruptible_exclusive(wq, condition)		\這幾個(gè)函數都有用到prepare_to_wait()下面分析一下這個(gè)函數;prepare_to_wait() 函數

void fastcall

prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)

{

unsigned long flags;

wait->flags &= ~WQ_FLAG_EXCLUSIVE; //弄清楚這一行是什么意思;

spin_lock_irqsave(&q->lock, flags); //獲得自旋鎖并保存EFLAGS的值

if (list_empty(&wait->task_list)) //判斷是等待隊列是否為空:空時(shí)返回1;函數為:

//static inline int list_empty(const struct list_head *head)

__add_wait_queue(q, wait); //{ return head->next == head;}

/* 插入等待隊列中(為何空時(shí)插入,非空時(shí)不行?

* don't alter the task state if this is just going to

* queue an async wait queue callback

*/

if (is_sync_wait(wait))

set_current_state(state); //因為非阻塞進(jìn)程訪(fǎng)問(wèn)不到設備時(shí)并不掛起,所以不改狀態(tài)

//set_current_state()->set_mb()->mb() :強制順序執行(更改狀態(tài))

//函數mb()內存柵頭文件中定義的

spin_unlock_irqrestore(&q->lock, flags);//解鎖將EFLAGS的值讀回

}

prepare_to_wait()的作用是將等待隊列插入等待隊列鏈表中,并更改等待隊列的狀態(tài)為state;





inux將進(jìn)程狀態(tài)描述為如下五種:

TASK_RUNNING:可運行狀態(tài)。處于該狀態(tài)的進(jìn)程可以被調度執行而成為當前進(jìn)程。

TASK_INTERRUPTIBLE:可中斷的睡眠狀態(tài)。處于該狀態(tài)的進(jìn)程在所需資源有效時(shí)被喚醒,也可以通過(guò)信號或定時(shí)中斷喚醒。

TASK_UNINTERRUPTIBLE:不可中斷的睡眠狀態(tài)。處于該狀態(tài)的進(jìn)程僅當所需資源有效時(shí)被喚醒。

TASK_ZOMBIE:僵尸狀態(tài)。表示進(jìn)程結束且已釋放資源,但其task_struct仍未釋放。

TASK_STOPPED:暫停狀態(tài)。處于該狀態(tài)的進(jìn)程通過(guò)其他進(jìn)程的信號才能被喚醒。


喚醒:

#define wake_up(x) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL)


void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,

int nr_exclusive, void *key)

{

unsigned long flags;


spin_lock_irqsave(&q->lock, flags);

__wake_up_common(q, mode, nr_exclusive, 0, key);

spin_unlock_irqrestore(&q->lock, flags);

}

Wake_up()喚醒等待隊列中的進(jìn)程,其參數含義:

q:等待隊列;

mode:要喚醒的進(jìn)程

nr_exclusive:要喚醒的進(jìn)程數;

keyis directly passed to the wakeup function

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
內核等待隊列機制原理分析 - wilson的日志 - 網(wǎng)易博客
wake_event
Linux內核的同步機制(三):等待隊列
阻塞與非阻塞I/O
linux中的阻塞機制及等待隊列
等待隊列 - Linux - chinaunix
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久