數據結構如下:
struct completion { unsigned int done; //指示等待的事件是否完成。初始化時為0。 //如果為0,則表示等待的事件未完成。大于0表示等待的事件已經完成 wait_queue_head_t wait;//存放等待該事件完成的進程隊列};1) init_completion(&completion) init_completion()會將done字段初始化為0,wait字段的自旋鎖為未鎖,等待隊列為空。 這說明調用該完成量的進程必須等待某事件完成(即另外一進程必須先調用completiom()喚醒該完成量)。
static inline void init_completion(struct completion *x){ x->done = 0; init_waitqueue_head(&x->wait);}#define init_waitqueue_head(q) / do { / static struct lock_class_key __key; / / __init_waitqueue_head((q), #q, &__key); / } while (0)void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct lock_class_key *key){ spin_lock_init(&q->lock); lockdep_set_class_and_name(&q->lock, key, name); INIT_LIST_HEAD(&q->task_list);}2) DECLARE_COMPLETION(completion); 直接定義并初始化completion完成量,效果等同于以上定義方式
1) wait_for_completion()函數
void __sched wait_for_completion(struct completion *x){ wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);}static long __schedwait_for_common(struct completion *x, long timeout, int state){ return __wait_for_common(x, schedule_timeout, timeout, state);}static inline long __sched__wait_for_common(struct completion *x, long (*action)(long), long timeout, int state){ might_sleep(); spin_lock_irq(&x->wait.lock); timeout = do_wait_for_common(x, action, timeout, state); spin_unlock_irq(&x->wait.lock); return timeout;}static inline long __scheddo_wait_for_common(struct completion *x, long (*action)(long), long timeout, int state){ if (!x->done) { /*該函數相當于信號量中的down()操作。不過在操作中對使用其自身的自旋鎖。如果done為0, 則說明等待的事件沒有完成,則調用DECLARE_WAITQUEUE()定義等待隊列wait并將當前進程 添加進等待隊列wait。然后將wait添加進該完成量的等待隊列的末尾,進入循環。 設置當前進程為不可中斷狀態(TASK_UNINTERRUPTIBLE),釋放自旋鎖并讓當前進程進入睡眠狀態。 一旦進程被調度喚醒據又獲得自旋鎖并查看等待的事件是否完成。如果完成(大于0), 則從完成量的等待隊列中刪除等待的進程,并自減*/ DECLARE_WAITQUEUE(wait, current); __add_wait_queue_tail_exclusive(&x->wait, &wait); do { if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; } __set_current_state(state); spin_unlock_irq(&x->wait.lock); timeout = action(timeout); spin_lock_irq(&x->wait.lock); } while (!x->done && timeout); __remove_wait_queue(&x->wait, &wait); if (!x->done) return timeout; } x->done--; return timeout ?: 1;}2) wait_for_completion_timeout() 也是等待完成量。與wait_for_completion()最大的區別是它等待超時的情況下返回。也就是說如果經過給定的時間該完成量還沒有被喚醒,就直接返回。這樣最大的好處是經過一定的時間該進程已經不需要等待某事件,那么就可以直接被喚醒繼續執行。
3) wait_for_completion_interruptible() 這個函數的等待完成量的方式是可以被信號打斷的。如果當前進程收到 如果收到TIF_SIGPENDING信號,則等待該完成量的進程會被從等待隊列中刪除,并返回ERESTARTSYS
4) wait_for_completion_interruptible_timeout() 可中斷的并且可超時返回的等待完成量。
completion()函數 : 喚醒所有等待給完成量的進程
新聞熱點
疑難解答