1. 当一个设备无法立刻满足用户的读写请求时(例如调用read时,设备没有数据提供),驱动程序应当(缺省的)阻塞进程,使它进入等待(睡眠)状态,知道请求可以得到满足。

2. Linux内核等待队列:在实现阻塞驱动的过程中,需要有一个“候车室”来安排被阻塞的进程“休息”,当唤醒它们的条件成熟时,则可以从“候车室”中将这些进程唤醒。而这个“候车室”就是等待队列。

3. Linux内核等待队列的使用

(1)定义等待队列

wait_queue_head_t my_queue;

(2)初始化等待队列

init_waitqueue_head(&my_queue);

(3)定义+初始化等待队列

DECLARE_WAIT_QUEUE_HEAD(my_queue)

(4)使进程进入等待队列

① wait_event

wait_event(queue, condition)

  当condition(布尔表达式)为真时,立即返回;否则让进程进入TASK_UNINTERRUPTIBLE模式的睡眠,并挂在queue参数所指定的等待队列上。

② wait_event_interruptible

wait_event_interruptible(queue, condition)

  当condition(布尔表达式)为真时,立即返回;否则让进程进入TASK_INTERRUPTIBLE的睡眠,并挂在queue参数所指定的等待队列上。

③ wait_event_killable

wait_event_killable(queue, condition)

  当condition(一个布尔表达式)为真时,立即返回;否则让进程进入TASK_KILLABLE的睡眠,并挂在queue参数所指定的等待队列上。

(5)从等待队列中唤醒进程

① wake_up:

wake_up(wait_queue_t *q)

  从等待队列q中唤醒状态为TASK_UNINTERRUPTIBLE,TASK_INTERRUPTIBLE,TASK_KILLABLE 的所有进程。

② wake_up_interruptible

wake_up_interruptible(wait_queue_t *q)

  从等待队列q中唤醒状态为TASK_INTERRUPTIBLE 的进程

4. 简单示例

#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <asm/uaccess.h> #define GPGCON 0x56000060
#define GPGDAT 0x56000064 unsigned int *gpio_config; struct timer_list buttons_timer; unsigned int key_num = ; wait_queue_head_t key_wait_queue; void keys_timer_function(unsigned long data)
{
printk("keys_timer_function\n"); key_num = ; printk("data = %lx\n", data); switch(data)
{
case IRQ_EINT8:
key_num = ;
break; case IRQ_EINT11:
key_num = ;
break; case IRQ_EINT13:
key_num = ;
break;
case IRQ_EINT14:
key_num = ;
break; case IRQ_EINT15:
key_num = ;
break; case IRQ_EINT19:
key_num = ;
break; default:
break;
} printk("key_num = %d\n", key_num); wake_up(&key_wait_queue);
} irqreturn_t key_int(int irq, void *dev_id)
{
//1. 检测是否发生了按键中断 //2. 清除已经发生的按键中断 //3. 提交下半部
buttons_timer.data = (unsigned long)irq;
mod_timer(&buttons_timer, jiffies + (HZ / )); //return 0;
return IRQ_HANDLED;
} void key_hw_init(void)
{
unsigned int config_data; config_data = readl(gpio_config);
config_data &= 0b00111100;
config_data |= 0b10000010; printk("config_data = %x\n", config_data); writel(config_data, gpio_config);
} int key_open(struct inode *node,struct file *filp)
{
return ;
} ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
wait_event(key_wait_queue, key_num); printk("in kernel: key num is %d\n",key_num);
copy_to_user(buf, &key_num, ); key_num = ; return ;
} struct file_operations key_fops =
{
.open = key_open,
.read = key_read,
}; struct miscdevice key_miscdev = {
.minor = ,
.name = "key",
.fops = &key_fops,
}; static int button_init(void)
{
int ret; gpio_config = ioremap(GPGCON, ); ret = misc_register(&key_miscdev); printk("ret = %d\n", ret); if (ret == )
{
//按键初始化
key_hw_init(); //注册中断处理程序
request_irq(IRQ_EINT8, key_int, IRQF_TRIGGER_LOW, "key1", );
request_irq(IRQ_EINT11, key_int, IRQF_TRIGGER_LOW, "key2", );
request_irq(IRQ_EINT13, key_int, IRQF_TRIGGER_LOW, "key3", );
request_irq(IRQ_EINT14, key_int, IRQF_TRIGGER_LOW, "key4", );
request_irq(IRQ_EINT15, key_int, IRQF_TRIGGER_LOW, "key5", );
request_irq(IRQ_EINT19, key_int, IRQF_TRIGGER_LOW, "key6", ); /* 初始化定时器 */
init_timer(&buttons_timer);
buttons_timer.function = keys_timer_function; /* 向内核注册一个定时器 */
add_timer(&buttons_timer); /* 初始化等待队列 */
init_waitqueue_head(&key_wait_queue);
}
else
{
printk("register fail!\n");
} return ret;
} static void button_exit(void)
{
iounmap(gpio_config); free_irq(IRQ_EINT8, );
free_irq(IRQ_EINT11, );
free_irq(IRQ_EINT13, );
free_irq(IRQ_EINT14, );
free_irq(IRQ_EINT15, );
free_irq(IRQ_EINT19, ); misc_deregister(&key_miscdev);
} module_init(button_init);
module_exit(button_exit);

Linux设备驱动开发基础--阻塞型设备驱动的更多相关文章

  1. Linux 网络协议栈开发基础篇—— 网桥br0

    一.桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口"连接"起来.其结果是,其中一个网口收到的报文会被复制给其他网口并发送出去.以使得网口之间的报文能够互相转发. 交换机 ...

  2. arm-linux字符设备驱动开发之---简单字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...

  3. usb驱动开发5之总线设备与接口

    Linux设备模型中的总线落实在USB子系统里就是usb_bus_type,它在usb_init的函数bus_register(&usb_bus_type)里注册.usb_bus_type定义 ...

  4. usb驱动开发4之总线设备驱动模型

    在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...

  5. WindowsNT设备驱动程序开发基础

    一.背景介绍 1.1WindowsNT操作系统的组成1.1.1用户模式(UserMode)与内核模式(KernelMode) 从Intel80386开始,出于安全性和稳定性的考虑,该系列的CPU可以运 ...

  6. Windows驱动程序开发基础(四)驱动的编译调试和安装

    Windows驱动程序开发基础,转载标明出处:http://blog.csdn.net/ikerpeng/article/details/38793995 以下说一下开发出来驱动程序以后怎样编译.一般 ...

  7. Android系统移植与驱动开发——第七章——LED驱动

    LED驱动的实现原理 编写LED驱动: 测试LED驱动之前需要用USB数据线连接开发板,然后打开电源,成功启动之后,执行build.sh脚本文件编译和安装LED驱动,顺利则会自动连接 如果有多个设备文 ...

  8. 【Spring注解驱动开发】聊聊Spring注解驱动开发那些事儿!

    写在前面 今天,面了一个工作5年的小伙伴,面试结果不理想啊!也不是我说,工作5年了,问多线程的知识:就只知道继承Thread类和实现Runnable接口!问Java集合,竟然说HashMap是线程安全 ...

  9. Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动【转】

    本文转载自:https://blog.csdn.net/zqixiao_09/article/details/50858776 版权声明:本文为博主原创文章,未经博主允许不得转载.    https: ...

随机推荐

  1. MYSQL优化——索引覆盖

    索引覆盖:如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要进行到磁盘中找数据,若果查询得列不是索引的一部分则要到磁盘中找数据. 建表: create table test_ind ...

  2. Flask框架 之 wtforms

    简介 WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证. 作用 生成HTML标签 form表单验证 使用 - 用户登录示例- 用户注册示例- 数据库获取数据实时更新 ...

  3. 复习HTTP状态码+301和302

    一,HTTP状态码: 1xx:(信息状态码),接受的请求正在处理.2xx:(成功状态码),请求正常处理完毕.3xx:(重定向状态码),需要进行附加操作以完成请求.4xx:(客户端错误状态码),服务器无 ...

  4. Robot Framework - 常用断言讲解

    RobotFramework带有丰富的系统关键,使用时无需导入,直接使用,为写自动化用例带来了极大的方便:不能停留在知道或者是会得程度,只有熟练使用各关键字,才能提升自动化用例的写作效率. 下面将逐个 ...

  5. Maven整理笔记の初步窥探

    第一部分:引言 Maven是一款跨平台的项目管理工具,作为Apache组织的一个开源项目,主要服务于基于java平台的项目构建.依赖管理和项目信息管理. 项目构建:编译.运行单元测试.生成文档.打包和 ...

  6. asp.net 类,接口

    ASP.NET抽象类和接口的比较 相同点 ●都不能被直接实例化,都可以通过继承实现其抽象方法. ●都是面向抽象编程的技术基础,实现了诸多的设计模式. 不同点 ●接口支持多继承:抽象类不能实现多继承.  ...

  7. C#生成静态文件

    一般生成文件都是通过读取模板文件,然后替换标签. 这些古老的方法使用起来不但麻烦而且效率还不怎么样. 这里给添加介绍一个方法. 如果你用过asp.net.mvc (Razor),你就应该明白 chtm ...

  8. 使用VS Code编写Markdown文件

    VS Code默认支持Markdown文件文件格式,这里介绍两个比较实用的功能,后续有新发现,可以持续更新. 实时预览 顾名思义,实时编辑,实时预览解析效果. 在VS Code扩展中搜索"M ...

  9. firefox 59 无法使用 pac 代理上网

    最近装了 firefox,电脑配置不太高,chrome 太吃内存了. 但是发现 SwitchyOmega的 pac 模式无法工作,这篇文章提到了两个思路, 其中network.dns.disableI ...

  10. git Problem with the SSL CA cert (path? access rights?)

    问题: [root@localhost opt]# git clone https://github.com/docker/docker.git 正克隆到 'docker'...fatal: unab ...