Linux 中断下半部
为什么使用中断下半部?
中断执行的原则是要以最快的速度执行完,而且期间不能延时和休眠!
可是现实中,中断中可能没办法很快的处理完需要做的事,或者必须用到延时和休眠,因此引入了中断下半部。
中断中处理紧急事务,其余的交给中断下半部处理。
怎样将代码合理有效的分配给中断和中断下半部?(以后发现新的再添加)
与硬件有关的给中断处理程序(比如按键中断后判断电平),其余的给中断下半部;
紧急事务给中断处理程序,相对不紧急的给中断下半部;
不能被中断的给中断处理程序,剩余的给中断下半部;
没有延时或休眠的给中断处理程序,有休眠或延时的给中断下半部(延时只能用工作队列);
中断下半部有三种实现方法:软中断,小任务,工作队列
1、软中断---softirq
软中断一般用在内核级别的代码中,现在不讨论
2、小任务---tasklet
tasklet中不能延时或休眠
- struct tasklet_struct
- {
- struct tasklet_struct *next;
- unsigned long state; // tasklet 状态
- atomic_t count; // 锁计数器
- void (*func)(unsigned long); // tasklet 处理函数
- unsigned long data; // 传递给 tasklet 处理函数的参数
- };
// 功能:初始化 tasklet
// 参数1:被初始化的 tasklet
// 参数2:中断下半部函数入口
// 参数3:传递给中断下半部函数的参数
static inline void tasklet_init(struct tasklet_struct *tasklet, void (*func)(unsigned long), unsigned long data);
// 功能:启动下半部
// 参数:tasklet
static inline void tasklet_schedule(struct tasklet_struct *tasklet);
// 功能:释放 tasklet
// 参数: tasklet
void tasklet_kill(struct tasklet_struct *t);
- struct key_event
- {
- int name;
- int value;
- };
- struct samsung
- {
- int major;
- struct class *cls;
- struct device *dev;
- struct key_event key;
- struct tasklet_struct tasklet;
- };
- static struct samsung *key_dev;
- void tasklet_key_irq(unsigned long data)
- {
- printk("___^_^___ %s\n", __FUNCTION__);
- }
- // 中断处理程序,多个按键可以根据 irqno 区分
- irqreturn_t key_irq_handler(int irqno, void *dev_id)
- {
- int ret;
- printk("------------%s-------------\n", __FUNCTION__);
- ret = gpio_get_value(key_info[i].key_gpio);
- ret ? (key_dev->key.value = ) : (key_dev->key.value = );
- printk("key = %d status = %d\n", key_dev->key.name, key_dev->key.value);
- tasklet_schedule(&key_dev->tasklet);
- // 返回值一定要是 IRQ_HANDLED
- return IRQ_HANDLED;
- }
- static int __init key_drv_init(void)
- {
- ... ...
- key_dev->irqno = IRQ_EINT();
- ret = request_irq(key_dev->irqno, key_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "key_eint", NULL);
- tasklet_init(&key_dev->tasklet, tasklet_key_irq, );
- ... ...
- }
- static int __exit key_drv_exit(void)
- {
- ... ...
- tasklet_kill(&key_dev->tasklet);
- free_irq(key_dev->irqno,NULL);
- ... ...
- }
3、工作队列---work queue
work queue 中不能延时或休眠
// 功能:初始化work
// 参数1:被初始化的work
// 参数2:中断下半部的入口函数
INIT_WORK(_work, _func)
// 功能:启动下半部
// 参数:work
int schedule_work(struct work_struct *work);
// 功能:释放work
// 参数:work
bool cancel_work_sync(struct work_struct *work);
- struct key_event
- {
- int name;
- int value;
- };
- struct samsung
- {
- int major;
- struct class *cls;
- struct device *dev;
- struct key_event key;
- struct work_struct work;
- };
- static struct samsung *key_dev;
- void work_key_irq(struct work_struct *work)
- {
- printk("___^_^___ %s\n", __FUNCTION__);
- }
- // 中断处理程序,多个按键可以根据 irqno 区分
- irqreturn_t key_irq_handler(int irqno, void *dev_id)
- {
- int ret;
- printk("------------%s-------------\n", __FUNCTION__);
- ret = gpio_get_value(key_info[i].key_gpio);
- ret ? (key_dev->key.value = ) : (key_dev->key.value = );
- printk("key = %d status = %d\n", key_dev->key.name, key_dev->key.value);
- schedule_work(&key_dev->work);
- // 返回值一定要是 IRQ_HANDLED
- return IRQ_HANDLED;
- }
- static int __init key_drv_init(void)
- {
- ... ...
- key_dev->irqno = IRQ_EINT();
- ret = request_irq(key_dev->irqno, key_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "key_eint", NULL);
- INIT_WORK(&key_dev->work, work_key_irq);
- ... ...
- }
- static int __exit key_drv_exit(void)
- {
- ... ...
- cancel_work_sync(&key_dev->work);
- free_irq(key_dev->irqno,NULL);
- ... ...
- }
Linux 中断下半部的更多相关文章
- linux中断的上半部和下半部 【转】
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=24690947&id=3491821 一.什么是下半部 中断是一 ...
- 《Linux内核设计与实现》读书笔记(八)- 中断下半部的处理
在前一章也提到过,之所以中断会分成上下两部分,是由于中断对时限的要求非常高,需要尽快的响应硬件. 主要内容: 中断下半部处理 实现中断下半部的机制 总结中断下半部的实现 中断实现示例 1. 中断下半部 ...
- linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】
转自:https://blog.csdn.net/weixin_42471952/article/details/81609141 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协 ...
- linux中断申请之request_threaded_irq
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=21977330&id=3755609 在linux里,中断处理分 ...
- 驱动: 中断【1】linux中断流程
通常情况下,当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断总是被禁止的. 将中断处理切为两个部分或两半.中断处理程序上半部(top ...
- Linux中断子系统:级联中断控制器驱动
Linux中断子系统 Linux中断子系统是个很大的话题,如下面的思维导图所示,包含硬件.驱动.中断上半部.中断下半部等等.本文着眼于中断控制器(PIC),特别是级联中断控制器驱动部分,对驱动的设计和 ...
- Linux中断管理
CPU和外设之间的交互,或CPU通过轮询机制查询,或外设通过中断机制主动上报. 对大部分外设中断比轮询效率高,但比如网卡驱动采取轮询比中断效率高. 这里重点关注ARM+Linux组合下中断管理,从底层 ...
- Linux中断管理 (1)Linux中断管理机制
目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...
- Linux中断管理 (2)软中断和tasklet
目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...
随机推荐
- spring security采用自定义登录页和退出功能
更新... 首先采用的是XML配置方式,请先查看 初识Spring security-添加security 在之前的示例中进行代码修改 项目结构如下: 一.修改spring-security.xml ...
- dubbo学习小结
dubbo学习小结 参考: https://blog.csdn.net/paul_wei2008/article/details/19355681 https://blog.csdn.net/liwe ...
- 利用war包和Tomcat镜像创建Web镜像
from hub.c.163.com/library/tomcat:tag #代表以tomcat镜像为基础 MAINTAINER huhuixin 18611551449@163.com #代表所 ...
- Quartz(1)--框架简介
一.概述 Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间.主要用来执行定时任务,如:定时发送信息.定时生成报表等等. 二.为什么会选择Qu ...
- 简单的aop实现日志打印(切入点表达式)
Spring中可以使用注解或XML文件配置的方式实现AOP. 1.导入jar包 com.springsource.net.sf.cglib -2.2.0.jar com.springsource.or ...
- C# imgage图片转base64字符/base64字符串转图片另存成
//图片转为base64编码的字符串 protected string ImgToBase64String(string Imagefilename) { try { Bitmap bmp = new ...
- python模块及模块安装
其实python的模块及模块安装和其他编程语言,如:nodeJs.reactJs的相同,只不过他们使用包管理工具不相同而已,python用pip,而node用npm python 模块 python语 ...
- 在linux上用jmeter压测时出现很多异常java.net.NoRouteToHostException: Cannot assign requested address.
今天压力测试时, 刚开始出现了很多异常, 都是 java.net.NoRouteToHostException: Cannot assign requested address. 经网上查资料, 是由 ...
- day5-hashlib模块
一.概述 在程序开发过程中,很多时候会涉及用户信息验证环节,这类场景下我们往往需要对字符串进行加密处理.python中也有专门的加密模块,它就是hashlib.下面章节将详述它的常见用法. 二.常见加 ...
- CSS: transitions
CSS Transitions CSS transitions allows you to change property values smoothly (from one value to ano ...