在使用等待队列的时候我们知道需要以下步骤:
1.定义并初始化一个等待队列头wait_queue_head_t
DECLARE_WAIT_QUEUE_HEAD(my_queue); <==> init_waitqueue_head(); + wait_queue_head_t *q;
2.调用wait_event , wait_event_interruptible , wait_event_timeout , wait_event_interruptible_timeout , wait_event_killable中的一个函数
让进程阻塞
如何让一个进程阻塞呢?我们看来看看wait_event的实现
#define __wait_event(wq, condition) \
do { \
DEFINE_WAIT(__wait); \
\
for (;;) { \
prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
} \
finish_wait(&wq, &__wait); \
} while (0)
struct task的全局变量,他表示的就是当前进程。所以我们也可以将wait_queue_t当作是当前进程的一个表示。
#define DEFINE_WAIT_FUNC(name, function) \
wait_queue_t name = { \
.private = current, \
.func = function, \
.task_list = LIST_HEAD_INIT((name).task_list), \
}
struct list_head task_list将当前进程都串起来。然后调用set_current_state将当前进程设置成TASK_INTERRUPTIBLE,最后返回__wait_event判断condition来调用
schdule()来调度别的进程,从而阻塞当前进程。
prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
{
unsigned long flags;
wait->flags &= ~WQ_FLAG_EXCLUSIVE;
spin_lock_irqsave(&q->lock, flags);
if (list_empty(&wait->task_list))
__add_wait_queue(q, wait);
set_current_state(state);
spin_unlock_irqrestore(&q->lock, flags);
}
因为我们经常是在驱动程序中使用等待队列,但是不同的进程打开同一个设备的时候所使用的驱动程序肯定是一个,所以我们不同进程使用在驱动程序中定义的
wait_queue_head_t是可以共享的,也就是说不同的进程使用wake_up(wait_queue_head_t)的时候是可以访问到同一个等待队列头的,从而使用一个进程的某些操作来
唤醒另外的在wait_queue_head_t中阻塞进程是可以实现的。