Linux核心等待佇列 原始碼簡單分析

2021-09-28 22:17:19 字數 3268 閱讀 1660

一.概述

二.等待佇列

struct __wait_queue_head 

;typedef

struct __wait_queue_head wait_queue_head_t;

因為等待佇列可以在中斷的時候進行修改,所以操作佇列之前會給佇列加上乙個自旋鎖,task_list其中是雙向佇列

struct __wait_queue 

;

為了讓當前程序在乙個等待佇列中進行睡眠,需要呼叫wait_event 函式,程序進入睡眠,將控制權釋放給排程器,但是在執行了wait_event函式之中,得要有相應的能夠達到的地方進行wake_up呼叫,讓程序從沉睡狀態中進行喚醒

我們可以使用add_wait_queue函式來將乙個程序新增到等待佇列,該函式在獲得必要的自旋鎖之後,會執行__add_wait_queue函式

void

add_wait_queue

(wait_queue_head_t *q, wait_queue_t *wait)

static

inline

void

__add_wait_queue

(wait_queue_head_t *head, wait_queue_t *new)

將任務插到佇列的頭部,其中我們還可以使用一下add_wait_queue_exclusive,這個函式會將任務插到佇列的尾部,並且將標籤進行設定為wq_exclusive

void fastcall add_wait_queue_exclusive

(wait_queue_head_t *q, wait_queue_t *wait)

我們也可以同時使用prepare_to_wait.還需要程序的狀態

void fastcall

prepare_to_wait

(wait_queue_head_t *q, wait_queue_t *wait,

int state)

export_symbol

(prepare_to_wait)

;

//初始化等待分配

void

init_waitqueue_head

(wait_queue_head_t *q)

static

inline

void

init_waitqueue_entry

(wait_queue_t *q ,

struct task_struct *p)

try_to_wake_up

(struct task_struct *p,

unsigned

int state,

int wake_flags)

我們也可以使用乙個巨集來進行wait_queue_t的初始化

#define define_wait(name) \ 

wait_queue_t name =

在這裡我們使用了autoremove_wake_function 來進行程序的喚醒,還將等待佇列成員從等待佇列中進行刪除

int

autoremove_wake_function

(wait_queue_t *wait,

unsigned mode,

int sync,

void

*key)

但是使用的過程中,add_wait_queue 通常是不直接使用的,經常使用的是wait_event

這是乙個巨集,我們可以將其展開

___wait_event

(wq, condition, state, exclusive, ret, cmd)

cmd;

//schedule(),進入睡眠,從程序就緒佇列選擇乙個高優先順序程序來代替當前程序執行

}finish_wait

(&wq,

&__wait)

;//如果__wait還位於佇列wq,則將__wait從wq中移除

}

除此之外,核心還定義了其他的幾個函式,可以將當前程序放置於等待佇列中

#define wait_event_interruptible(wq,condition)

#define wait_event_timeout(wq,condition,timeout)

#define wait_event_interruptible_timeout(wq,condition,timeout)

wait_event_interruptible 使用的程序狀態為task_interruptible,因而睡眠程式可以通過接受訊號而被喚醒

wait_event_timeout 等待滿足指定條件,等待時間超過了指定的超時限制而停止,防止程序永久沉睡

wait_event_interruptible_timeout 讓程序睡眠,但可以通過接受訊號來進行喚醒,註冊乙個超時的時間

喚醒程序,可用於喚醒等待佇列的程序,它們基於同乙個函式

void

__wake_up

(wait_queue_head_t *q,

unsigned

int mode,

int nr_exclusive,

void

*key)

static

void

__wake_up_common

(wait_queue_head_t *q,

unsigned

int mode,

int nr_exclusive,

int wake_flags,

void

*key)

//q用於選定等待佇列,mode指定程序的狀態,用於控制喚醒程序的條件 nr_exclusive

//表示將要喚醒的設定了wq_flag_exclusive標誌的程序的資料

}

在這裡會反覆的掃瞄鍊錶,直到沒有更多的程序需要喚醒,或者已經喚醒的獨佔程序的數目達到了nr_exclusive.該限制用於避免所謂的驚群問題.如果幾個程序在等待獨佔訪問的某乙個資源,那麼同時喚醒所有等待程序應該是毫無意義的,除了其中乙個,其他程序都會再次睡眠

Linux原始碼 等待佇列注釋

linux中了等待佇列的毒,中充斥著等待佇列。不信你翻翻 等待佇列的喚醒我們這裡叫啟用。免得和執行緒喚醒混淆。頭結點wait queue head t的結構 struct wait queue head 熟悉的wait queue head t實際上是struct wait queue head t...

Linux核心等待佇列

在linux驅動程式設計中,可以使用等待佇列來實現程序的阻塞,等待佇列可看作儲存程序的容器,在阻塞程序時,將程序放入等待佇列,當喚醒程序時,從等待等列中取出程序。linux 2.6核心提供了如下關於等待佇列的操作 1 定義等待佇列 wait queue head t my queue 2 初始化等待...

linux等待佇列簡析

在閱讀tun驅動時看到,有一些類似 add wait queue 的函式,這些函式正是執行等待佇列的相關操作,要說等待佇列還得從linux核心程序排程說起,核心排程系統內程序,分配時間片,但是有些程序如從網絡卡中讀資料,在網絡卡有資料到達之前程序處於阻塞狀態,如果此時給相應程序分配時間片做排程,無疑...