Linux设备驱动开发基础--阻塞型设备驱动
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设备驱动开发基础--阻塞型设备驱动的更多相关文章
- Linux 网络协议栈开发基础篇—— 网桥br0
一.桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口"连接"起来.其结果是,其中一个网口收到的报文会被复制给其他网口并发送出去.以使得网口之间的报文能够互相转发. 交换机 ...
- arm-linux字符设备驱动开发之---简单字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...
- usb驱动开发5之总线设备与接口
Linux设备模型中的总线落实在USB子系统里就是usb_bus_type,它在usb_init的函数bus_register(&usb_bus_type)里注册.usb_bus_type定义 ...
- usb驱动开发4之总线设备驱动模型
在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...
- WindowsNT设备驱动程序开发基础
一.背景介绍 1.1WindowsNT操作系统的组成1.1.1用户模式(UserMode)与内核模式(KernelMode) 从Intel80386开始,出于安全性和稳定性的考虑,该系列的CPU可以运 ...
- Windows驱动程序开发基础(四)驱动的编译调试和安装
Windows驱动程序开发基础,转载标明出处:http://blog.csdn.net/ikerpeng/article/details/38793995 以下说一下开发出来驱动程序以后怎样编译.一般 ...
- Android系统移植与驱动开发——第七章——LED驱动
LED驱动的实现原理 编写LED驱动: 测试LED驱动之前需要用USB数据线连接开发板,然后打开电源,成功启动之后,执行build.sh脚本文件编译和安装LED驱动,顺利则会自动连接 如果有多个设备文 ...
- 【Spring注解驱动开发】聊聊Spring注解驱动开发那些事儿!
写在前面 今天,面了一个工作5年的小伙伴,面试结果不理想啊!也不是我说,工作5年了,问多线程的知识:就只知道继承Thread类和实现Runnable接口!问Java集合,竟然说HashMap是线程安全 ...
- Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动【转】
本文转载自:https://blog.csdn.net/zqixiao_09/article/details/50858776 版权声明:本文为博主原创文章,未经博主允许不得转载. https: ...
随机推荐
- VMWare、Ubuntu Server 18.04 共享文件夹
背景:VMWare选项中配置了共享文件夹,装完Ubuntu Server 18.04在 /mnt/下都没有 hgfs文件夹,更别提共享文件夹了 参考:Ubuntu16.04版安装VMwareTools ...
- Robot Framework - 常用断言讲解
RobotFramework带有丰富的系统关键,使用时无需导入,直接使用,为写自动化用例带来了极大的方便:不能停留在知道或者是会得程度,只有熟练使用各关键字,才能提升自动化用例的写作效率. 下面将逐个 ...
- Linux下的fdlisk - l 用法解析-入门篇
fdlisk - l 的含义是查看linux下面的磁盘分区大小.这个大小包含了很多信息. 我们来看度娘的一则介绍: FDISK进行硬盘分区从实质上说就是对硬盘的一种格式化.当我们创建分区时,就已经设置 ...
- App测试从入门到精通之性能测试
好了,上节我们介绍了关于APP测试的功能测试方面一些细节.这一篇我们来介绍一下,关于APP测试过程中的性能测试参考要点,我们需要思考的如下: 响应时间 1.APP安装卸载的响应时间 2.APP各种功能 ...
- C# 关于接口与基类的理解(二者的区别)
接口(接口的名称一般用大写字母I开头的)是把公共实例(非静态)方法和属性组合起来,以封装特定功能的一个集合.(其实,接口简单理解就是一种约定,使得实现接口的类或结构在形式上保持一致) 注意:使用接口可 ...
- HTML5+CSS3网站设计教程 (张晓景,胡克) [iso]
<HTML5+CSS3网站设计教程>系统地讲解了CSS的基础理论和实际运用技术,并结合多个案例讲解了采用CSS与层布局相结合制作网页的方法,在详细讲解各个案例的制作中,不仅介绍了CSS样式 ...
- SharePoint 2013在浏览器中打开pdf文档
在没有安装Office Web Apps的情况下,SharePoint 2013是支持在IE上直接打开pdf和Excel文档的(只能查看,不能编辑,部分Excel会报错). 当然,需要现在管理中心做一 ...
- Log--日志变大原因总结
1. 有产生大日志操作,如重建整理索引,大量数据修改等2. 长期未提交事务,为保证为提交事务可以回滚,从最早为提交事务开始之后的所有事务,都是活动事务,不能被截断或覆盖3. 日志没有定期备份4. 镜像 ...
- IIS将http强转为https(重定向和重写)
最近接到一个需求,客户希望无论是http还是https请求都可以访问,并且http能转换成https.研究了一圈发现iis的重定向和重写都可以实现http强转https,记录一下. 用到的东东: In ...
- Kylin存储和查询的分片问题
本文来自网易云社区 作者:汪胜 相关概念介绍 为了了解Kylin存储和查询的分片问题,需要先介绍两个重要概念:segment和cuboid.相信大数据行业的相关同学都不陌生.Kylin每次提交一个新的 ...