中断(interrupt)是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回原程序被中断的位置并继续执行。

中断服务程序的执行并不存在于进程上下文,因此,要求中断服务程序的时间尽可能地短。因此,Linux在中断处理中引入了顶半部和底半部分离的机制。顶半部处理紧急的硬件操作,底半部处理不紧急的耗时操作。

tasklet和工作队列都是调度中断底半部的良好机制,tasklet基于软中断实现,原子操作,速度快,常用,但不可阻塞或睡眠。

中断分类

根据中断的来源,可分为内部中断和外部中断

内部中断的中断源来自CPU内部(软件中断指令、溢出、除法错误等,例如,操作系统从用户态切换到内核态需借助CPU内部的软件中断),外部中断的中断源来自CPU外部,由外设提出请求。

根据中断是否可以屏蔽分为可屏蔽中断与不屏蔽中断(NMI)

可屏蔽中断可以通过屏蔽字(MASK)被屏蔽,屏蔽后,该中断不再得到响应,而不屏蔽中断不能被屏蔽。

根据中断入口跳转方法的不同,分为向量中断和非向量中断

采用向量中断的CPU通常为不同的中断分配不同的中断号,当检测到某中断号的中断到来后,就自动跳转到与该中断号对应的地址执行。不同中断号的中断有不同的入口地址。非向量中断的多个中断共享一个入口地址,进入该入口地址后再通过软件判断中断标志来识别具体是哪个中断。也就是说,向量中断由硬件提供中断服务程序入口地址,非向量中断由软件提供中断服务程序入口地址。

Linux中断处理(Interrupt Handling)架构

设备的中断会打断内核中进程的正常调度和运行,系统对更高吞吐率的追求势必要求中断服务程序尽可能的短小精悍。为了在中断执行时间尽可能短和中断处理需完成大量工作之间找到一个平衡点, Linux 将中断处理程序分解为两个半部:顶半部(top half)和底半部(bottom half)。

top half

顶半部完成尽可能少的比较紧急的功能,它往往只是简单地读取寄存器中的中断状态并清除中断标志后就进行“登记中断”的工作。“登记中断”意味着将底半部处理程序挂到该设备的底半部执行队列中去。这样,顶半部执行的速度就会很快,可以服务更多的中断请求。软件上一般采用handler中断响应程序实现。

bottom half

底半部由顶半部调度而来进行延后处理,几乎做了中断处理程序所有的事情,而且可以被新的中断打断,这也是底半部和顶半部的最大不同,因为顶半部往往被设计成不可中断。底半部则相对来说并不是非常紧急的,而且相对比较耗时,不在硬件中断服务程序中执行。软件上一般采用tasklet或工作队列机制。

Tip:尽管顶半部、底半部的结合能够改善系统的响应能力,但是,僵化地认为 Linux 设备驱动中的中断处理一定要分两个半部则是不对的。如果中断要处理的工作本身很少,则完全可以直接在顶半部全部完成。

Linux中断编程

申请和释放(Installing an Interrupt Handler)

#include

int /* 返回 0 -- OK, -EINVAL -- irq/handler invalid, -EBUSY -- 中断被占用不能共享 */

request_irq(

unsigned int irq, /* 要申请的硬件中断号 */

irq_handler_t handler, /* 向系统登记的中断处理函数(顶半部)*/

unsigned long flags, /* 中断处理的属性,可以指定中断的触发方式以及处理方式等 */

const char *devname, /* used in /proc/interrupts */

void *dev_id /* 传递给handler的参数 */

);

void free_irq(unsigned int irq,void *dev_id);

Tip: 如果中断确定不被共享可将其安装在初始化中,否则应安装在打开函数中。interrupt.h有irq_handler_t的定义及flags的详细注释

使能和屏蔽 (Enabling and Disabling Interrupts)

Disabling a single interrupt

#include

/* disable并等待指定的中断被处理完,如果调用线程占有interrupt handler需要的资源如spinlock那么就会死锁 */

void disable_irq(int irq);

/* disable并立即返回,有可能产生竞态 */

void disable_irq_nosync(int irq);

void enable_irq(int irq);

Disabling all interrupts

#include

void local_irq_save(unsigned long flags); /* save flags then disable local all */

void local_irq_disable(void); /* disable local all directly */

void local_irq_restore(unsigned long flags);

void local_irq_enable(void);

底半部机制

tasklet

void my_tasklet_func(unsigned long); /*定义一个处理函数*/

/* 定义一个tasklet结构my_tasklet,并与my_tasklet_func(data)处理函数相关联 */

DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);

/* 在需要调度tasklet的时候引用一个tasklet_schedule()函数就能使系统在适当的时候进行调度运行

一般在top half即中断响应函数中调用 */

tasklet_schedule(&my_tasklet);

工作队列(workqueues)

与tasklet类似:

void my_wq_func(unsigned long); /*定义一个处理函数*/

struct work_struct my_wq; /*定义一个工作队列*/

/* 初始化工作队列并将其与处理函数绑定 */

INIT_WORK(&my_wq, (void (*)(void *)) my_wq_func, NULL);

schedule_work(&my_wq);/*调度工作队列执行*/

Tip: tasklet在中断上下文中执行,不可阻塞或睡眠;而workqueues由内核线程去执行,属进程上下文,可阻塞和睡眠。

linux设备驱动中断的步骤,Linux设备驱动之中断处理相关推荐

  1. linux 按键驱动中断 rockchip_嵌入式linux快速入门(转载)

    从上图可以知道: ① 组成:嵌入式Linux系统 = bootloader + linux内核 + 根文件系统(里面含有APP). ② bootloader:它的目的是启动内核,去哪读内核?读到哪里? ...

  2. ARM GIC 与Linux kernel的中断子系统(4)GIC和中断处理

    1.GIC GIC,Generic Interrupt Controller.是ARM公司提供的一个通用的中断控制器.主要作用为:接受硬件中断信号,并经过一定处理后,分发给对应的CPU进行处理. GI ...

  3. linux下文件怎么改名字,Linux文件名字批量修改步骤 Linux修改文件名的方法

    在Linux环境下修改文件名可以有不同的命令方式,比如rename.mv都可以进行修改,如果用户正在了解这方面的知识,可以阅读下文了解Linux修改文件名以及批量修改文件名的方法. 对于单个的文件,可 ...

  4. zynq linux多个中断注册,zynq linux 中断号如何对应

    在linux系统下,中断号跟BD中zynq7000 processer中配置的生成的中断号不是直接对应的,中间有一个"-32" 的关系,如下 For Shared Peripera ...

  5. linux设置组配置额步骤,linux 中磁盘配额设置

    linux 中磁盘配额设置 在一些linux文件服务器中需要限制某个用户的磁盘用量,防止磁盘爆满 1)首先设置磁盘某个分区需要是一个文件系统 需要在这个区添加用户和组 比如说/dev/sdb1分区 建 ...

  6. linux telnet远程登录的步骤,Linux如何远程登录telnet和ssh

    通常情况下在Linux系统中远程登录我们使用telnet服务,Red Hat Linux自带的有telnet服务器的软件包,我们需要安装telnet-server和xinetd两个软件包: [root ...

  7. linux搭建ldap服务器详细步骤,linux环境搭建ldap服务器

    首先保证linux正常联网 yum install openldap-servers -y 拷贝配置文件 cd /usr/share/openldap-servers/ cp slapd.conf.o ...

  8. linux下安装pg数据库步骤,Linux下安装PG

    安装包下载地址 最好下载编译好的二进制安装包,直接解压就可以使用 1. 添加postgres用户: groupadd postgres useradd -d /home/postgres -m pos ...

  9. linux内核看门狗关闭方法,linux内核中断之看门狗

    一:内核中断 linux内核中的看门狗中断跟之前的裸板的中断差不多,在编写驱动之前,需要线把内核自带的watch dog模块裁剪掉,要不然会出现错误:在Device Drivers /Watchdog ...

最新文章

  1. xdoj 1114(线段树离线处理)
  2. 三层交换不同VLAN间通信
  3. C 语言编程 — 静态库、动态库和共享库
  4. 阅读源码技术与艺术五
  5. python字典导入mongodb_python连接mongoDB进行数据提取→常用操作指南
  6. rabbitmq topic 收不到数据_RabbitMQ和Kafka到底怎么选?
  7. 创建war类型的maven工程时报web.xml is missing and failOnMissingWebXml is set to true
  8. 中国移动将于11月4日首发上会 拟募资560亿元
  9. 高性能访客记录系统如何设计?
  10. Java线程池的学习记录
  11. 软考中级-软件设计师|下午题攻略
  12. matlab多行注释方法
  13. 主板风扇转不开机是什么问题_cpu风扇转主板不启动怎么办
  14. walking机器人仿真教程-应用-多点导航结合摄像头实现在线查房
  15. python免费的实时语音交互(讯飞语音识别+青云客Robot)
  16. Python免安装环境(Windows)
  17. ai替换混合轴例子_可解释的vs可解释的AI:一个直观的例子
  18. 硕士研究生期间,必须了解的一些科研工具
  19. 标称型数据和数值型数据
  20. Vue中slot的使用(具名插槽与作用域插槽)

热门文章

  1. c 语言调用java_C语言调用java的方法
  2. 关于非编系统的组成,作用和发展!
  3. 在不确定的时代,用理性的思考去对抗群体的疯狂
  4. Java递归遍历文件夹
  5. php 打印数组 还原,PHP 重新格式化var_dump/print_r打印的数组
  6. RS485三线制和两线制差别
  7. ide怎么设置方法中间加一道横线_像IDE那样使用VIM(快速入门版)
  8. Linux Command du 查看文件大小
  9. 前端预览word文档实现
  10. 鲸鱼剧本杀盒子刷机a905x3刷机