为什么使用中断下半部?

中断执行的原则是要以最快的速度执行完,而且期间不能延时和休眠!

可是现实中,中断中可能没办法很快的处理完需要做的事,或者必须用到延时和休眠,因此引入了中断下半部。

中断中处理紧急事务,其余的交给中断下半部处理。

怎样将代码合理有效的分配给中断和中断下半部?(以后发现新的再添加)

与硬件有关的给中断处理程序(比如按键中断后判断电平),其余的给中断下半部;

紧急事务给中断处理程序,相对不紧急的给中断下半部;

不能被中断的给中断处理程序,剩余的给中断下半部;

没有延时或休眠的给中断处理程序,有休眠或延时的给中断下半部(延时只能用工作队列);

中断下半部有三种实现方法:软中断,小任务,工作队列

1、软中断---softirq

软中断一般用在内核级别的代码中,现在不讨论

2、小任务---tasklet

tasklet中不能延时或休眠

  1. struct tasklet_struct
  2. {
  3. struct tasklet_struct *next;
  4. unsigned long state; // tasklet 状态
  5. atomic_t count; // 锁计数器
  6. void (*func)(unsigned long); // tasklet 处理函数
  7. unsigned long data; // 传递给 tasklet 处理函数的参数
  8. };

// 功能:初始化 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);

  1. struct key_event
  2. {
  3. int name;
  4. int value;
  5. };
  6.  
  7. struct samsung
  8. {
  9. int major;
  10. struct class *cls;
  11. struct device *dev;
  12. struct key_event key;
  13. struct tasklet_struct tasklet;
  14. };
  15.  
  16. static struct samsung *key_dev;
  17.  
  18. void tasklet_key_irq(unsigned long data)
  19. {
  20. printk("___^_^___ %s\n", __FUNCTION__);
  21. }
  22.  
  23. // 中断处理程序,多个按键可以根据 irqno 区分
  24. irqreturn_t key_irq_handler(int irqno, void *dev_id)
  25. {
  26. int ret;
  27.  
  28. printk("------------%s-------------\n", __FUNCTION__);
  29.  
  30. ret = gpio_get_value(key_info[i].key_gpio);
  31. ret ? (key_dev->key.value = ) : (key_dev->key.value = );
  32. printk("key = %d status = %d\n", key_dev->key.name, key_dev->key.value);
  33.  
  34. tasklet_schedule(&key_dev->tasklet);
  35.  
  36. // 返回值一定要是 IRQ_HANDLED
  37. return IRQ_HANDLED;
  38. }
  39.  
  40. static int __init key_drv_init(void)
  41. {
  42. ... ...
  43. key_dev->irqno = IRQ_EINT();
  44. ret = request_irq(key_dev->irqno, key_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "key_eint", NULL);
  45. tasklet_init(&key_dev->tasklet, tasklet_key_irq, );
  46. ... ...
  47. }
  48.  
  49. static int __exit key_drv_exit(void)
  50. {
  51. ... ...
  52. tasklet_kill(&key_dev->tasklet);
  53. free_irq(key_dev->irqno,NULL);
  54. ... ...
  55. }

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);

  1. struct key_event
  2. {
  3. int name;
  4. int value;
  5. };
  6.  
  7. struct samsung
  8. {
  9. int major;
  10. struct class *cls;
  11. struct device *dev;
  12. struct key_event key;
  13. struct work_struct work;
  14. };
  15.  
  16. static struct samsung *key_dev;
  17.  
  18. void work_key_irq(struct work_struct *work)
  19. {
  20. printk("___^_^___ %s\n", __FUNCTION__);
  21. }
  22.  
  23. // 中断处理程序,多个按键可以根据 irqno 区分
  24. irqreturn_t key_irq_handler(int irqno, void *dev_id)
  25. {
  26. int ret;
  27.  
  28. printk("------------%s-------------\n", __FUNCTION__);
  29.  
  30. ret = gpio_get_value(key_info[i].key_gpio);
  31. ret ? (key_dev->key.value = ) : (key_dev->key.value = );
  32. printk("key = %d status = %d\n", key_dev->key.name, key_dev->key.value);
  33.  
  34. schedule_work(&key_dev->work);
  35.  
  36. // 返回值一定要是 IRQ_HANDLED
  37. return IRQ_HANDLED;
  38. }
  39.  
  40. static int __init key_drv_init(void)
  41. {
  42. ... ...
  43. key_dev->irqno = IRQ_EINT();
  44. ret = request_irq(key_dev->irqno, key_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "key_eint", NULL);
  45. INIT_WORK(&key_dev->work, work_key_irq);
  46. ... ...
  47. }
  48.  
  49. static int __exit key_drv_exit(void)
  50. {
  51. ... ...
  52. cancel_work_sync(&key_dev->work);
  53. free_irq(key_dev->irqno,NULL);
  54. ... ...
  55. }
  1.  

Linux 中断下半部的更多相关文章

  1. linux中断的上半部和下半部 【转】

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=24690947&id=3491821 一.什么是下半部 中断是一 ...

  2. 《Linux内核设计与实现》读书笔记(八)- 中断下半部的处理

    在前一章也提到过,之所以中断会分成上下两部分,是由于中断对时限的要求非常高,需要尽快的响应硬件. 主要内容: 中断下半部处理 实现中断下半部的机制 总结中断下半部的实现 中断实现示例 1. 中断下半部 ...

  3. linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】

    转自:https://blog.csdn.net/weixin_42471952/article/details/81609141 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协 ...

  4. linux中断申请之request_threaded_irq

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=21977330&id=3755609 在linux里,中断处理分 ...

  5. 驱动: 中断【1】linux中断流程

    通常情况下,当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断总是被禁止的. 将中断处理切为两个部分或两半.中断处理程序上半部(top ...

  6. Linux中断子系统:级联中断控制器驱动

    Linux中断子系统 Linux中断子系统是个很大的话题,如下面的思维导图所示,包含硬件.驱动.中断上半部.中断下半部等等.本文着眼于中断控制器(PIC),特别是级联中断控制器驱动部分,对驱动的设计和 ...

  7. Linux中断管理

    CPU和外设之间的交互,或CPU通过轮询机制查询,或外设通过中断机制主动上报. 对大部分外设中断比轮询效率高,但比如网卡驱动采取轮询比中断效率高. 这里重点关注ARM+Linux组合下中断管理,从底层 ...

  8. Linux中断管理 (1)Linux中断管理机制

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  9. Linux中断管理 (2)软中断和tasklet

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

随机推荐

  1. spring security采用自定义登录页和退出功能

    更新... 首先采用的是XML配置方式,请先查看  初识Spring security-添加security 在之前的示例中进行代码修改 项目结构如下: 一.修改spring-security.xml ...

  2. dubbo学习小结

    dubbo学习小结 参考: https://blog.csdn.net/paul_wei2008/article/details/19355681 https://blog.csdn.net/liwe ...

  3. 利用war包和Tomcat镜像创建Web镜像

      from hub.c.163.com/library/tomcat:tag #代表以tomcat镜像为基础 MAINTAINER huhuixin 18611551449@163.com #代表所 ...

  4. Quartz(1)--框架简介

    一.概述 Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间.主要用来执行定时任务,如:定时发送信息.定时生成报表等等. 二.为什么会选择Qu ...

  5. 简单的aop实现日志打印(切入点表达式)

    Spring中可以使用注解或XML文件配置的方式实现AOP. 1.导入jar包 com.springsource.net.sf.cglib -2.2.0.jar com.springsource.or ...

  6. C# imgage图片转base64字符/base64字符串转图片另存成

    //图片转为base64编码的字符串 protected string ImgToBase64String(string Imagefilename) { try { Bitmap bmp = new ...

  7. python模块及模块安装

    其实python的模块及模块安装和其他编程语言,如:nodeJs.reactJs的相同,只不过他们使用包管理工具不相同而已,python用pip,而node用npm python 模块 python语 ...

  8. 在linux上用jmeter压测时出现很多异常java.net.NoRouteToHostException: Cannot assign requested address.

    今天压力测试时, 刚开始出现了很多异常, 都是 java.net.NoRouteToHostException: Cannot assign requested address. 经网上查资料, 是由 ...

  9. day5-hashlib模块

    一.概述 在程序开发过程中,很多时候会涉及用户信息验证环节,这类场景下我们往往需要对字符串进行加密处理.python中也有专门的加密模块,它就是hashlib.下面章节将详述它的常见用法. 二.常见加 ...

  10. CSS: transitions

    CSS Transitions CSS transitions allows you to change property values smoothly (from one value to ano ...