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

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

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

開(kāi)通VIP
內核的等待隊列 - Linux內核編程 - creator的天空 - m_cu的日志 - ...
內核的等待隊列
creator sz111@126.com
1.
等待隊列在內核中有著(zhù)極其重要的作用,作為異步操作,他的實(shí)現簡(jiǎn)單而又強大
500)this.width=500;" border=0>
它通過(guò)一個(gè)雙鏈表和把等待tast的頭,和等待的進(jìn)程列表鏈接起來(lái)從上圖可以清晰看到所以我們知道,如果要實(shí)現一個(gè)等待隊列,首先要有兩個(gè)部分隊列頭和隊列項下面看他們的數據結構
struct list_head {
struct list_head *next, *prev;
};
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE    0x01
void *private;//2.6版本是采用void指針,而以前的版本是struct task_struct * task;
//實(shí)際在用的時(shí)候,仍然把private賦值為task
wait_queue_func_t func;
struct list_head task_list;
};
typedef struct __wait_queue wait_queue_t;
所以隊列頭和隊列項是通過(guò)list_head聯(lián)系到一起的,list_head是一個(gè)雙向鏈表,在linux內核中有著(zhù)廣泛的應用并且在list.h中對它有著(zhù)很多的操作
2.對列頭和隊列項的初始化:
/*
* Macros for declaration and initialisaton of the datatypes
*/
#define __WAITQUEUE_INITIALIZER(name, tsk) {                \
.private    = tsk,                        \
.func        = default_wake_function,            \
.task_list    = { NULL, NULL } }
//這個(gè)是初始化一個(gè)隊列項,設定tast_list鏈表前后都是空,說(shuō)明還沒(méi)有加入到鏈表里面
//私有數據private為任務(wù)的任務(wù)結構
//這個(gè)宏說(shuō)聲明和初始化都同時(shí)做了如果不愿意這樣的話(huà),可以先聲明,然后通過(guò)
//init_waitqueue_entry進(jìn)行完成
#define DECLARE_WAITQUEUE(name, tsk)                    \
wait_queue_t tsk)
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                \
.lock        = __SPIN_LOCK_UNLOCKED(name.lock),        \
.task_list    = { &(name).task_list, &(name).task_list } }
//聲明一個(gè)隊列頭,讓他的鏈表前后都指向自己,這個(gè)時(shí)候還沒(méi)有加入任何的鏈表項
//這個(gè)宏說(shuō)聲明和初始化都同時(shí)做了如果不愿意這樣的話(huà),可以先聲明,然后通過(guò)
//init_waitqueue_head進(jìn)行完成
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t >
#define __WAIT_BIT_KEY_INITIALIZER(word, bit)                \
{ .flags = word, .bit_nr = bit, }
extern void init_waitqueue_head(wait_queue_head_t *q);
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;
}
//將指定的等待隊列項new添加到等待隊列頭head所在的鏈表頭部,該函數假設已經(jīng)獲得鎖
static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
list_add(&new->task_list, &head->task_list);
}
/*
* Used for wake-one threads:
*/
//將指定的等待隊列項new添加到等待隊列頭head所在的鏈表尾部,該函數假設已經(jīng)獲得鎖
//其實(shí)因為隊列是個(gè)環(huán)形隊列,所以head是頭,head的錢(qián)一個(gè)就可以認為是尾,當然,環(huán)形也無(wú)所//謂頭尾了
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);
}
static inline void __remove_wait_queue(wait_queue_head_t *head,
wait_queue_t *old)
{
list_del(&old->task_list);
}
3.睡眠和喚醒操作
對等待隊列的操作包括睡眠和喚醒(相關(guān)函數保存在源代碼樹(shù)的/kernel/sched.c和include/linux/sched.h中)思想是更改當前進(jìn)程(CURRENT)的任務(wù)狀態(tài),并要求重新調度,因為這時(shí)這個(gè)進(jìn)程的狀態(tài)已經(jīng)改變,不再在調度表的就緒隊列中,因此無(wú)法再獲得執行機會(huì ),進(jìn)入" 睡眠"狀態(tài),直至被"喚醒",即其任務(wù)狀態(tài)重新被修改回就緒態(tài)
常用的睡眠操作有interruptible_sleep_on和 sleep_on兩個(gè)函數類(lèi)似,只不過(guò)前者將進(jìn)程的狀態(tài)從就緒態(tài)(TASK_RUNNING)設置為T(mén)ASK_INTERRUPTIBLE,允許通過(guò)發(fā)送signal喚醒它(即可中斷的睡眠狀態(tài));而后者將進(jìn)程的狀態(tài)設置為T(mén)ASK_UNINTERRUPTIBLE,在這種狀態(tài)下,不接收任何 singal在一般情況下,我們要采用可以中斷的sleep
interruptible_sleep_on宏代碼如下:
//首先定義隊列項,然后對隊列項進(jìn)行初始化,任務(wù)結構設定為當前進(jìn)程的任務(wù)結構
#define    SLEEP_ON_VAR                    \
unsigned long flags;                \
wait_queue_t wait;                \
init_waitqueue_entry(&wait, current);
//然后把隊列項加入到隊列頭中
#define SLEEP_ON_HEAD                    \
spin_lock_irqsave(&q->lock,flags);        \
__add_wait_queue(q, &wait);            \
spin_unlock(&q->lock);
//喚醒之后要把隊列項從隊列頭上刪除
#define    SLEEP_ON_TAIL                    \
spin_lock_irq(&q->lock);            \
__remove_wait_queue(q, &wait);            \
spin_unlock_irqrestore(&q->lock, flags);
void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
{
SLEEP_ON_VAR
current->state = TASK_INTERRUPTIBLE;
SLEEP_ON_HEAD
schedule();
SLEEP_ON_TAIL
}
對應的喚醒操作包括wake_up_interruptible和wake_upwake_up函數不僅可以喚醒狀態(tài)為 TASK_UNINTERRUPTIBLE的進(jìn)程,而且可以喚醒狀態(tài)為T(mén)ASK_INTERRUPTIBLE的進(jìn)程 wake_up_interruptible只負責喚醒狀態(tài)為T(mén)ASK_INTERRUPTIBLE的進(jìn)程這兩個(gè)宏的定義如下:
#define wake_up(x)__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL)
#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE, 1, NULL)
__wake_up函數主要是獲取隊列操作的鎖,具體工作是調用__wake_up_common完成的
/**
* __wake_up - wake up threads blocked on a waitqueue.
* @q: the waitqueue喚醒的隊列的隊列頭
* @mode: which threads 喚醒那種類(lèi)型的等待隊列,如:可中斷和不可中斷
* @nr_exclusive: how many wake-one or wake-many threads to wake up
* @key: is directly passed to the wakeup function
*/
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);
}
/*
* The core wakeup function.  Non-exclusive wakeups (nr_exclusive == 0) just
* wake everything up.  If it's an exclusive wakeup (nr_exclusive == small +ve
* number) then we wake all the non-exclusive tasks and one exclusive task.
*
* There are circumstances in which we can try to wake a task which has already
* started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns
* zero in this (rare) case, and we handle it by continuing to scan the queue.
*/
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, int sync, void *key)
{
struct list_head *tmp, *next;
list_for_each_safe(tmp, next, &q->task_list) {
wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
unsigned flags = curr->flags;
//這里的func實(shí)際上是
//int default_wake_function(wait_queue_t *curr, unsigned mode, int sync,
//      void *key)
//{喚醒一個(gè)進(jìn)程,將它放到運行隊列中,如果它還不在運行隊列的話(huà)"當前"進(jìn)程總是在運行隊列中的
//    return try_to_wake_up(curr->private, mode, sync);
//}
if (curr->func(curr, mode, sync, key) &&
(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
break;
}
}
4.等待隊列的應用
等待隊列的的應用涉及兩個(gè)進(jìn)程,假設為A和BA是資源的消費者,B是資源的生產(chǎn)者A在消費的時(shí)候必須確保資源已經(jīng)生產(chǎn)出來(lái),為此定義一個(gè)資源等待隊列這個(gè)隊列同時(shí)要被進(jìn)程A和進(jìn)程B使用,我們可以將它定義為一個(gè)全局變量
DECLARE_WAIT_QUEUE_HEAD(rsc_queue); /* 全局變量 */
在進(jìn)程A中,執行邏輯如下:
while (resource is unavaiable) {
interruptible_sleep_on( &wq );
}
consume_resource();
在進(jìn)程B中,執行邏輯如下:
produce_resource();
wake_up_interruptible( &wq );
引文來(lái)源  內核的等待隊列 - Linux內核編程 - creator的天空
----------------------------
一鍵轉貼,快速捕捉生活精彩,贏(yíng)每周好禮!查看活動(dòng)首頁(yè)>>
最近讀者
傷心大樹(shù)
dengchao880214
chao_rap
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Linux內核的同步機制(三):等待隊列
內核等待隊列機制原理分析 - wilson的日志 - 網(wǎng)易博客
等待隊列 - Linux - chinaunix
linux中的阻塞機制及等待隊列
字符設備驅動(dòng)之一些函數
wake_event
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

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