阻塞型驱动设计
来源:互联网 发布:淘宝情趣内衣模特 编辑:程序博客网 时间:2024/06/03 15:33
阻塞型驱动设计
1.阻塞的必要性
当一个设备无法立刻满足用户的读写请求时应当如何处理? 例如:调用read时,设备没有数据提供, 但以后可能会有;或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据。当上述情况发生的时候,驱动程序应当(缺省地)阻塞进程,使它进入等待(睡眠)状态,直到请求可以得到满足。
A准备对B(驱动程序)读取数据,B说现在还没数据。请A先进候车室等待,B之后有了数据。B就将A唤醒。
2.内核等待队列
在实现阻塞驱动的过程中,也需要有一个“候车室”来安排被阻塞的进程“休息”,当唤醒它们的条件成熟时,则可以从“候车室”中将这些进程唤醒。而这个“候车室”就是等待队列。
1、定义等待队列
1.阻塞的必要性
当一个设备无法立刻满足用户的读写请求时应当如何处理? 例如:调用read时,设备没有数据提供, 但以后可能会有;或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据。当上述情况发生的时候,驱动程序应当(缺省地)阻塞进程,使它进入等待(睡眠)状态,直到请求可以得到满足。
A准备对B(驱动程序)读取数据,B说现在还没数据。请A先进候车室等待,B之后有了数据。B就将A唤醒。
2.内核等待队列
在实现阻塞驱动的过程中,也需要有一个“候车室”来安排被阻塞的进程“休息”,当唤醒它们的条件成熟时,则可以从“候车室”中将这些进程唤醒。而这个“候车室”就是等待队列。
1、定义等待队列
wait_queue_head_t my_queue
2、初始化等待队列
init_waitqueue_head(&my_queue);
3、定义+初始化等待队列
DECLARE_WAIT_QUEUE_HEAD(my_queue);
3.进入等待队列,睡眠
3.进入等待队列,睡眠
wait_event(queue,condition)
当condition(布尔表达式)为真时,立即返回;否则让进程进入TASK_UNINTERRUPTIBLE模式的睡眠,并挂在queue参数所指定的等待队列上。
wait_event_interruptible(queue,condition)
wait_event_interruptible(queue,condition)
当condition(布尔表达式)为真时,立即返回;否则让进程进入TASK_INTERRUPTIBLE的睡眠,并挂在queue参数所指定的等待队列上。
int wait_event_killable(queue, condition)
int wait_event_killable(queue, condition)
当condition(一个布尔表达式)为真时,立即返回;否则让进程进入TASK_KILLABLE的睡眠,并挂在queue参数所指定的等待队列上。
4.从等待队列中唤醒进程
wake_up(wait_queue_t *q)
4.从等待队列中唤醒进程
wake_up(wait_queue_t *q)
从等待队列q中唤醒状态为TASK_UNINTERRUPTIBLE,TASK_INTERRUPTIBLE,TASK_KILLABLE 的所有进程。
wake_up_interruptible(wait_queue_t *q)
从等待队列q中唤醒状态为TASK_INTERRUPTIBLE 的进程。
5.对按键程序进行改造
key.c
5.对按键程序进行改造
key.c
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/miscdevice.h>
- #include <linux/fs.h>
- #include <asm/uaccess.h>
- #include <linux/io.h>
- #include <linux/irqreturn.h>
- #include <linux/interrupt.h>
- #include <linux/uaccess.h>
- #define GPFCON (volatile unsigned long*) 0x56000050
- #define GPFDAT (volatile unsigned long*) 0x56000054
- unsigned int *gpio_data;
- struct work_struct *work1;
- struct timer_list key_timer;
- wait_queue_head_t key_q;
- unsigned int key_num = 0;
- void key_timer_func(unsigned long data)
- {
- unsigned int key_val;
- key_val = readw(gpio_data);
- if((key_val & 0x01) == 0)
- {
- key_num = 4;
- }
- else if((key_val& 0x02) == 0)
- {
- key_num = 1;
- }
- else if((key_val & 0x04) == 0)
- {
- key_num = 3;
- }
- else if((key_val & 0x10) == 0)
- {
- key_num = 2;
- }
- wake_up(&key_q); //唤醒进程
- }
- void work1_func(struct work_struct *work)
- {
- mod_timer(&key_timer, jiffies + HZ/10);
- }
- irqreturn_t key_int(int irq, void *dev_id)
- {
- //1.检测是否发生了按键中断
-
- //2.清除已经发生的按键中断
-
- //3.提交下半部
- schedule_work(work1);
- return 0;
- }
- void key_hw_init()
- {
- unsigned int *gpio_config;
- unsigned short data;
-
- gpio_config = ioremap(GPFCON, 4);
- gpio_data = ioremap(GPFDAT, 4);
- data = readw(gpio_config);
- data &= ~0x33f;
- data |= 0x22a;
- writew(data, gpio_config);
- }
- int key_open(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
- {
- wait_event(key_q, 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 = "tq2400key",
- .fops = &key_fops,
- };
- static int button_init()
- {
- int ret;
- ret = misc_register(&key_miscdev);
- if(ret != 0)
- {
- printk(KERN_ERR"misc_register failed\n");
- }
- //按键初始化
- key_hw_init();
- //注册中断处理程序
- ret = request_irq(IRQ_EINT0, &key_int, IRQF_TRIGGER_FALLING, "tq2440key", 0);
- ret = request_irq(IRQ_EINT1, &key_int, IRQF_TRIGGER_FALLING, "tq2440key", 0);
- ret = request_irq(IRQ_EINT2, &key_int, IRQF_TRIGGER_FALLING, "tq2440key", 0);
- ret = request_irq(IRQ_EINT4, &key_int, IRQF_TRIGGER_FALLING, "tq2440key", 0);
- //创建工作
- work1 = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
- INIT_WORK(work1, work1_func);
- //初始化定时器
- init_timer(&key_timer);
- key_timer.function = key_timer_func;
- //注册定时器
- add_timer(&key_timer);
- //初始化等待队列
- init_waitqueue_head(&key_q); //初始化等待队列
- return 0;
- }
- static void button_exit()
- {
- misc_deregister(&key_miscdev);
- //注销中断处理函数
- free_irq(IRQ_EINT0, 0);
- free_irq(IRQ_EINT1, 0);
- free_irq(IRQ_EINT2, 0);
- free_irq(IRQ_EINT4, 0);
- }
- module_init(button_init);
- module_exit(button_exit);
0
上一篇:中断分层和按键去抖
下一篇:总线设备驱动模型和平台设备模型
相关热门文章
- SHTML是什么_SSI有什么用...
- 查看linux中某个端口(port)...
- 卡尔曼滤波的原理说明...
- shell中字符串操作
- 关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议
阅读全文
0 0
- 阻塞型驱动设计
- 阻塞型驱动设计
- Linux阻塞型驱动设计
- 12.按键驱动程序设计(7)-阻塞型驱动设计
- 阻塞型设备驱动
- 阻塞型字符设备驱动
- 按键驱动程序设计---混杂设备、中断分层处理、工作队列、阻塞型驱动
- 一个阻塞型的小驱动
- 8、linux设备驱动--阻塞型输入输出
- 阻塞型字符设备驱动的编写
- 阻塞型字符设备驱动及例子
- 高级字符设备驱动-阻塞型字符设备驱动笔记
- Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志
- 阻塞性驱动编写
- 4412驱动-poll 阻塞
- 深入理解linux设备驱动中的阻塞型I/O与非阻塞型I/O
- Linux设备驱动一 (1)阻塞型IO及非阻塞型IO
- Linux 驱动程序笔记3--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志
- SQL 注入防御方法总结
- LED驱动程序设计
- 以太坊GAS相关知识
- 按键驱动程序设计
- 中断分层和按键去抖
- 阻塞型驱动设计
- 总线设备驱动模型和平台设备模型
- tty驱动程序架构
- 串口驱动分析-初始化
- 串口驱动分析-打开设备
- 串口驱动分析-发送
- 串口驱动分析-接收
- Qt学习之路(60): 创建shared library
- getWriter() has already been called for this response 的解决办法
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
秒分时英文字母是什么
四英文
考研英语分值
英语四级听力分值
考研英语二题型及分值
英语考级分几级
自考英语二70分技巧
考研英语分值分布
考研英语一分值
英语四级分值分布情况
四分之一英语
考研英语作文
英语二分值
英语分几级
考研英语平均分
英语选择题怎么蒙可以蒙90分
英语六级分值
考研英语60分什么水平
考研英语题型及分值
英语四级相当于高考多少分
英语六级听力分值
分英语
英语分为几个等级
英语100分
考研英语作文平均分
英语四级题型及分值
英语一分值
小学英语100分
四级英语听力分值
英语分几个等级
英语六级分值分布
英语a极考试多少分过
四级英语多少分算过
四级英语听力多少分
四分之三用英语怎么说
考研英语分
三分之二用英语怎么说
2010英语一平均分
英语四级分值分布明细
考研英语作文多少分
自考英语二技巧