内核等待队列 --- wait_queue_head --- wait_event_interruptible

2023-10-20 09:32

本文主要是介绍内核等待队列 --- wait_queue_head --- wait_event_interruptible,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

链接:https://blog.csdn.net/yikai2009/article/details/8653578

等待队列:

      在 Linux 驱动程序设计中,可以使用等待队列来实现进程的阻塞.等待队列可以看作保存进程的容器,在阻塞进程时,将进程放入等待队列;当唤醒进程时,从等待队列中取出进程.

等待队列的 定义 和 初始化 wait_queue_head_t DECLARE_WAIT_QUEUE_HEAD :

      Linux 2.6 内核提供了如下关于等待队列的操作:1,定义等待队列.wait_queue_head_t   my_queue2,初始化等待队列.init_waitqueue_head ( &my_queue )3,定义并初始化等待队列.DECLARE_WAIT_QUEUE_HEAD  ( my_queue )

等待队列的 睡眠 wait_event_interruptible :
有条件睡眠:

          1,  wait_event ( queue , condition )当 condition ( 一个布尔表达式 ) 为真,立即返回;否则让进程进入 TASK_UNINTERRUPTIBLE 模式睡眠,并挂在 queue 参数所指定的等待队列上.2,  wait_event_interruptible ( queue , condition )当 condition ( 一个布尔表达式 ) 为真,立即返回;否则让进程进入 TASK_INTERRUPTIBLE 模式睡眠,并挂在 queue 参数所指定的等待队列上.3, int  wait_event_killable ( wait_queue_t  queue , condition )当 condition ( 一个布尔表达式 ) 为真,立即返回;否则让进程进入 TASK_KILLABLE 模式睡眠,并挂在 queue 参数所指定的等待队列上.

无条件睡眠:

                ( 老版本,不建议使用 )sleep_on  ( wait_queue_head_t  *q )让进程进入 不可中断 的睡眠,并把它放入等待队列 q.interruptible_sleep_on  ( wait_queue_head_t  *q )让进程进入 可中断 的睡眠,并把它放入等待队列 q.

等待队列中唤醒进程 wake_up :

                wake_up ( wait_queue_t  *q )从等待队列 q 中唤醒状态为 TASKUNINTERRUPTIBLE ,TASK_INTERRUPTIBLE ,TASK_KILLABLE的所有进程.wake_up_interruptible ( wait_queue_t  *q )从等待队列 q 中唤醒状态为 TASK_INTERRUPTIBLE 的进程.

实例 — 按键驱动程序 优化:

下面列出一个实例,方便理解和使用 等待队列:

比如我们在编写 按键驱动程序的时候,我们的 应用程序 采用 while(1) 一直去 read 按键值,这样的话 CPU 消耗占用过大;

所以,我们采用 等待队列 来优化按键驱动程序:

首先 定义并且初始化 等待队列:

在程序开头 定义并且初始化 等待队列 DECLARE_WAIT_QUEUE_HEAD :

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

并定义一个 static volatile 变量 :

static volatile int ev_press = 0;

然后 在 read 方法中 将等待队列睡眠:

在有按键按下的时候,读取按键值;

在 没有按键按下 的情况下将等待队列睡眠睡眠 wait_event_interruptible :

static int tq2440_irq_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{unsigned long err;if (!ev_press){if (filp->f_flags & O_NONBLOCK)return -EAGAIN;elsewait_event_interruptible(button_waitq, ev_press);}ev_press = 0;err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));return err ? -EFAULT : min(sizeof(key_values), count);
}

再在 中断服务程序中 唤醒等待队列:

在 中断服务程序中 唤醒等待队列 wake_up_interruptible :

在 按键按下时,进入中断服务程序,在这时候 将等待队列唤醒:

static irqreturn_t irq_interrupt(int irq, void *dev_id)
{struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;int down;down = !s3c2410_gpio_getpin(button_irqs->pin);if (down != (key_values[button_irqs->number] & 1)){key_values[button_irqs->number] = '0' + down;ev_press = 1;wake_up_interruptible(&button_waitq);}return IRQ_RETVAL(IRQ_HANDLED);
}

通过 对 static volatile int ev_press 变量的值 判断,来确定 等待队列 是睡眠 还是马上读取键值 .

测试 — 按键驱动程序:
1,insmod 驱动;

2,在后台运行 测试应用程序:

3,ps 命令查看 应用程序状态:

buttons stat 状态为 sleep;

4,cat /proc/interrupts 命令 看中断有没有被申请:

看各个按键的中断有没有被申请 KEY1-4 :

5,测试按键:


作者:借我你的一生
来源:CSDN
原文:https://blog.csdn.net/yikai2009/article/details/8653578
版权声明:本文为博主原创文章,转载请附上博文链接!

这篇关于内核等待队列 --- wait_queue_head --- wait_event_interruptible的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/246227

相关文章

Java中常见队列举例详解(非线程安全)

《Java中常见队列举例详解(非线程安全)》队列用于模拟队列这种数据结构,队列通常是指先进先出的容器,:本文主要介绍Java中常见队列(非线程安全)的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一.队列定义 二.常见接口 三.常见实现类3.1 ArrayDeque3.1.1 实现原理3.1.2

解决mysql插入数据锁等待超时报错:Lock wait timeout exceeded;try restarting transaction

《解决mysql插入数据锁等待超时报错:Lockwaittimeoutexceeded;tryrestartingtransaction》:本文主要介绍解决mysql插入数据锁等待超时报... 目录报错信息解决办法1、数据库中执行如下sql2、再到 INNODB_TRX 事务表中查看总结报错信息Lock

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A

golang实现延迟队列(delay queue)的两种实现

《golang实现延迟队列(delayqueue)的两种实现》本文主要介绍了golang实现延迟队列(delayqueue)的两种实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录1 延迟队列:邮件提醒、订单自动取消2 实现2.1 simplChina编程e简单版:go自带的time

Java 的 Condition 接口与等待通知机制详解

《Java的Condition接口与等待通知机制详解》在Java并发编程里,实现线程间的协作与同步是极为关键的任务,本文将深入探究Condition接口及其背后的等待通知机制,感兴趣的朋友一起看... 目录一、引言二、Condition 接口概述2.1 基本概念2.2 与 Object 类等待通知方法的区别

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

SpringKafka错误处理(重试机制与死信队列)

《SpringKafka错误处理(重试机制与死信队列)》SpringKafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、Spring Kafka错误处理基础二、配置重试机制三、死信队列实现四、特定异常的处理策略五