wait_queue_head_t和wait_queue_t 联系

来源:互联网 发布:日剧知乎 编辑:程序博客网 时间:2024/05/16 12:17

在使用等待队列的时候我们知道需要以下步骤:


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)


这里面我们看到有一句DEFINE_WAIT(__wait);他的最终调用如下,我们看到这里面其实就是定义了一个wait_queue_t的变量,其中.private = current .这个current是一个

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),\}


我们来继续看wait_event中的prepare_to_wait函数的实现,我们看到调用__add_wait_queue将当前进程加入到一个wait_queue_head_t的等待队列头里面,利用里面的

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中阻塞进程是可以实现的。




0 0
原创粉丝点击