DECLARE_WAITQUEUE 将进程加入等待队列

#define   DECLARE_WAITQUEUE(name,   tsk)       / 
wait_queue_t   name     =__WAITQUEUE_INITIALIZER(name,   tsk) 
#define   __WAITQUEUE_INITIALIZER(name,tsk)   {task:  tsk,  task_list:  {  NULL,NULL},  __WAITQUEUE_DEBUG_INI(name)} 

参考资料:http://blog.csdn.net/hzn407487204/article/details/5489507

                    http://www.360doc.com/content/10/1009/17/1317564_59632874.shtml
它的解释是:
通过DECLARE_WAITQUEUE宏将等待队列项初始化成对应的任务结构,并且用于连接的相关指针均设置为空。其中加入了调试相关代码。


进程通过执行下面步骤将自己加入到一个等待队列中:
1) 调用DECLARE_WAITQUEUE()创建一个等待队列的项;
2) 调用add_wait_queue()把自己加入到等待队列中。该队列会在进程等待的条件满足时唤醒它。在其他地方写相关代码,在事件发生时,对等的队列执行wake_up()操作。
3) 将进程状态变更为: TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE。
4) 如果状态被置为TASK_INTERRUPTIBLE ,则信号唤醒进程。即为伪唤醒(唤醒不是因为事件的发生),因此检查并处理信号。
5) 检查condition是否为真,为真则没必要休眠,如果不为真,则调用scheduled()。
6) 当进程被唤醒的时候,它会再次检查条件是否为真。真就退出循环,否则再次调用scheduled()并一直重复这步操作。
7) condition满足后,进程将自己设置为TASK_RUNNING 并通过remove_wait_queue()退出。

 

 

加入等待队列 | add_wait_queue() | add_wait_queue_exclusive()

内核:2.6.24
add_wait_queue() 用来将一个进程添加到等待队列,该函数在获得必要的自旋锁后,使用 __add_wait_queue() 函数来完成队列添加工作。

__add_wait_queue() 定义为:

static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
    list_add(&new->task_list, &head->task_list);//list_add() 是标准的建立队列双向链表函数。

}

另外还有一个  add_wait_queue_exclusive() 函数,它的工作方式和 add_wait_queue() 一样,但是将进程插入到队列尾部,同时还设置了 WQ_EXCLUSIVE 标志。
add_wait_queue_exclusive() 定义为:

void fastcall add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
{
    unsigned long flags;


    wait->flags |= WQ_FLAG_EXCLUSIVE;
    spin_lock_irqsave(&q->lock, flags);
    __add_wait_queue_tail(q, wait);
    spin_unlock_irqrestore(&q->lock, flags);
}
__add_wait_queue_tail() 函数定义为:

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);
}
list_add_tail() 定义为:


/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}

由此可见,添加到队列尾也是调用 __list_add() 函数,只是第 2 个参数和第 3 个参数与原来的增加到队列头的参数调换了一下顺序。

 

wait_event_interruptible()。该函数修改task的状态为TASK_INTERRUPTIBLE,意味着改进程将不会继续运行直到被唤醒,然后被添加到等待队列wq中。

在wait_event_interruptible()中首先判断condition是不是已经满足,如果是则直接返回0,否则调用__wait_event_interruptible(),并用__ret来存放返回值

---------------------------------------------------------------

#define wait_event_interruptible(wq, condition)          /

({                                                       /

    int __ret = 0;                                       /

    if (!(condition))                                    /

       
__wait_event_interruptible (wq, condition, __ret);/

    __ret;                                               /

})

wait_event_interruptible()--> __wait_event_interruptible()

__wait_event_interruptible()首先定义并初始化一个wait_queue_t变量__wait,其中数据为当前进程current,并把__wait入队。

在无限循环中,__wait_event_interruptible()将本进程置为可中断的挂起状态,反复检查condition是否成立,如果成立则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态,并将__wait从等待队列中清除掉,从而进程能够调度运行。如果进程当前有异步信号(POSIX的),则返回-ERESTARTSYS。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值