原创 Linux中等待队列机制分析

2008-7-11 10:21 7000 3 3 分类: MCU/ 嵌入式


什么是等待队列?



       在软件开发中任务经常由于某种条件没有得到满足而不得不进入睡眠状态,然后等待条件得到满足的时候再继续运行,进入运行状态。这种需求需要等待队列机制的支持。Linux中提供了等待队列的机制,该机制在内核中应用很广泛。



 



       Linux内核中使用等待队列的过程很简单,首先定义一个wait_queue_head,然后如果一个task想等待某种事件,那么调用wait_event(等待队列,事件)就可以了。



 



Linux中等待队列的实现



       等待队列应用广泛,但是内核实现却十分简单。其涉及到两个比较重要的数据结构:



1)       
__wait_queue_head,该结构描述了等待队列的链头,其包含一个链表和一个原子锁,结构定义如下:



struct
__wait_queue_head {



              spinlock_t lock;                    /* 保护等待队列的原子锁 */



              struct list_head task_list;              /* 等待队列 */



};



2)       
__wait_queue,该结构是对一个等待任务的抽象。每个等待任务都会抽象成一个wait_queue,并且挂载到wait_queue_head上。该结构定义如下:



struct
__wait_queue {



       unsigned int flags;



       void *private;                       /* 通常指向当前任务控制块 */



       /* 任务唤醒操作方法,该方法在内核中提供,通常为autoremove_wake_function */



       wait_queue_func_t func;             



       struct list_head task_list;              /* 挂入wait_queue_head的挂载点 */



};



 



        Linux中等待队列的实现思想如下图所示,当一个任务需要在某个wait_queue_head上睡眠时,将自己的进程控制块信息封装到wait_queue中,然后挂载到wait_queue的链表中,执行调度睡眠。当某些事件发生后,另一个任务(进程)会唤醒wait_queue_head上的某个或者所有任务,唤醒工作也就是将等待队列中的任务设置为可调度的状态,并且从队列中删除。

点击看大图


    使用等待队列时首先需要定义一个wait_queue_head,这可以通过DECLARE_WAIT_QUEUE_HEAD宏来完成,这是静态定义的方法。该宏会定义一个wait_queue_head,并且初始化结构中的锁以及等待队列。当然,动态初始化的方法也很简单,初始化一下锁及队列就可以了。



 



       一个任务需要等待某一事件的发生时,通常调用wait_event,该函数会定义一个wait_queue,描述等待任务,并且用当前的进程描述块初始化wait_queue,然后将wait_queue加入到wait_queue_head中。函数实现流程说明如下:



1、 
用当前的进程描述块(PCB)初始化一个wait_queue描述的等待任务。



2、 
在等待队列锁资源的保护下,将等待任务加入等待队列。



3、 
判断等待条件是否满足,如果满足,那么将等待任务从队列中移出,退出函数。



4、 
如果条件不满足,那么任务调度,将CPU资源交与其它任务。



5、 
当睡眠任务被唤醒之后,需要重复(2)、(3)步骤,如果确认条件满足,退出等待事件函数。



 



等待队列编程接口




序号



编程接口



使用说明



1



wait_event



这是一个宏,让当前任务处于等待事件状态。输入参数如下:


@wq:等待队列


@conditions:等待条件



2



wait_event_timeout



功能与wait_event类似,多了一个超时机制。参数中多了一项超时时间。



3



wait_event_interruptible



这是一个宏,与前两个宏相比,该宏定义的等待能够被消息唤醒。如果被消息唤醒,那么返回- ERESTARTSYS。输入参数如下:


@wq:等待队列


@condition:等待条件


@rt:返回值



4



wait_event_interruptible_timeout



与(3)相比,多了超时机制



5



wake_up



唤醒等待队列中的一个任务



6



wake_up_all



唤醒等待队列中的所有任务




 



 





文章评论0条评论)

登录后参与讨论
相关推荐阅读
tiloog 2012-12-18 12:58
我的存储之道博客
大家好,最近一直在做存储方面的工作,所以我在51CTO上专门开辟了一个空间讨论存储相关的问题,喜欢存储的朋友可以可以访问我的存储博客: 存储之道 (http://alanwu.blog.51cto...
tiloog 2012-04-06 21:39
SAS Cable可以有多长?
SAS接口是高端硬盘的主流接口,是存储系统的理想选择。我们知道高速信号的传输距离和传输线相关的,那么SAS作为外部通信接口,其Cable线具体可以有多长呢? 我在网上找到上图所示的眼图测...
tiloog 2012-04-06 21:38
对TRIM SCSI命令的一些分析
前一段时间做了一些对SSD方面进行优化的工作,SSD最大的问题在于长时间使用之后,IO性能会急剧下降。其主要问题在于为了防止“写放大”问题的产生,SSD的firmware采用了类似于log方式的算...
tiloog 2012-04-06 21:35
惊叹!我们的跨洋网络
  每次地质自然灾害的时候,总会伴随着网络的问题,这是由于我们的越洋光纤网络出了故障,受到自然力的破坏而导致断裂。越洋光纤,听起来的确是件非常不可思议的事情,工程量非常的巨大,但正是如此伟大的...
tiloog 2012-04-06 21:33
科学仪器网络模型
科学仪器概述     科学仪器发展趋势 科学是从测量开始的,科学仪器是信息技术的源头,是信息产业的重要组成部分,是现代科学与工业的基石。科学仪器产业的发展关系到国家科学研究实力、生...
tiloog 2012-04-06 21:16
谈谈RAID产品与技术
说起RAID,学计算机的同学马上会说RAID技术简单啊,就是将数据条带化,然后计算一些冗余数据,一并写入磁盘。通过RAID技术一方面提高系统的IO性能;另一方面提高系统的可靠性。单纯从RAID的原...
广告
我要评论
0
3
1
2
3
4
5
6
7
8
9
0
广告
关闭 热点推荐上一条 /6 下一条