内核的等待队列
creator sz111@126.com
1.
等待队列在内核中有着极其重要的作用,作为异步操作,他的实现简单而又强大。
它通过一个双链表和把等待tast的头,和等待的进程列表链接起来。从上图可以清晰看到。所以我们知道,如果要实现一个等待队列,首先要有两个部分。队列头和队列项。下面看他们的数据结构。
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;
//实际在用的时候,仍然把private赋值为task
wait_queue_func_t func;
struct list_head task_list;
};
typedef struct __wait_queue wait_queue_t;
所以队列头和队列项是通过list_head联系到一起的,list_head是一个双向链表,在linux内核中有着广泛的应用。并且在list.h中对它有着很多的操作。
2.对列头和队列项的初始化:
/*
* Macros for declaration and initialisaton of the datatypes
*/
#define __WAITQUEUE_INITIALIZER(name, tsk) { \
.private = tsk, \
.func = default_wake_function, \
.task_list = { NULL, NULL } }
//这个是初始化一个队列项,设定tast_list链表前后都是空,说明还没有加入到链表里面。
//私有数据private为任务的任务结构。
//这个宏说声明和初始化都同时做了。如果不愿意这样的话,可以先声明,然后通过
//init_waitqueue_entry进行完成。
#define DECLARE_WAITQUEUE(name, tsk) \
wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.task_list = { &(name).task_list, &(name).task_list } }
//声明一个队列头,让他的链表前后都指向自己,这个时候还没有加入任何的链表项。
//这个宏说声明和初始化都同时做了。如果不愿意这样的话,可以先声明,然后通过
//init_waitqueue_head进行完成。
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#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所在的链表头部,该函数假设已经获得锁
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所在的链表尾部,该函数假设已经获得锁。
//其实因为队列是个环形队列,所以head是头,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);
}
static inline void __remove_wait_queue(wait_queue_head_t *head,
wait_queue_t *old)
{
list_del(&old->task_list);
}
creator sz111@126.com
1.
等待队列在内核中有着极其重要的作用,作为异步操作,他的实现简单而又强大。

它通过一个双链表和把等待tast的头,和等待的进程列表链接起来。从上图可以清晰看到。所以我们知道,如果要实现一个等待队列,首先要有两个部分。队列头和队列项。下面看他们的数据结构。
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;
//实际在用的时候,仍然把private赋值为task
wait_queue_func_t func;
struct list_head task_list;
};
typedef struct __wait_queue wait_queue_t;
所以队列头和队列项是通过list_head联系到一起的,list_head是一个双向链表,在linux内核中有着广泛的应用。并且在list.h中对它有着很多的操作。
2.对列头和队列项的初始化:
/*
* Macros for declaration and initialisaton of the datatypes
*/
#define __WAITQUEUE_INITIALIZER(name, tsk) { \
.private = tsk, \
.func = default_wake_function, \
.task_list = { NULL, NULL } }
//这个是初始化一个队列项,设定tast_list链表前后都是空,说明还没有加入到链表里面。
//私有数据private为任务的任务结构。
//这个宏说声明和初始化都同时做了。如果不愿意这样的话,可以先声明,然后通过
//init_waitqueue_entry进行完成。
#define DECLARE_WAITQUEUE(name, tsk) \
wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.task_list = { &(name).task_list, &(name).task_list } }
//声明一个队列头,让他的链表前后都指向自己,这个时候还没有加入任何的链表项。
//这个宏说声明和初始化都同时做了。如果不愿意这样的话,可以先声明,然后通过
//init_waitqueue_head进行完成。
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#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所在的链表头部,该函数假设已经获得锁
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所在的链表尾部,该函数假设已经获得锁。
//其实因为队列是个环形队列,所以head是头,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);
}
static inline void __remove_wait_queue(wait_queue_head_t *head,
wait_queue_t *old)
{
list_del(&old->task_list);
}
0
