在<linux/wait.h>中,结构体定义如下:
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};typedef struct __wait_queue_head wait_queue_head_t;
且
struct list_head {
struct list_head *next, *prev;
};
再来看定义并初始化一个wait_queue_head_t 的函数:
主要就是定义个一个wait_queue_head_t 的变量,然后初始化,lock初始化为unlock, task_list里面的next和pre都指向自己的list_head。
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.task_list = { &(name).task_list, &(name).task_list } }
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
我们再来看这个这个结构体:
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
struct task_struct * task;
struct list_head task_list;
};
把整个队列画出来,是这样的,中间的节点是wait_queue_t,一个等待队列包含了等待特定事件的所有进程。

在我们这样使用:
DECLARE_WAIT_QUEUE_HEAD(queue_name);
就新建并初始化了一个queue的头结点。
然后调用以下函数,就新生成了一个wait_queue_t 的节点,并加入到这个队列中,这样在等待的事情发生后,内核就可以从该队列中找到等待的进程。
wait_even(queue_name, condition);
wait_even_interruptible(queue_name, condition);
wait_even_timeout(queue_name, condition, timeout);
wait_even_interruptible_timeout(queue_name, condition);
唤醒的方法:
void wake_up(wait_queue_head_t* queue);
void wake_up_interruptible(wait_queue_head_t* queue);
会唤醒等待的所有进程。注意我们一般都把wait_even与wake_up对应起来,wait_even_interruptible与 wake_up_interruptible对应起来。
本文深入探讨了Linux内核中的等待队列,重点分析了`struct wait_queue_head`及其`spinlock_t`锁和`list_head`任务列表在驱动学习中的应用。
4957

被折叠的 条评论
为什么被折叠?



