Linux中等待队列的实现

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

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

       Linux内核中使用等待队列的过程很简单,首先定义一个wait_queue_head,然后如果一个task想等待某种事件,那么调用wait_event(等待队列,事件)就可以了。
     等待队列应用广泛,但是内核实现却十分简单。其涉及到两个比较重要的数据结构:__wait_queue_head,该结构描述了等待队列的链头,其包含一个链表和一个原子锁,结构定义如下:

struct __wait_queue_head {
    

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

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

};

__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



 

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

 



目录
相关文章
|
7月前
|
Linux C语言
Linux内核队列queue.h
Linux内核队列queue.h
|
7月前
|
Linux C语言
Linux系统下C语言的队列操作
Linux系统下C语言的队列操作
140 0
|
Linux API 调度
Linux设备驱动workqueue(工作队列)案例实现
Linux设备驱动workqueue(工作队列)案例实现
278 0
|
4月前
|
监控 数据挖掘 Linux
Linux服务器PBS任务队列作业提交脚本的使用方法
【8月更文挑战第21天】在Linux服务器环境中,PBS任务队列能高效管理及调度计算任务。首先需理解基本概念:作业是在服务器上执行的任务;队列则是等待执行任务的列表,具有不同的资源限制与优先级;节点指分配给作业的计算资源。
627 4
|
4月前
|
Linux 调度
Linux内核的基础设施:工作队列、等待队列
本文介绍了Linux内核中的工作队列和等待队列机制,通过一个具体的Demo演示了如何使用等待队列进行条件等待和唤醒,以及工作队列的创建和调度,同时展示了修改唤醒条件导致无法唤醒进程的情况。
63 0
|
5月前
|
消息中间件 Java Kafka
kafka Linux环境搭建安装及命令创建队列生产消费消息
kafka Linux环境搭建安装及命令创建队列生产消费消息
114 4
|
7月前
|
算法 Linux 调度
【进程调度】Linux内核的进程调度队列--runqueue
【进程调度】Linux内核的进程调度队列--runqueue
|
7月前
|
存储 安全 Linux
Linux中断(tasklet,工作队列,内核线程的使用)
Linux中断(tasklet,工作队列,内核线程的使用)
140 0
|
7月前
|
存储 算法 Linux
(Linux2.6内核)进程调度队列与切换
(Linux2.6内核)进程调度队列与切换
71 0
|
关系型数据库 MySQL Linux
Linux下C语言实现MySQL操作——连接、查询、插入与客户端打造
Linux下C语言实现MySQL操作——连接、查询、插入与客户端打造
475 0
Linux下C语言实现MySQL操作——连接、查询、插入与客户端打造