博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux设备驱动开发基础--阻塞型设备驱动
阅读量:4931 次
发布时间:2019-06-11

本文共 3767 字,大约阅读时间需要 12 分钟。

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 
#include
#include
#include
#include
#include
#include
#define GPGCON 0x56000060#define GPGDAT 0x56000064unsigned int *gpio_config;struct timer_list buttons_timer;unsigned int key_num = 0;wait_queue_head_t key_wait_queue;void keys_timer_function(unsigned long data) { printk("keys_timer_function\n"); key_num = 0; printk("data = %lx\n", data); switch(data) { case IRQ_EINT8: key_num = 1; break; case IRQ_EINT11: key_num = 2; break; case IRQ_EINT13: key_num = 3; break; case IRQ_EINT14: key_num = 4; break; case IRQ_EINT15: key_num = 5; break; case IRQ_EINT19: key_num = 6; 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 / 10)); //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 0; }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, 4); key_num = 0; return 4;}struct file_operations key_fops = { .open = key_open, .read = key_read, };struct miscdevice key_miscdev = { .minor = 200, .name = "key", .fops = &key_fops, };static int button_init(void){ int ret; gpio_config = ioremap(GPGCON, 4); ret = misc_register(&key_miscdev); printk("ret = %d\n", ret); if (ret == 0) { //按键初始化 key_hw_init(); //注册中断处理程序 request_irq(IRQ_EINT8, key_int, IRQF_TRIGGER_LOW, "key1", 0); request_irq(IRQ_EINT11, key_int, IRQF_TRIGGER_LOW, "key2", 0); request_irq(IRQ_EINT13, key_int, IRQF_TRIGGER_LOW, "key3", 0); request_irq(IRQ_EINT14, key_int, IRQF_TRIGGER_LOW, "key4", 0); request_irq(IRQ_EINT15, key_int, IRQF_TRIGGER_LOW, "key5", 0); request_irq(IRQ_EINT19, key_int, IRQF_TRIGGER_LOW, "key6", 0); /* 初始化定时器 */ 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, 0); free_irq(IRQ_EINT11, 0); free_irq(IRQ_EINT13, 0); free_irq(IRQ_EINT14, 0); free_irq(IRQ_EINT15, 0); free_irq(IRQ_EINT19, 0); misc_deregister(&key_miscdev); }module_init(button_init);module_exit(button_exit);

 

转载于:https://www.cnblogs.com/wulei0630/p/9524633.html

你可能感兴趣的文章
thymeleaf学习
查看>>
Quartz Core之CALayer
查看>>
MySQL表行数查询最佳实践
查看>>
win10下安装psql9,后无法访问数据库引擎
查看>>
潭州课堂25班:Ph201805201 爬虫基础 第一课 (课堂笔记)
查看>>
mysql utf8_bin跟utf8_general_ci的区别
查看>>
linux编辑器 vi的使用
查看>>
真正可用的Asdoc生成工具及技巧和注意事项
查看>>
什么时候能相信人
查看>>
运算符和表达式
查看>>
html页面中块级元素的居中
查看>>
简练网软考知识点整理-采购工作说明书SOW
查看>>
易忘小技巧--yum
查看>>
springboot环境中,可能会出现使用font-Awesome结果图标不显示的问题,在webService的pom文件中添加如下配置代码...
查看>>
BZOJ 4567 [SCOI2016]背单词 (Trie树、贪心)
查看>>
BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)
查看>>
部署-云服务器-运维
查看>>
字符串处理的两个小技巧
查看>>
GoLand配置数据库、远程host以及远程调试
查看>>
第一周学习进度条
查看>>